From 14f7f6c764f605095c6c96a48218da83d365119d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gutie=CC=81rrez=20Palma?= Date: Tue, 15 Jul 2014 11:36:35 +0200 Subject: [PATCH] Initial commit --- .gitignore | 10 + License.txt | 31 + src/Assets/UnityTestTools.meta | 5 + src/Assets/UnityTestTools/Assertions.meta | 5 + .../Assertions/AssertionComponent.cs | 372 + .../Assertions/AssertionComponent.cs.meta | 8 + .../Assertions/AssertionException.cs | 22 + .../Assertions/AssertionException.cs.meta | 8 + .../UnityTestTools/Assertions/Assertions.cs | 40 + .../Assertions/Assertions.cs.meta | 8 + .../UnityTestTools/Assertions/CheckMethod.cs | 32 + .../Assertions/CheckMethod.cs.meta | 8 + .../UnityTestTools/Assertions/Comparers.meta | 5 + .../Assertions/Comparers/ActionBase.cs | 119 + .../Assertions/Comparers/ActionBase.cs.meta | 8 + .../Assertions/Comparers/BoolComparer.cs | 10 + .../Assertions/Comparers/BoolComparer.cs.meta | 8 + .../Assertions/Comparers/ColliderComparer.cs | 28 + .../Comparers/ColliderComparer.cs.meta | 8 + .../Assertions/Comparers/ComparerBase.cs | 144 + .../Assertions/Comparers/ComparerBase.cs.meta | 8 + .../Assertions/Comparers/FloatComparer.cs | 38 + .../Comparers/FloatComparer.cs.meta | 8 + .../Assertions/Comparers/GeneralComparer.cs | 20 + .../Comparers/GeneralComparer.cs.meta | 8 + .../Assertions/Comparers/IntComparer.cs | 39 + .../Assertions/Comparers/IntComparer.cs.meta | 8 + .../Comparers/IsRenderedByCamera.cs | 30 + .../Comparers/IsRenderedByCamera.cs.meta | 8 + .../Assertions/Comparers/StringComparer.cs | 40 + .../Comparers/StringComparer.cs.meta | 8 + .../Assertions/Comparers/TransformComparer.cs | 25 + .../Comparers/TransformComparer.cs.meta | 8 + .../Comparers/ValueDoesNotChange.cs | 16 + .../Comparers/ValueDoesNotChange.cs.meta | 8 + .../Assertions/Comparers/Vector2Comparer.cs | 35 + .../Comparers/Vector2Comparer.cs.meta | 8 + .../Assertions/Comparers/Vector3Comparer.cs | 31 + .../Comparers/Vector3Comparer.cs.meta | 8 + .../Assertions/Comparers/Vector4Comparer.cs | 37 + .../Comparers/Vector4Comparer.cs.meta | 8 + .../Comparers/VectorComparerBase.cs | 16 + .../Comparers/VectorComparerBase.cs.meta | 8 + .../UnityTestTools/Assertions/Editor.meta | 5 + .../Editor/AssertionComponentEditor.cs | 217 + .../Editor/AssertionComponentEditor.cs.meta | 8 + .../Editor/AssertionExplorerWindow.cs | 192 + .../Editor/AssertionExplorerWindow.cs.meta | 8 + .../Editor/AssertionListRenderer.cs | 255 + .../Editor/AssertionListRenderer.cs.meta | 8 + .../Assertions/Editor/AssertionStripper.cs | 22 + .../Editor/AssertionStripper.cs.meta | 8 + .../Assertions/Editor/DropDownControl.cs | 77 + .../Assertions/Editor/DropDownControl.cs.meta | 8 + .../Editor/GroupByComparerRenderer.cs | 19 + .../Editor/GroupByComparerRenderer.cs.meta | 8 + .../Editor/GroupByExecutionMethodRenderer.cs | 30 + .../GroupByExecutionMethodRenderer.cs.meta | 8 + .../Assertions/Editor/GroupByGORenderer.cs | 33 + .../Editor/GroupByGORenderer.cs.meta | 8 + .../Editor/GroupByNothingRenderer.cs | 18 + .../Editor/GroupByNothingRenderer.cs.meta | 8 + .../Assertions/Editor/GroupByTestsRenderer.cs | 28 + .../Editor/GroupByTestsRenderer.cs.meta | 8 + .../Assertions/Editor/PropertyPathSelector.cs | 211 + .../Editor/PropertyPathSelector.cs.meta | 8 + .../Assertions/Editor/PropertyResolver.cs | 188 + .../Editor/PropertyResolver.cs.meta | 8 + .../Assertions/InvalidPathException.cs | 12 + .../Assertions/InvalidPathException.cs.meta | 8 + .../Assertions/MemberResolver.cs | 217 + .../Assertions/MemberResolver.cs.meta | 8 + src/Assets/UnityTestTools/Common.meta | 5 + src/Assets/UnityTestTools/Common/Editor.meta | 5 + .../UnityTestTools/Common/Editor/Icons.cs | 74 + .../Common/Editor/Icons.cs.meta | 8 + .../UnityTestTools/Common/Editor/Styles.cs | 47 + .../Common/Editor/Styles.cs.meta | 8 + .../UnityTestTools/Common/Editor/icons.meta | 5 + .../Common/Editor/icons/create-darktheme.png | Bin 0 -> 1520 bytes .../Editor/icons/create-darktheme.png.meta | 46 + .../Common/Editor/icons/create-lighttheme.png | Bin 0 -> 1520 bytes .../Editor/icons/create-lighttheme.png.meta | 46 + .../Common/Editor/icons/failed.png | Bin 0 -> 1041 bytes .../Common/Editor/icons/failed.png.meta | 46 + .../Common/Editor/icons/ignored.png | Bin 0 -> 1041 bytes .../Common/Editor/icons/ignored.png.meta | 46 + .../Common/Editor/icons/inconclusive.png | Bin 0 -> 1041 bytes .../Common/Editor/icons/inconclusive.png.meta | 46 + .../Common/Editor/icons/normal.png | Bin 0 -> 1041 bytes .../Common/Editor/icons/normal.png.meta | 46 + .../Common/Editor/icons/options-darktheme.png | Bin 0 -> 2171 bytes .../Editor/icons/options-darktheme.png.meta | 46 + .../Editor/icons/options-lighttheme.png | Bin 0 -> 2161 bytes .../Editor/icons/options-lighttheme.png.meta | 46 + .../Common/Editor/icons/passed.png | Bin 0 -> 1041 bytes .../Common/Editor/icons/passed.png.meta | 46 + .../Common/Editor/icons/play-darktheme.png | Bin 0 -> 2002 bytes .../Editor/icons/play-darktheme.png.meta | 46 + .../Common/Editor/icons/play-lighttheme.png | Bin 0 -> 2004 bytes .../Editor/icons/play-lighttheme.png.meta | 46 + .../Editor/icons/play_selected-darktheme.png | Bin 0 -> 1657 bytes .../icons/play_selected-darktheme.png.meta | 46 + .../Editor/icons/play_selected-lighttheme.png | Bin 0 -> 1649 bytes .../icons/play_selected-lighttheme.png.meta | 46 + .../Common/Editor/icons/rerun-darktheme.png | Bin 0 -> 1767 bytes .../Editor/icons/rerun-darktheme.png.meta | 46 + .../Common/Editor/icons/rerun-lighttheme.png | Bin 0 -> 1748 bytes .../Editor/icons/rerun-lighttheme.png.meta | 46 + .../Common/Editor/icons/stopwatch.png | Bin 0 -> 1041 bytes .../Common/Editor/icons/stopwatch.png.meta | 46 + .../UnityTestTools/Common/ITestResult.cs | 14 + .../UnityTestTools/Common/ITestResult.cs.meta | 8 + .../UnityTestTools/Common/ResultWriter.meta | 5 + .../Common/ResultWriter/ResultSummarizer.cs | 160 + .../ResultWriter/ResultSummarizer.cs.meta | 8 + .../Common/ResultWriter/StackTraceFilter.cs | 61 + .../ResultWriter/StackTraceFilter.cs.meta | 8 + .../Common/ResultWriter/XmlResultWriter.cs | 333 + .../ResultWriter/XmlResultWriter.cs.meta | 8 + .../UnityTestTools/Common/TestResultState.cs | 42 + .../Common/TestResultState.cs.meta | 8 + src/Assets/UnityTestTools/Docs.meta | 5 + .../UnityTestTools/Docs/UnityTestTools-en.pdf | Bin 0 -> 474685 bytes .../Docs/UnityTestTools-en.pdf.meta | 4 + .../UnityTestTools/Docs/UnityTestTools-ja.pdf | Bin 0 -> 893461 bytes .../Docs/UnityTestTools-ja.pdf.meta | 4 + .../IntegrationTestsFramework.meta | 5 + .../IntegrationTestsFramework/TestRunner.meta | 5 + .../TestRunner/Editor.meta | 5 + .../TestRunner/Editor/Batch.cs | 96 + .../TestRunner/Editor/Batch.cs.meta | 8 + .../Editor/IntegrationTestsRunnerWindow.cs | 612 + .../IntegrationTestsRunnerWindow.cs.meta | 8 + .../TestRunner/Editor/PlatformRunner.meta | 5 + .../Editor/PlatformRunner/PlatformRunner.cs | 147 + .../PlatformRunner/PlatformRunner.cs.meta | 8 + .../PlatformRunnerSettingsWindow.cs | 105 + .../PlatformRunnerSettingsWindow.cs.meta | 8 + .../TestRunner/Editor/Renderer.meta | 5 + .../Renderer/IntegrationTestGroupLine.cs | 87 + .../Renderer/IntegrationTestGroupLine.cs.meta | 8 + .../Editor/Renderer/IntegrationTestLine.cs | 57 + .../Renderer/IntegrationTestLine.cs.meta | 8 + .../Renderer/IntegrationTestRendererBase.cs | 146 + .../IntegrationTestRendererBase.cs.meta | 8 + .../TestRunner/Editor/TestComponentEditor.cs | 119 + .../Editor/TestComponentEditor.cs.meta | 8 + .../TestRunner/ITestRunnerCallback.cs | 13 + .../TestRunner/ITestRunnerCallback.cs.meta | 8 + .../TestRunner/IntegrationTest.cs | 141 + .../TestRunner/IntegrationTest.cs.meta | 8 + .../TestRunner/IntegrationTestAttribute.cs | 23 + .../IntegrationTestAttribute.cs.meta | 8 + .../TestRunner/IntegrationTestsProvider.cs | 112 + .../IntegrationTestsProvider.cs.meta | 8 + .../TestRunner/TestComponent.cs | 370 + .../TestRunner/TestComponent.cs.meta | 8 + .../TestRunner/TestResult.cs | 141 + .../TestRunner/TestResult.cs.meta | 8 + .../TestRunner/TestResultRenderer.cs | 75 + .../TestRunner/TestResultRenderer.cs.meta | 8 + .../TestRunner/TestRunner.cs | 446 + .../TestRunner/TestRunner.cs.meta | 8 + .../TestRunner/TestRunnerCallbackList.cs | 60 + .../TestRunner/TestRunnerCallbackList.cs.meta | 8 + .../TestingAssets.meta | 5 + .../TestingAssets/CallTesting.cs | 206 + .../TestingAssets/CallTesting.cs.meta | 8 + .../TestingAssets/CubeCollisionFailure.prefab | Bin 0 -> 9336 bytes .../CubeCollisionFailure.prefab.meta | 4 + .../TestingAssets/CubeCollisionSuccess.prefab | Bin 0 -> 9336 bytes .../CubeCollisionSuccess.prefab.meta | 4 + .../TestingAssets/CubeTriggerFailure.prefab | Bin 0 -> 9336 bytes .../CubeTriggerFailure.prefab.meta | 4 + .../TestingAssets/CubeTriggerSuccess.prefab | Bin 0 -> 9336 bytes .../CubeTriggerSuccess.prefab.meta | 4 + .../TestingAssets/Materials.meta | 5 + .../TestingAssets/Materials/green.mat | Bin 0 -> 4212 bytes .../TestingAssets/Materials/green.mat.meta | 4 + .../TestingAssets/Materials/red.mat | Bin 0 -> 4208 bytes .../TestingAssets/Materials/red.mat.meta | 4 + .../TestingAssets/green.png | Bin 0 -> 140 bytes .../TestingAssets/green.png.meta | 46 + .../TestingAssets/red.png | Bin 0 -> 139 bytes .../TestingAssets/red.png.meta | 46 + src/Assets/UnityTestTools/LICENSE.txt | 83 + src/Assets/UnityTestTools/LICENSE.txt.meta | 4 + src/Assets/UnityTestTools/UnitTesting.meta | 5 + .../UnityTestTools/UnitTesting/Editor.meta | 5 + .../UnitTesting/Editor/Batch.cs | 88 + .../UnitTesting/Editor/Batch.cs.meta | 8 + .../UnitTesting/Editor/NSubstitute.meta | 5 + .../Editor/NSubstitute/NSubstitute.dll | Bin 0 -> 327680 bytes .../Editor/NSubstitute/NSubstitute.dll.meta | 7 + .../UnitTesting/Editor/NUnit.meta | 5 + .../UnitTesting/Editor/NUnit/Libs.meta | 5 + .../Editor/NUnit/Libs/Mono.Cecil.Mdb.dll | Bin 0 -> 39424 bytes .../Editor/NUnit/Libs/Mono.Cecil.Mdb.dll.meta | 7 + .../Editor/NUnit/Libs/Mono.Cecil.dll | Bin 0 -> 280576 bytes .../Editor/NUnit/Libs/Mono.Cecil.dll.meta | 7 + .../Editor/NUnit/Libs/nunit.core.dll | Bin 0 -> 139264 bytes .../Editor/NUnit/Libs/nunit.core.dll.meta | 7 + .../NUnit/Libs/nunit.core.interfaces.dll | Bin 0 -> 53248 bytes .../NUnit/Libs/nunit.core.interfaces.dll.meta | 7 + .../Editor/NUnit/Libs/nunit.framework.dll | Bin 0 -> 131072 bytes .../NUnit/Libs/nunit.framework.dll.meta | 7 + .../UnitTesting/Editor/NUnit/Renderer.meta | 5 + .../Editor/NUnit/Renderer/GroupLine.cs | 155 + .../Editor/NUnit/Renderer/GroupLine.cs.meta | 8 + .../Editor/NUnit/Renderer/RenderingOptions.cs | 12 + .../NUnit/Renderer/RenderingOptions.cs.meta | 8 + .../Editor/NUnit/Renderer/TestLine.cs | 167 + .../Editor/NUnit/Renderer/TestLine.cs.meta | 8 + .../NUnit/Renderer/UnitTestRendererLine.cs | 93 + .../Renderer/UnitTestRendererLine.cs.meta | 8 + .../UnitTesting/Editor/TestRunner.meta | 5 + .../Editor/TestRunner/BackgroundRunner.cs | 65 + .../TestRunner/BackgroundRunner.cs.meta | 8 + .../Editor/TestRunner/GuiHelper.cs | 162 + .../Editor/TestRunner/GuiHelper.cs.meta | 8 + .../Editor/TestRunner/ITestRunnerCallback.cs | 13 + .../TestRunner/ITestRunnerCallback.cs.meta | 8 + .../Editor/TestRunner/IUnitTestEngine.cs | 8 + .../Editor/TestRunner/IUnitTestEngine.cs.meta | 8 + .../Editor/TestRunner/NUnitExtensions.cs | 20 + .../Editor/TestRunner/NUnitExtensions.cs.meta | 8 + .../Editor/TestRunner/NUnitTestEngine.cs | 197 + .../Editor/TestRunner/NUnitTestEngine.cs.meta | 8 + .../Editor/TestRunner/TestRunner.cs | 158 + .../Editor/TestRunner/TestRunner.cs.meta | 8 + .../TestRunner/TestRunnerCallbackList.cs | 61 + .../TestRunner/TestRunnerCallbackList.cs.meta | 8 + .../Editor/TestRunner/UnitTestInfo.cs | 97 + .../Editor/TestRunner/UnitTestInfo.cs.meta | 8 + .../Editor/TestRunner/UnitTestResult.cs | 60 + .../Editor/TestRunner/UnitTestResult.cs.meta | 8 + .../Editor/TestRunner/UnitTestView.cs | 320 + .../Editor/TestRunner/UnitTestView.cs.meta | 8 + .../UnitTesting/Editor/UnityUnitTest.cs | 26 + .../UnitTesting/Editor/UnityUnitTest.cs.meta | 8 + src/Assets/UnityTestTools/changelog.txt | 109 + src/Assets/UnityTestTools/changelog.txt.meta | 4 + src/Assets/quickgraph4unity.meta | 5 + src/Assets/quickgraph4unity/Editor.meta | 5 + src/Assets/quickgraph4unity/Editor/Tests.meta | 5 + .../Editor/Tests/QuickGraph.Tests.meta | 5 + .../QuickGraph.Tests/AdjacencyGraphFactory.cs | 150 + .../AdjacencyGraphFactory.cs.meta | 8 + .../Tests/QuickGraph.Tests/Algorithms.meta | 5 + .../CentralityApproximationAlgorithmTest.cs | 10 + ...ntralityApproximationAlgorithmTest.cs.meta | 8 + .../Algorithms/Condensation.meta | 5 + ...ConnectedCondensationGraphAlgorithmTest.cs | 95 + ...ctedCondensationGraphAlgorithmTest.cs.meta | 8 + .../WeaklyConnectedCondensationGraphTest.cs | 70 + ...aklyConnectedCondensationGraphTest.cs.meta | 8 + .../Algorithms/DoubleDenseMatrixFactory.cs | 41 + .../DoubleDenseMatrixFactory.cs.meta | 8 + .../Algorithms/DoubleDenseMatrixTest.cs | 34 + .../Algorithms/DoubleDenseMatrixTest.cs.meta | 8 + .../Algorithms/EulerianTrailAlgorithmTest.cs | 55 + .../EulerianTrailAlgorithmTest.cs.meta | 8 + .../Algorithms/MaximumFlow.meta | 5 + .../AllVerticesGraphAugmentorAlgorithmTest.cs | 96 + ...erticesGraphAugmentorAlgorithmTest.cs.meta | 8 + .../Algorithms/MinimumSpanningTree.meta | 5 + .../PrimMinimumSpanningTreeAlgorithmTest.cs | 34 + ...imMinimumSpanningTreeAlgorithmTest.cs.meta | 8 + .../Algorithms/RandomWalks.meta | 5 + .../CyclePoppingRandomTreeAlgorithmTest.cs | 42 + ...yclePoppingRandomTreeAlgorithmTest.cs.meta | 8 + .../RandomWalks/EdgeChainFactory.cs | 67 + .../RandomWalks/EdgeChainFactory.cs.meta | 8 + .../Algorithms/RandomWalks/EdgeChainTest.cs | 39 + .../RandomWalks/EdgeChainTest.cs.meta | 8 + .../RandomWalks/RandomWalkAlgorithmTest.cs | 46 + .../RandomWalkAlgorithmTest.cs.meta | 8 + .../QuickGraph.Tests/Algorithms/Search.meta | 5 + ...irectionalDepthFirstSearchAlgorithmTest.cs | 32 + ...ionalDepthFirstSearchAlgorithmTest.cs.meta | 8 + .../Search/BreadthFirstSearchAlgirthmTest.cs | 208 + .../BreadthFirstSearchAlgirthmTest.cs.meta | 8 + .../Search/DepthFirstSearchAlgorithmTest.cs | 169 + .../DepthFirstSearchAlgorithmTest.cs.meta | 8 + .../Search/SearchingExamplesTest.cs | 28 + .../Search/SearchingExamplesTest.cs.meta | 8 + ...ndirectedBreathFirstSearchAlgorithmTest.cs | 229 + ...ctedBreathFirstSearchAlgorithmTest.cs.meta | 8 + .../Algorithms/ShortestPath.meta | 5 + .../DagShortestPathAlgorithmTest.cs | 116 + .../DagShortestPathAlgorithmTest.cs.meta | 8 + .../DijkstraShortestPathAlgorithmTest.cs | 271 + .../DijkstraShortestPathAlgorithmTest.cs.meta | 8 + .../DijkstraShortestPathAlgorithmTest2.cs | 50 + ...DijkstraShortestPathAlgorithmTest2.cs.meta | 8 + ...SourceFirstTopologicalSortAlgorithmTest.cs | 25 + ...eFirstTopologicalSortAlgorithmTest.cs.meta | 8 + ...tronglyConnectedComponentsAlgorithmTest.cs | 141 + ...lyConnectedComponentsAlgorithmTest.cs.meta | 8 + .../TopologicalSortAlgorithmTest.cs | 30 + .../TopologicalSortAlgorithmTest.cs.meta | 8 + ...rectedFirstTopologicalSortAlgorithmTest.cs | 31 + ...dFirstTopologicalSortAlgorithmTest.cs.meta | 8 + .../UndirectedTopologicalSortAlgorithmTest.cs | 29 + ...rectedTopologicalSortAlgorithmTest.cs.meta | 8 + .../WeaklyConnectedComponentsAlgorithmTest.cs | 40 + ...lyConnectedComponentsAlgorithmTest.cs.meta | 8 + .../BidirectionalGraphFactory.cs | 82 + .../BidirectionalGraphFactory.cs.meta | 8 + .../BidirectionalMatrixGraphFactory.cs | 60 + .../BidirectionalMatrixGraphFactory.cs.meta | 8 + .../Tests/QuickGraph.Tests/Collections.meta | 5 + ...atorTest.CurrentAfterMoveNextFinished.g.cs | Bin 0 -> 2842 bytes ...est.CurrentAfterMoveNextFinished.g.cs.meta | 8 + ...eEnumeratorTest.CurrentBeforeMoveNext.g.cs | Bin 0 -> 2786 bytes ...eratorTest.CurrentBeforeMoveNext.g.cs.meta | 8 + ...meratorTest.InsertAndCurrentAndModify.g.cs | Bin 0 -> 2818 bytes ...orTest.InsertAndCurrentAndModify.g.cs.meta | 8 + ...eratorTest.InsertAndMoveNextAndModify.g.cs | Bin 0 -> 2826 bytes ...rTest.InsertAndMoveNextAndModify.g.cs.meta | 8 + ...numeratorTest.InsertAndResetAndModify.g.cs | Bin 0 -> 2802 bytes ...atorTest.InsertAndResetAndModify.g.cs.meta | 8 + ...eratorTest.InsertManyAndDoubleForEach.g.cs | Bin 0 -> 8154 bytes ...rTest.InsertManyAndDoubleForEach.g.cs.meta | 8 + ...torTest.InsertManyAndEnumerateUntyped.g.cs | Bin 0 -> 7352 bytes ...st.InsertManyAndEnumerateUntyped.g.cs.meta | 8 + ...torTest.InsertManyAndMoveNextAndReset.g.cs | Bin 0 -> 8236 bytes ...st.InsertManyAndMoveNextAndReset.g.cs.meta | 8 + ...ryHeapTPriorityTValueTest.Constructor.g.cs | Bin 0 -> 1974 bytes ...pTPriorityTValueTest.Constructor.g.cs.meta | 8 + .../BinaryHeapTPriorityTValueTest.Insert.g.cs | Bin 0 -> 8288 bytes ...ryHeapTPriorityTValueTest.Insert.g.cs.meta | 8 + ...PriorityTValueTest.InsertAndEnumerate.g.cs | Bin 0 -> 7870 bytes ...ityTValueTest.InsertAndEnumerate.g.cs.meta | 8 + ...pTPriorityTValueTest.InsertAndIndexOf.g.cs | Bin 0 -> 8270 bytes ...orityTValueTest.InsertAndIndexOf.g.cs.meta | 8 + ...pTPriorityTValueTest.InsertAndMinimum.g.cs | Bin 0 -> 12224 bytes ...orityTValueTest.InsertAndMinimum.g.cs.meta | 8 + ...TPriorityTValueTest.InsertAndRemoveAt.g.cs | Bin 0 -> 11126 bytes ...rityTValueTest.InsertAndRemoveAt.g.cs.meta | 8 + ...iorityTValueTest.InsertAndRemoveAtAll.g.cs | Bin 0 -> 1974 bytes ...yTValueTest.InsertAndRemoveAtAll.g.cs.meta | 8 + ...rityTValueTest.InsertAndRemoveMinimum.g.cs | Bin 0 -> 20356 bytes ...ValueTest.InsertAndRemoveMinimum.g.cs.meta | 8 + .../Collections/BinaryHeapTest.cs | 312 + .../Collections/BinaryHeapTest.cs.meta | 8 + .../Tests/QuickGraph.Tests/DegreeTest.cs | 47 + .../Tests/QuickGraph.Tests/DegreeTest.cs.meta | 8 + .../QuickGraph.Tests/EdgeListGraphFactory.cs | 52 + .../EdgeListGraphFactory.cs.meta | 8 + .../EdgeListGraphInvariant.cs | 35 + .../EdgeListGraphInvariant.cs.meta | 8 + .../QuickGraph.Tests/FactoryCompilerTest.cs | 78 + .../FactoryCompilerTest.cs.meta | 8 + .../GraphConsoleSerializer.cs | 16 + .../GraphConsoleSerializer.cs.meta | 8 + .../Tests/QuickGraph.Tests/GraphFactory.cs | 195 + .../QuickGraph.Tests/GraphFactory.cs.meta | 8 + .../Editor/Tests/QuickGraph.Tests/Heap.meta | 5 + .../Tests/QuickGraph.Tests/Heap/HeapTest.cs | 52 + .../QuickGraph.Tests/Heap/HeapTest.cs.meta | 8 + .../Tests/QuickGraph.Tests/Heap/gcheap.xml | 207636 +++++++++++++++ .../QuickGraph.Tests/Heap/gcheap.xml.meta | 4 + .../MutableVertexAndEdgeListGraphTest.cs | 98 + .../MutableVertexAndEdgeListGraphTest.cs.meta | 8 + .../Editor/Tests/QuickGraph.Tests/Program.cs | 15 + .../Tests/QuickGraph.Tests/Program.cs.meta | 8 + .../Tests/QuickGraph.Tests/Properties.meta | 5 + .../Properties/AssemblyInfo.cs | 23 + .../Properties/AssemblyInfo.cs.meta | 8 + .../Properties/PexAssemblyInfo.cs | 18 + .../Properties/PexAssemblyInfo.cs.meta | 8 + .../QuickGraph.Tests/QuickGraph.Tests.csproj | 193 + .../QuickGraph.Tests.csproj.meta | 4 + .../QuickGraph.Tests.csproj.vspscc | 10 + .../QuickGraph.Tests.csproj.vspscc.meta | 4 + .../Tests/QuickGraph.Tests/Regression.meta | 5 + .../Regression/DijkstraTest.cs | 127 + .../Regression/DijkstraTest.cs.meta | 8 + .../ReversedBidirectionalGraphTest.cs | 12 + .../ReversedBidirectionalGraphTest.cs.meta | 8 + .../Tests/QuickGraph.Tests/Serialization.meta | 5 + .../Serialization/GraphMLSerializerTest.cs | 63 + .../GraphMLSerializerTest.cs.meta | 8 + .../GraphMLSerializerWithArgumentsTest.cs | 237 + ...GraphMLSerializerWithArgumentsTest.cs.meta | 8 + .../UndirectedGraphFactory.cs | 72 + .../UndirectedGraphFactory.cs.meta | 8 + .../UndirectedGraphInvariant.cs | 22 + .../UndirectedGraphInvariant.cs.meta | 8 + .../VertexListGraphInvariant.cs | 20 + .../VertexListGraphInvariant.cs.meta | 8 + .../Tests/QuickGraph.Tests/testframework.cs | 2055 + .../QuickGraph.Tests/testframework.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit.meta | 5 + .../AssemblySetUpAndTearDownAttribute.cs | 24 + .../AssemblySetUpAndTearDownAttribute.cs.meta | 8 + .../QuickGraph.Unit/AssemblySetUpAttribute.cs | 8 + .../AssemblySetUpAttribute.cs.meta | 8 + .../AssemblyTearDownAttribute.cs | 8 + .../AssemblyTearDownAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Assert.cs | 435 + .../Tests/QuickGraph.Unit/Assert.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Assume.cs | 20 + .../Tests/QuickGraph.Unit/Assume.cs.meta | 8 + .../Tests/QuickGraph.Unit/CollectionAssert.cs | 153 + .../QuickGraph.Unit/CollectionAssert.cs.meta | 8 + .../CombinatorialTestAttribute.cs | 137 + .../CombinatorialTestAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/CommandLine.meta | 5 + .../CommandLine/ArgumentAttribute.cs | 49 + .../CommandLine/ArgumentAttribute.cs.meta | 8 + .../CommandLine/ArgumentParserBase.cs | 154 + .../CommandLine/ArgumentParserBase.cs.meta | 8 + .../CommandLine/ArgumentParserCollection.cs | 79 + .../ArgumentParserCollection.cs.meta | 8 + .../CommandLine/ArgumentParserFactory.cs | 91 + .../CommandLine/ArgumentParserFactory.cs.meta | 8 + .../CommandLine/ArgumentsBase.cs | 19 + .../CommandLine/ArgumentsBase.cs.meta | 8 + .../CommandLine/BoolArgumentParser.cs | 53 + .../CommandLine/BoolArgumentParser.cs.meta | 8 + .../CommandLine/CommandLineParser.cs | 144 + .../CommandLine/CommandLineParser.cs.meta | 8 + .../QuickGraph.Unit/CommandLine/ConsoleLog.cs | 97 + .../CommandLine/ConsoleLog.cs.meta | 8 + .../CommandLine/DateTimeArgumentParser.cs | 24 + .../DateTimeArgumentParser.cs.meta | 8 + .../CommandLine/DefaultArgumentAttribute.cs | 18 + .../DefaultArgumentAttribute.cs.meta | 8 + .../CommandLine/EnumArgumentParser.cs | 44 + .../CommandLine/EnumArgumentParser.cs.meta | 8 + .../CommandLine/FieldMember.cs | 39 + .../CommandLine/FieldMember.cs.meta | 8 + .../CommandLine/FloatArgumentParser.cs | 24 + .../CommandLine/FloatArgumentParser.cs.meta | 8 + .../CommandLine/IArgumentParser.cs | 18 + .../CommandLine/IArgumentParser.cs.meta | 8 + .../QuickGraph.Unit/CommandLine/IMember.cs | 15 + .../CommandLine/IMember.cs.meta | 8 + .../CommandLine/IntArgumentParser.cs | 24 + .../CommandLine/IntArgumentParser.cs.meta | 8 + .../CommandLine/LongArgumentParser.cs | 24 + .../CommandLine/LongArgumentParser.cs.meta | 8 + .../CommandLine/PropertyMember.cs | 40 + .../CommandLine/PropertyMember.cs.meta | 8 + .../CommandLine/StringArgumentParser.cs | 25 + .../CommandLine/StringArgumentParser.cs.meta | 8 + .../Tests/QuickGraph.Unit/CompilerAssert.cs | 365 + .../QuickGraph.Unit/CompilerAssert.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Core.meta | 5 + .../Tests/QuickGraph.Unit/Core/BadFixture.cs | 56 + .../QuickGraph.Unit/Core/BadFixture.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/BadTestCase.cs | 56 + .../QuickGraph.Unit/Core/BadTestCase.cs.meta | 8 + .../Core/DataProviderAttributeBase.cs | 16 + .../Core/DataProviderAttributeBase.cs.meta | 8 + .../QuickGraph.Unit/Core/DataTestCase.cs | 21 + .../QuickGraph.Unit/Core/DataTestCase.cs.meta | 8 + .../Core/DecoratorTestCaseBase.cs | 43 + .../Core/DecoratorTestCaseBase.cs.meta | 8 + .../QuickGraph.Unit/Core/DelegateTestCase.cs | 34 + .../Core/DelegateTestCase.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/FixtureBase.cs | 90 + .../QuickGraph.Unit/Core/FixtureBase.cs.meta | 8 + .../QuickGraph.Unit/Core/FixtureRunner.cs | 388 + .../Core/FixtureRunner.cs.meta | 8 + .../Core/LightweightReflection.cs | 331 + .../Core/LightweightReflection.cs.meta | 8 + .../QuickGraph.Unit/Core/MethodTestCase.cs | 42 + .../Core/MethodTestCase.cs.meta | 8 + .../QuickGraph.Unit/Core/ReflectionHelper.cs | 152 + .../Core/ReflectionHelper.cs.meta | 8 + .../Core/ReportGenerationScenario.cs | 9 + .../Core/ReportGenerationScenario.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/Result.cs | 103 + .../Tests/QuickGraph.Unit/Core/Result.cs.meta | 8 + .../Core/SynchronizedTestCase.cs | 27 + .../Core/SynchronizedTestCase.cs.meta | 8 + .../QuickGraph.Unit/Core/TestAssembly.cs | 66 + .../QuickGraph.Unit/Core/TestAssembly.cs.meta | 8 + .../QuickGraph.Unit/Core/TestAttributeBase.cs | 15 + .../Core/TestAttributeBase.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/TestBatch.cs | 47 + .../QuickGraph.Unit/Core/TestBatch.cs.meta | 8 + .../QuickGraph.Unit/Core/TestBatchFactory.cs | 237 + .../Core/TestBatchFactory.cs.meta | 8 + .../QuickGraph.Unit/Core/TestCaseBase.cs | 72 + .../QuickGraph.Unit/Core/TestCaseBase.cs.meta | 8 + .../QuickGraph.Unit/Core/TestCaseWorker.cs | 78 + .../Core/TestCaseWorker.cs.meta | 8 + .../Core/TestCaseWorkerCollection.cs | 131 + .../Core/TestCaseWorkerCollection.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/TestCounter.cs | 116 + .../QuickGraph.Unit/Core/TestCounter.cs.meta | 8 + .../Core/TestDecoratorAttributeBase.cs | 21 + .../Core/TestDecoratorAttributeBase.cs.meta | 8 + .../Core/TestFixtureAttributeBase.cs | 36 + .../Core/TestFixtureAttributeBase.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/TestResult.cs | 38 + .../QuickGraph.Unit/Core/TestResult.cs.meta | 8 + .../Core/TestResultEventArgs.cs | 22 + .../Core/TestResultEventArgs.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/TestState.cs | 10 + .../QuickGraph.Unit/Core/TestState.cs.meta | 8 + .../Core/TypeDecoratorTestCaseBase.cs | 23 + .../Core/TypeDecoratorTestCaseBase.cs.meta | 8 + .../QuickGraph.Unit/Core/TypeFixtureBase.cs | 52 + .../Core/TypeFixtureBase.cs.meta | 8 + .../QuickGraph.Unit/Core/TypeTestCaseBase.cs | 21 + .../Core/TypeTestCaseBase.cs.meta | 8 + .../QuickGraph.Unit/Core/UnitContainer.cs | 70 + .../Core/UnitContainer.cs.meta | 8 + .../Tests/QuickGraph.Unit/Core/UnitImages.cs | 15 + .../QuickGraph.Unit/Core/UnitImages.cs.meta | 8 + .../Core/UnitResourceManager.cs | 191 + .../Core/UnitResourceManager.cs.meta | 8 + .../QuickGraph.Unit/CulturesAttribute.cs | 57 + .../QuickGraph.Unit/CulturesAttribute.cs.meta | 8 + .../CurrentFixtureAttribute.cs | 8 + .../CurrentFixtureAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Data.meta | 5 + .../Tests/QuickGraph.Unit/Data/unit.sql | 0 .../Tests/QuickGraph.Unit/Data/unit.sql.meta | 4 + .../QuickGraph.Unit/DataFixtureAttribute.cs | 79 + .../DataFixtureAttribute.cs.meta | 8 + .../QuickGraph.Unit/DataTestAttribute.cs | 41 + .../QuickGraph.Unit/DataTestAttribute.cs.meta | 8 + .../QuickGraph.Unit/DurationAttribute.cs | 45 + .../QuickGraph.Unit/DurationAttribute.cs.meta | 8 + .../QuickGraph.Unit/DynamicTestAttribute.cs | 43 + .../DynamicTestAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/Exceptions.meta | 5 + .../Exceptions/AssertionException.cs | 23 + .../Exceptions/AssertionException.cs.meta | 8 + .../Exceptions/AssumptionFailedException.cs | 18 + .../AssumptionFailedException.cs.meta | 8 + .../Exceptions/CompilationException.cs | 50 + .../Exceptions/CompilationException.cs.meta | 8 + .../Exceptions/DebugFailureException.cs | 15 + .../Exceptions/DebugFailureException.cs.meta | 8 + .../ExceptionMessageDoesNotMatchException.cs | 17 + ...eptionMessageDoesNotMatchException.cs.meta | 8 + .../ExceptionNotThrowedException.cs | 12 + .../ExceptionNotThrowedException.cs.meta | 8 + .../ExceptionTypeMistmatchException.cs | 18 + .../ExceptionTypeMistmatchException.cs.meta | 8 + .../FixtureReflectionFailedException.cs | 14 + .../FixtureReflectionFailedException.cs.meta | 8 + .../Exceptions/FixtureTimedOutException.cs | 14 + .../FixtureTimedOutException.cs.meta | 8 + .../Exceptions/IgnoreException.cs | 19 + .../Exceptions/IgnoreException.cs.meta | 8 + .../Exceptions/UnitException.cs | 23 + .../Exceptions/UnitException.cs.meta | 8 + .../ExpectedArgumentExceptionAttribute.cs | 14 + ...ExpectedArgumentExceptionAttribute.cs.meta | 8 + .../ExpectedArgumentNullExceptionAttribute.cs | 14 + ...ctedArgumentNullExceptionAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/FactoryAttribute.cs | 30 + .../QuickGraph.Unit/FactoryAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/FileAssert.cs | 48 + .../Tests/QuickGraph.Unit/FileAssert.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Filters.meta | 5 + .../Filters/AndFixtureFilter.cs | 20 + .../Filters/AndFixtureFilter.cs.meta | 8 + .../Filters/AndTestCaseFilter.cs | 16 + .../Filters/AndTestCaseFilter.cs.meta | 8 + .../Filters/AnyFixtureFilter.cs | 11 + .../Filters/AnyFixtureFilter.cs.meta | 8 + .../Filters/AnyTestCaseFilter.cs | 12 + .../Filters/AnyTestCaseFilter.cs.meta | 8 + .../BinaryOperationFixtureFilterBase.cs | 30 + .../BinaryOperationFixtureFilterBase.cs.meta | 8 + .../BinaryOperationTestCaseFilterBase.cs | 30 + .../BinaryOperationTestCaseFilterBase.cs.meta | 8 + .../Filters/CategoryFixtureFilter.cs | 29 + .../Filters/CategoryFixtureFilter.cs.meta | 8 + .../Filters/CurrentFixtureFilter.cs | 13 + .../Filters/CurrentFixtureFilter.cs.meta | 8 + .../QuickGraph.Unit/Filters/FailureFilter.cs | 42 + .../Filters/FailureFilter.cs.meta | 8 + .../Filters/ScopeFixtureFilter.cs | 28 + .../Filters/ScopeFixtureFilter.cs.meta | 8 + .../Filters/ScopeTestCaseFilter.cs | 28 + .../Filters/ScopeTestCaseFilter.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Fixture.png | Bin 0 -> 461 bytes .../Tests/QuickGraph.Unit/Fixture.png.meta | 46 + .../Tests/QuickGraph.Unit/IDataProvider.cs | 11 + .../QuickGraph.Unit/IDataProvider.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/IFixture.cs | 27 + .../Tests/QuickGraph.Unit/IFixture.cs.meta | 8 + .../Tests/QuickGraph.Unit/IFixtureFactory.cs | 11 + .../QuickGraph.Unit/IFixtureFactory.cs.meta | 8 + .../Tests/QuickGraph.Unit/IFixtureFilter.cs | 9 + .../QuickGraph.Unit/IFixtureFilter.cs.meta | 8 + .../Tests/QuickGraph.Unit/ILoggerListener.cs | 12 + .../QuickGraph.Unit/ILoggerListener.cs.meta | 8 + .../Tests/QuickGraph.Unit/ILoggerService.cs | 41 + .../QuickGraph.Unit/ILoggerService.cs.meta | 8 + .../IParameterDomainFactory.cs | 15 + .../IParameterDomainFactory.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/ITestCase.cs | 16 + .../Tests/QuickGraph.Unit/ITestCase.cs.meta | 8 + .../QuickGraph.Unit/ITestCaseDecorator.cs | 7 + .../ITestCaseDecorator.cs.meta | 8 + .../Tests/QuickGraph.Unit/ITestCaseFactory.cs | 14 + .../QuickGraph.Unit/ITestCaseFactory.cs.meta | 8 + .../Tests/QuickGraph.Unit/ITestCaseFilter.cs | 7 + .../QuickGraph.Unit/ITestCaseFilter.cs.meta | 8 + .../ITestCaseParameterFactory.cs | 10 + .../ITestCaseParameterFactory.cs.meta | 8 + .../Tests/QuickGraph.Unit/ITestListener.cs | 41 + .../QuickGraph.Unit/ITestListener.cs.meta | 8 + .../Tests/QuickGraph.Unit/IUnitServices.cs | 10 + .../QuickGraph.Unit/IUnitServices.cs.meta | 8 + .../Tests/QuickGraph.Unit/IgnoreAttribute.cs | 44 + .../QuickGraph.Unit/IgnoreAttribute.cs.meta | 8 + .../QuickGraph.Unit/KillProcessAttribute.cs | 68 + .../KillProcessAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/Listeners.meta | 5 + .../Listeners/ConsoleTestListener.cs | 331 + .../Listeners/ConsoleTestListener.cs.meta | 8 + .../Listeners/CounterTestListener.cs | 157 + .../Listeners/CounterTestListener.cs.meta | 8 + .../Listeners/TestListenerCollection.cs | 159 + .../Listeners/TestListenerCollection.cs.meta | 8 + .../Listeners/XmlTestListener.cs | 257 + .../Listeners/XmlTestListener.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/LogError.png | Bin 0 -> 726 bytes .../Tests/QuickGraph.Unit/LogError.png.meta | 46 + .../Editor/Tests/QuickGraph.Unit/LogLevel.cs | 10 + .../Tests/QuickGraph.Unit/LogLevel.cs.meta | 8 + .../Tests/QuickGraph.Unit/LogMessage.png | Bin 0 -> 788 bytes .../Tests/QuickGraph.Unit/LogMessage.png.meta | 46 + .../Tests/QuickGraph.Unit/LogWarning.png | Bin 0 -> 810 bytes .../Tests/QuickGraph.Unit/LogWarning.png.meta | 46 + .../Editor/Tests/QuickGraph.Unit/Logging.meta | 5 + .../Logging/ConsoleLoggerListener.cs | 17 + .../Logging/ConsoleLoggerListener.cs.meta | 8 + .../QuickGraph.Unit/Logging/LoggerService.cs | 79 + .../Logging/LoggerService.cs.meta | 8 + .../Logging/XmlLoggerListener.cs | 24 + .../Logging/XmlLoggerListener.cs.meta | 8 + .../QuickGraph.Unit/MessageImportance.cs | 12 + .../QuickGraph.Unit/MessageImportance.cs.meta | 8 + .../Tests/QuickGraph.Unit/Monitoring.meta | 5 + .../Monitoring/ConsoleLoggerMonitor.cs | 33 + .../Monitoring/ConsoleLoggerMonitor.cs.meta | 8 + .../Monitoring/ConsoleMonitor.cs | 56 + .../Monitoring/ConsoleMonitor.cs.meta | 8 + .../Monitoring/DebugMonitor.cs | 116 + .../Monitoring/DebugMonitor.cs.meta | 8 + .../Monitoring/EnvironmentMonitor.cs | 29 + .../Monitoring/EnvironmentMonitor.cs.meta | 8 + .../QuickGraph.Unit/Monitoring/IMonitor.cs | 10 + .../Monitoring/IMonitor.cs.meta | 8 + .../Monitoring/MonitorCollection.cs | 55 + .../Monitoring/MonitorCollection.cs.meta | 8 + .../Monitoring/ThreadExceptionMonitor.cs | 53 + .../Monitoring/ThreadExceptionMonitor.cs.meta | 8 + .../Monitoring/ThreadMonitor.cs | 46 + .../Monitoring/ThreadMonitor.cs.meta | 8 + .../QuickGraph.Unit/Monitoring/TimeMonitor.cs | 50 + .../Monitoring/TimeMonitor.cs.meta | 8 + .../Monitoring/UnhandledExceptionMonitor.cs | 38 + .../UnhandledExceptionMonitor.cs.meta | 8 + .../QuickGraph.Unit/Monitoring/testmonitor.cs | 106 + .../Monitoring/testmonitor.cs.meta | 8 + .../MultiThreadedTestAttribute.cs | 35 + .../MultiThreadedTestAttribute.cs.meta | 8 + .../MultiThreadedTestFixtureAttribute.cs | 164 + .../MultiThreadedTestFixtureAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/NameMatch.cs | 74 + .../Tests/QuickGraph.Unit/NameMatch.cs.meta | 8 + .../Tests/QuickGraph.Unit/Operations.meta | 5 + .../QuickGraph.Unit/Operations/ArrayDomain.cs | 59 + .../Operations/ArrayDomain.cs.meta | 8 + .../Operations/BooleanDomain.cs | 35 + .../Operations/BooleanDomain.cs.meta | 8 + .../CartesianProductDomainTupleEnumerable.cs | 25 + ...tesianProductDomainTupleEnumerable.cs.meta | 8 + .../CartesianProductDomainTupleEnumerator.cs | 67 + ...tesianProductDomainTupleEnumerator.cs.meta | 8 + .../Operations/CollectionDomain.cs | 59 + .../Operations/CollectionDomain.cs.meta | 8 + .../Operations/CombinationType.cs | 10 + .../Operations/CombinationType.cs.meta | 8 + .../QuickGraph.Unit/Operations/DomainBase.cs | 26 + .../Operations/DomainBase.cs.meta | 8 + .../Operations/DomainTupleEnumeratorBase.cs | 49 + .../DomainTupleEnumeratorBase.cs.meta | 8 + .../QuickGraph.Unit/Operations/Domains.cs | 171 + .../Operations/Domains.cs.meta | 8 + .../QuickGraph.Unit/Operations/EmptyDomain.cs | 53 + .../Operations/EmptyDomain.cs.meta | 8 + .../Operations/GreedyTupleEnumerator.cs | 78 + .../Operations/GreedyTupleEnumerator.cs.meta | 8 + .../QuickGraph.Unit/Operations/IDomain.cs | 12 + .../Operations/IDomain.cs.meta | 8 + .../QuickGraph.Unit/Operations/ITuple.cs | 15 + .../QuickGraph.Unit/Operations/ITuple.cs.meta | 8 + .../Operations/ITupleEnumeratorFactory.cs | 10 + .../ITupleEnumeratorFactory.cs.meta | 8 + .../Operations/LinearInt32Domain.cs | 124 + .../Operations/LinearInt32Domain.cs.meta | 8 + .../Operations/NamespaceDoc.cs | 23 + .../Operations/NamespaceDoc.cs.meta | 8 + .../Operations/OperationsResourceManager.cs | 51 + .../OperationsResourceManager.cs.meta | 8 + .../PairWizeProductDomainTupleEnumerable.cs | 61 + ...irWizeProductDomainTupleEnumerable.cs.meta | 8 + .../QuickGraph.Unit/Operations/Permutation.cs | 282 + .../Operations/Permutation.cs.meta | 8 + .../QuickGraph.Unit/Operations/Products.cs | 111 + .../Operations/Products.cs.meta | 8 + .../Operations/StringDomain.cs | 33 + .../Operations/StringDomain.cs.meta | 8 + .../Tests/QuickGraph.Unit/Operations/Tuple.cs | 92 + .../QuickGraph.Unit/Operations/Tuple.cs.meta | 8 + ...ormPairWizeProductDomainTupleEnumerable.cs | 206 + ...irWizeProductDomainTupleEnumerable.cs.meta | 8 + ...niformTWizeProductDomainTupleEnumerable.cs | 81 + ...mTWizeProductDomainTupleEnumerable.cs.meta | 8 + .../Operations/operations.banner.png | Bin 0 -> 11013 bytes .../Operations/operations.banner.png.meta | 46 + .../QuickGraph.Unit/Operations/operations.png | Bin 0 -> 4907 bytes .../Operations/operations.png.meta | 46 + .../QuickGraph.Unit/PerfMonitorAttribute.cs | 101 + .../PerfMonitorAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Pex.meta | 5 + .../Pex/QuickGraphPackageAttribute.cs | 18 + .../Pex/QuickGraphPackageAttribute.cs.meta | 8 + .../Pex/QuickGraphTestFramework.cs | 152 + .../Pex/QuickGraphTestFramework.cs.meta | 8 + .../Tests/QuickGraph.Unit/ProcessTester.cs | 228 + .../QuickGraph.Unit/ProcessTester.cs.meta | 8 + .../Tests/QuickGraph.Unit/Properties.meta | 5 + .../Properties/AssemblyInfo.cs | 27 + .../Properties/AssemblyInfo.cs.meta | 8 + .../QuickGraph.Unit/QuickGraph.Unit.csproj | 354 + .../QuickGraph.Unit.csproj.meta | 4 + .../QuickGraph.Unit.csproj.vspscc | 10 + .../QuickGraph.Unit.csproj.vspscc.meta | 4 + .../Tests/QuickGraph.Unit/ReflectionAssert.cs | 86 + .../QuickGraph.Unit/ReflectionAssert.cs.meta | 8 + .../Tests/QuickGraph.Unit/RepeatAttribute.cs | 46 + .../QuickGraph.Unit/RepeatAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/Reports.meta | 5 + .../QuickGraph.Unit/Reports/FileReportBase.cs | 97 + .../Reports/FileReportBase.cs.meta | 8 + .../QuickGraph.Unit/Reports/ReportBase.cs | 44 + .../Reports/ReportBase.cs.meta | 8 + .../QuickGraph.Unit/Reports/ReportCleaner.cs | 29 + .../Reports/ReportCleaner.cs.meta | 8 + .../QuickGraph.Unit/Reports/ReportHistory.cs | 99 + .../Reports/ReportHistory.cs.meta | 8 + .../QuickGraph.Unit/Reports/ReportPath.cs | 44 + .../Reports/ReportPath.cs.meta | 8 + .../Reports/UnitTestHistoryHtmlReport.cs | 47 + .../Reports/UnitTestHistoryHtmlReport.cs.meta | 8 + .../Reports/UnitTestHtmlReport.cs | 106 + .../Reports/UnitTestHtmlReport.cs.meta | 8 + .../QuickGraph.Unit/Reports/XslReportBase.cs | 53 + .../Reports/XslReportBase.cs.meta | 8 + .../QuickGraph.Unit/RollbackAttribute.cs | 30 + .../QuickGraph.Unit/RollbackAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/RowTestAttribute.cs | 75 + .../QuickGraph.Unit/RowTestAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/Serialization.meta | 5 + .../Serialization/UnitSerializer.cs | 71 + .../Serialization/UnitSerializer.cs.meta | 8 + .../Serialization/XmlCounter.cs | 83 + .../Serialization/XmlCounter.cs.meta | 8 + .../Serialization/XmlException.cs | 118 + .../Serialization/XmlException.cs.meta | 8 + .../Serialization/XmlFixture.cs | 146 + .../Serialization/XmlFixture.cs.meta | 8 + .../Serialization/XmlFixtureCollection.cs | 19 + .../XmlFixtureCollection.cs.meta | 8 + .../QuickGraph.Unit/Serialization/XmlLog.cs | 18 + .../Serialization/XmlLog.cs.meta | 8 + .../Serialization/XmlLogEntry.cs | 63 + .../Serialization/XmlLogEntry.cs.meta | 8 + .../Serialization/XmlLogEntryCollection.cs | 10 + .../XmlLogEntryCollection.cs.meta | 8 + .../Serialization/XmlMachine.cs | 97 + .../Serialization/XmlMachine.cs.meta | 8 + .../Serialization/XmlMonitor.cs | 78 + .../Serialization/XmlMonitor.cs.meta | 8 + .../Serialization/XmlResult.cs | 62 + .../Serialization/XmlResult.cs.meta | 8 + .../Serialization/XmlTestAssembly.cs | 116 + .../Serialization/XmlTestAssembly.cs.meta | 8 + .../XmlTestAssemblyCollection.cs | 9 + .../XmlTestAssemblyCollection.cs.meta | 8 + .../Serialization/XmlTestBatch.cs | 129 + .../Serialization/XmlTestBatch.cs.meta | 8 + .../Serialization/XmlTestBatchSearcher.cs | 77 + .../XmlTestBatchSearcher.cs.meta | 8 + .../Serialization/XmlTestCase.cs | 140 + .../Serialization/XmlTestCase.cs.meta | 8 + .../Serialization/XmlTestCaseCollection.cs | 11 + .../XmlTestCaseCollection.cs.meta | 8 + .../Serialization/XmlTestHistory.cs | 12 + .../Serialization/XmlTestHistory.cs.meta | 8 + .../QuickGraph.Unit/SerializationAssert.cs | 23 + .../SerializationAssert.cs.meta | 8 + .../SetEnvironmentVariableAttribute.cs | 70 + .../SetEnvironmentVariableAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/SetUpAttribute.cs | 9 + .../QuickGraph.Unit/SetUpAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/StreamAssert.cs | 47 + .../QuickGraph.Unit/StreamAssert.cs.meta | 8 + .../Tests/QuickGraph.Unit/StringAssert.cs | 62 + .../QuickGraph.Unit/StringAssert.cs.meta | 8 + .../QuickGraph.Unit/TearDownAttribute.cs | 9 + .../QuickGraph.Unit/TearDownAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/TestAttribute.cs | 19 + .../QuickGraph.Unit/TestAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/TestCase.png | Bin 0 -> 245 bytes .../Tests/QuickGraph.Unit/TestCase.png.meta | 46 + .../QuickGraph.Unit/TestCaseParameter.cs | 47 + .../QuickGraph.Unit/TestCaseParameter.cs.meta | 8 + .../TestCaseParameterFactoryAttributeBase.cs | 12 + ...tCaseParameterFactoryAttributeBase.cs.meta | 8 + .../Tests/QuickGraph.Unit/TestConsole.cs | 57 + .../Tests/QuickGraph.Unit/TestConsole.cs.meta | 8 + .../QuickGraph.Unit/TestFixtureAttribute.cs | 41 + .../TestFixtureAttribute.cs.meta | 8 + .../TestFixtureSetUpAttribute.cs | 9 + .../TestFixtureSetUpAttribute.cs.meta | 8 + .../TestFixtureTearDownAttribute.cs | 7 + .../TestFixtureTearDownAttribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/TestRunner.cs | 565 + .../Tests/QuickGraph.Unit/TestRunner.cs.meta | 8 + .../QuickGraph.Unit/TestRunnerArguments.cs | 252 + .../TestRunnerArguments.cs.meta | 8 + .../Tests/QuickGraph.Unit/TestSynchronizer.cs | 82 + .../QuickGraph.Unit/TestSynchronizer.cs.meta | 8 + .../ThreadedRepeatAttribute.cs | 69 + .../ThreadedRepeatAttribute.cs.meta | 8 + .../QuickGraph.Unit/TypeFactoryAttribute.cs | 103 + .../TypeFactoryAttribute.cs.meta | 8 + .../QuickGraph.Unit/TypeFixtureAttribute.cs | 102 + .../TypeFixtureAttribute.cs.meta | 8 + .../QuickGraph.Unit/UsingAttributeBase.cs | 18 + .../UsingAttributeBase.cs.meta | 8 + .../QuickGraph.Unit/UsingBooleanAttribute.cs | 22 + .../UsingBooleanAttribute.cs.meta | 8 + .../QuickGraph.Unit/UsingEnumAttribute.cs | 22 + .../UsingEnumAttribute.cs.meta | 8 + .../UsingFactoriesAttribute.cs | 123 + .../UsingFactoriesAttribute.cs.meta | 8 + .../UsingImplementationsAttribute.cs | 44 + .../UsingImplementationsAttribute.cs.meta | 8 + .../QuickGraph.Unit/UsingLinearAttribute.cs | 51 + .../UsingLinearAttribute.cs.meta | 8 + .../QuickGraph.Unit/UsingLiteralsAttribute.cs | 53 + .../UsingLiteralsAttribute.cs.meta | 8 + .../QuickGraph.Unit/UsingXmlAttribute.cs | 24 + .../QuickGraph.Unit/UsingXmlAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/XmlAssert.cs | 197 + .../Tests/QuickGraph.Unit/XmlAssert.cs.meta | 8 + .../XmlDataProviderAttribute.cs | 37 + .../XmlDataProviderAttribute.cs.meta | 8 + .../Editor/Tests/QuickGraph.Unit/common.xslt | 851 + .../Tests/QuickGraph.Unit/common.xslt.meta | 4 + .../expectedexceptionattribute.cs | 104 + .../expectedexceptionattribute.cs.meta | 8 + .../Tests/QuickGraph.Unit/fixturetest.xslt | 20 + .../QuickGraph.Unit/fixturetest.xslt.meta | 4 + .../Tests/QuickGraph.Unit/quickgraph.css | 41 + .../Tests/QuickGraph.Unit/quickgraph.css.meta | 4 + .../Tests/QuickGraph.Unit/quickgraph.snk | Bin 0 -> 596 bytes .../Tests/QuickGraph.Unit/quickgraph.snk.meta | 4 + .../Editor/Tests/QuickGraph.Unit/report.js | 78 + .../Tests/QuickGraph.Unit/report.js.meta | 8 + .../Tests/QuickGraph.Unit/unit.banner.png | Bin 0 -> 9581 bytes .../QuickGraph.Unit/unit.banner.png.meta | 46 + .../Editor/Tests/QuickGraph.Unit/unit.png | Bin 0 -> 4933 bytes .../Tests/QuickGraph.Unit/unit.png.meta | 46 + .../Tests/QuickGraph.Unit/unittest.xslt | 159 + .../Tests/QuickGraph.Unit/unittest.xslt.meta | 4 + .../Tests/QuickGraph.Unit/unittestframes.xslt | 26 + .../QuickGraph.Unit/unittestframes.xslt.meta | 4 + .../QuickGraph.Unit/unittesthistory.xslt | 253 + .../QuickGraph.Unit/unittesthistory.xslt.meta | 4 + src/Assets/quickgraph4unity/License.txt | 31 + src/Assets/quickgraph4unity/License.txt.meta | 4 + src/Assets/quickgraph4unity/Runtime.meta | 5 + .../Runtime/QuickGraph.Data.meta | 5 + .../QuickGraph.Data/DataRelationEdge.cs | 33 + .../QuickGraph.Data/DataRelationEdge.cs.meta | 8 + .../DataSetGraphPopulatorAlgorithm.cs | 40 + .../DataSetGraphPopulatorAlgorithm.cs.meta | 8 + .../Runtime/QuickGraph.Data/Properties.meta | 5 + .../Properties/AssemblyInfo.cs | 19 + .../Properties/AssemblyInfo.cs.meta | 8 + .../QuickGraph.Data/QuickGraph.Data.csproj | 71 + .../QuickGraph.Data.csproj.meta | 4 + .../QuickGraph.Data.csproj.vspscc | 10 + .../QuickGraph.Data.csproj.vspscc.meta | 4 + .../Runtime/QuickGraph.Graphviz.meta | 5 + .../CondensatedGraphRenderer.cs | 45 + .../CondensatedGraphRenderer.cs.meta | 8 + .../Runtime/QuickGraph.Graphviz/Dot.meta | 5 + .../QuickGraph.Graphviz/Dot/GraphvizArrow.cs | 91 + .../Dot/GraphvizArrow.cs.meta | 8 + .../Dot/GraphvizArrowClipping.cs | 12 + .../Dot/GraphvizArrowClipping.cs.meta | 8 + .../Dot/GraphvizArrowFilling.cs | 11 + .../Dot/GraphvizArrowFilling.cs.meta | 8 + .../Dot/GraphvizArrowShape.cs | 18 + .../Dot/GraphvizArrowShape.cs.meta | 8 + .../Dot/GraphvizClusterMode.cs | 12 + .../Dot/GraphvizClusterMode.cs.meta | 8 + .../QuickGraph.Graphviz/Dot/GraphvizEdge.cs | 361 + .../Dot/GraphvizEdge.cs.meta | 8 + .../Dot/GraphvizEdgeDirection.cs | 13 + .../Dot/GraphvizEdgeDirection.cs.meta | 8 + .../Dot/GraphvizEdgeExtremity.cs | 149 + .../Dot/GraphvizEdgeExtremity.cs.meta | 8 + .../Dot/GraphvizEdgeLabel.cs | 114 + .../Dot/GraphvizEdgeLabel.cs.meta | 8 + .../Dot/GraphvizEdgeStyle.cs | 15 + .../Dot/GraphvizEdgeStyle.cs.meta | 8 + .../QuickGraph.Graphviz/Dot/GraphvizGraph.cs | 616 + .../Dot/GraphvizGraph.cs.meta | 8 + .../Dot/GraphvizImageType.cs | 52 + .../Dot/GraphvizImageType.cs.meta | 8 + .../Dot/GraphvizLabelJustification.cs | 12 + .../Dot/GraphvizLabelJustification.cs.meta | 8 + .../Dot/GraphvizLabelLocation.cs | 11 + .../Dot/GraphvizLabelLocation.cs.meta | 8 + .../QuickGraph.Graphviz/Dot/GraphvizLayer.cs | 35 + .../Dot/GraphvizLayer.cs.meta | 8 + .../Dot/GraphvizLayerCollection.cs | 72 + .../Dot/GraphvizLayerCollection.cs.meta | 8 + .../Dot/GraphvizOutputMode.cs | 12 + .../Dot/GraphvizOutputMode.cs.meta | 8 + .../Dot/GraphvizPageDirection.cs | 17 + .../Dot/GraphvizPageDirection.cs.meta | 8 + .../Dot/GraphvizRankDirection.cs | 11 + .../Dot/GraphvizRankDirection.cs.meta | 8 + .../Dot/GraphvizRatioMode.cs | 12 + .../Dot/GraphvizRatioMode.cs.meta | 8 + .../QuickGraph.Graphviz/Dot/GraphvizRecord.cs | 45 + .../Dot/GraphvizRecord.cs.meta | 8 + .../Dot/GraphvizRecordCell.cs | 113 + .../Dot/GraphvizRecordCell.cs.meta | 8 + .../Dot/GraphvizRecordCellCollection.cs | 21 + .../Dot/GraphvizRecordCellCollection.cs.meta | 8 + .../Dot/GraphvizRecordEscaper.cs | 29 + .../Dot/GraphvizRecordEscaper.cs.meta | 8 + .../QuickGraph.Graphviz/Dot/GraphvizVertex.cs | 487 + .../Dot/GraphvizVertex.cs.meta | 8 + .../Dot/GraphvizVertexShape.cs | 38 + .../Dot/GraphvizVertexShape.cs.meta | 8 + .../Dot/GraphvizVertexStyle.cs | 18 + .../Dot/GraphvizVertexStyle.cs.meta | 8 + .../EdgeMergeCondensatedGraphRenderer.cs | 37 + .../EdgeMergeCondensatedGraphRenderer.cs.meta | 8 + .../QuickGraph.Graphviz/FileDotEngine.cs | 21 + .../QuickGraph.Graphviz/FileDotEngine.cs.meta | 8 + .../FormatEdgeEventArgs.cs | 35 + .../FormatEdgeEventArgs.cs.meta | 8 + .../FormatVertexEventArgs.cs | 30 + .../FormatVertexEventArgs.cs.meta | 8 + .../QuickGraph.Graphviz/GraphRendererBase.cs | 44 + .../GraphRendererBase.cs.meta | 8 + .../QuickGraph.Graphviz/GraphvizAlgorithm.cs | 236 + .../GraphvizAlgorithm.cs.meta | 8 + .../Runtime/QuickGraph.Graphviz/IDotEngine.cs | 15 + .../QuickGraph.Graphviz/IDotEngine.cs.meta | 8 + .../QuickGraph.Graphviz.csproj | 111 + .../QuickGraph.Graphviz.csproj.meta | 4 + .../QuickGraph.Graphviz.csproj.vspscc | 10 + .../QuickGraph.Graphviz.csproj.vspscc.meta | 4 + .../QuickGraph.Graphviz/SvgHtmlWrapper.cs | 65 + .../SvgHtmlWrapper.cs.meta | 8 + .../QuickGraph.Graphviz/quickgraph.snk | Bin 0 -> 596 bytes .../QuickGraph.Graphviz/quickgraph.snk.meta | 4 + .../Runtime/QuickGraph.Heap.meta | 5 + .../Runtime/QuickGraph.Heap/Data.meta | 5 + .../QuickGraph.Heap/Data/GcHeapParser.cs | 73 + .../QuickGraph.Heap/Data/GcHeapParser.cs.meta | 8 + .../Runtime/QuickGraph.Heap/Data/GcObject.cs | 57 + .../QuickGraph.Heap/Data/GcObject.cs.meta | 8 + .../Runtime/QuickGraph.Heap/Data/GcRoot.cs | 31 + .../QuickGraph.Heap/Data/GcRoot.cs.meta | 8 + .../Runtime/QuickGraph.Heap/Data/GcType.cs | 32 + .../QuickGraph.Heap/Data/GcType.cs.meta | 8 + .../Runtime/QuickGraph.Heap/FilterHelper.cs | 116 + .../QuickGraph.Heap/FilterHelper.cs.meta | 8 + .../Runtime/QuickGraph.Heap/FormatHelper.cs | 19 + .../QuickGraph.Heap/FormatHelper.cs.meta | 8 + .../Runtime/QuickGraph.Heap/GcObjectGraph.cs | 70 + .../QuickGraph.Heap/GcObjectGraph.cs.meta | 8 + .../Runtime/QuickGraph.Heap/GcObjectVertex.cs | 71 + .../QuickGraph.Heap/GcObjectVertex.cs.meta | 8 + .../Runtime/QuickGraph.Heap/GcType.cs | 133 + .../Runtime/QuickGraph.Heap/GcType.cs.meta | 8 + .../QuickGraph.Heap/GcTypeGraphReader.cs | 149 + .../QuickGraph.Heap/GcTypeGraphReader.cs.meta | 8 + .../Runtime/QuickGraph.Heap/GcTypeHeap.cs | 346 + .../QuickGraph.Heap/GcTypeHeap.cs.meta | 8 + .../Runtime/QuickGraph.Heap/HeapXmlReader.cs | 189 + .../QuickGraph.Heap/HeapXmlReader.cs.meta | 8 + .../Runtime/QuickGraph.Heap/QueryableList.cs | 54 + .../QuickGraph.Heap/QueryableList.cs.meta | 8 + .../QuickGraph.Heap/QuickGraph.Heap.csproj | 109 + .../QuickGraph.Heap.csproj.meta | 4 + .../QuickGraph.Heap.csproj.vspscc | 10 + .../QuickGraph.Heap.csproj.vspscc.meta | 4 + .../Runtime/QuickGraph.Heap/dumpheap.cmd | 2 + .../Runtime/QuickGraph.Heap/dumpheap.cmd.meta | 4 + .../Runtime/QuickGraph.Heap/dumpheap.txt | 7 + .../Runtime/QuickGraph.Heap/dumpheap.txt.meta | 4 + .../Runtime/QuickGraph.Heap/heap.py | 4 + .../Runtime/QuickGraph.Heap/heap.py.meta | 4 + .../Runtime/QuickGraph.Heap/quickgraph.snk | Bin 0 -> 596 bytes .../QuickGraph.Heap/quickgraph.snk.meta | 4 + .../quickgraph4unity/Runtime/QuickGraph.meta | 5 + .../Runtime/QuickGraph/AdjacencyGraph.cs | 467 + .../Runtime/QuickGraph/AdjacencyGraph.cs.meta | 8 + .../Runtime/QuickGraph/Algorithms.meta | 5 + .../QuickGraph/Algorithms/AlgoUtility.cs | 331 + .../QuickGraph/Algorithms/AlgoUtility.cs.meta | 8 + .../QuickGraph/Algorithms/AlgorithmBase.cs | 202 + .../Algorithms/AlgorithmBase.cs.meta | 8 + .../Algorithms/AlgorithmEventHandler.cs | 10 + .../Algorithms/AlgorithmEventHandler.cs.meta | 8 + .../CentralityApproximationAlgorithm.cs | 82 + .../CentralityApproximationAlgorithm.cs.meta | 8 + .../QuickGraph/Algorithms/ComputationState.cs | 14 + .../Algorithms/ComputationState.cs.meta | 8 + .../QuickGraph/Algorithms/Condensation.meta | 5 + .../Condensation/CondensatedEdge.cs | 22 + .../Condensation/CondensatedEdge.cs.meta | 8 + .../CondensationGraphAlgorithm.cs | 149 + .../CondensationGraphAlgorithm.cs.meta | 8 + .../EdgeMergeCondensationGraphAlgorithm.cs | 106 + ...dgeMergeCondensationGraphAlgorithm.cs.meta | 8 + .../Algorithms/Condensation/MergedEdge.cs | 36 + .../Condensation/MergedEdge.cs.meta | 8 + .../ConnectedComponentsAlgorithm.cs | 100 + .../ConnectedComponentsAlgorithm.cs.meta | 8 + .../Algorithms/EulerianTrailAlgorithm.cs | 465 + .../Algorithms/EulerianTrailAlgorithm.cs.meta | 8 + .../QuickGraph/Algorithms/Exploration.meta | 5 + .../CloneableVertexGraphExplorerAlgorithm.cs | 213 + ...neableVertexGraphExplorerAlgorithm.cs.meta | 8 + .../Exploration/ITransitionFactory.cs | 13 + .../Exploration/ITransitionFactory.cs.meta | 8 + .../TransitionFactoryImplicitGraph.cs | 90 + .../TransitionFactoryImplicitGraph.cs.meta | 8 + .../QuickGraph/Algorithms/IAlgorithm.cs | 11 + .../QuickGraph/Algorithms/IAlgorithm.cs.meta | 8 + .../QuickGraph/Algorithms/IComputation.cs | 20 + .../Algorithms/IComputation.cs.meta | 8 + .../IConnectedComponentAlgorithm.cs | 14 + .../IConnectedComponentAlgorithm.cs.meta | 8 + .../Algorithms/IDistanceRecorderAlgorithm.cs | 12 + .../IDistanceRecorderAlgorithm.cs.meta | 8 + .../Algorithms/IEdgeColorizerAlgorithm.cs | 11 + .../IEdgeColorizerAlgorithm.cs.meta | 8 + .../IEdgePredecessorRecorderAlgorithm.cs | 11 + .../IEdgePredecessorRecorderAlgorithm.cs.meta | 8 + .../IEndPathEdgeRecorderAlgorithm.cs | 8 + .../IEndPathEdgeRecorderAlgorithm.cs.meta | 8 + .../Algorithms/ITreeBuilderAlgorithm.cs | 10 + .../Algorithms/ITreeBuilderAlgorithm.cs.meta | 8 + .../Algorithms/IVertexColorizerAlgorithm.cs | 11 + .../IVertexColorizerAlgorithm.cs.meta | 8 + .../IVertexPredecessorRecorderAlgorithm.cs | 12 + ...VertexPredecessorRecorderAlgorithm.cs.meta | 8 + .../Algorithms/IVertexTimeStamperAlgorithm.cs | 11 + .../IVertexTimeStamperAlgorithm.cs.meta | 8 + .../Runtime/QuickGraph/Algorithms/Matrix.meta | 5 + .../Algorithms/Matrix/DenseFloatMatrix.cs | 36 + .../Matrix/DenseFloatMatrix.cs.meta | 8 + .../Algorithms/Matrix/DoubleDenseMatrix.cs | 382 + .../Matrix/DoubleDenseMatrix.cs.meta | 8 + .../MaximumBipartiteMatchingAlgorithm.cs | 124 + .../MaximumBipartiteMatchingAlgorithm.cs.meta | 8 + .../QuickGraph/Algorithms/MaximumFlow.meta | 5 + .../AllVerticesGraphAugmentorAlgorithm.cs | 48 + ...AllVerticesGraphAugmentorAlgorithm.cs.meta | 8 + .../EdmondsKarpMaximumFlowAlgorithm.cs | 133 + .../EdmondsKarpMaximumFlowAlgorithm.cs.meta | 8 + .../MaximumFlow/FeasibleFlowAlgorithm.cs | 18 + .../MaximumFlow/FeasibleFlowAlgorithm.cs.meta | 8 + .../GraphAugmentorAlgorithmBase.cs | 129 + .../GraphAugmentorAlgorithmBase.cs.meta | 8 + .../MaximumFlow/GraphBalancingAlgorithm.cs | 380 + .../GraphBalancingAlgorithm.cs.meta | 8 + .../MaximumFlow/MaximumFlowAlgorithmBase.cs | 123 + .../MaximumFlowAlgorithmBase.cs.meta | 8 + .../MinimumCostMaximumFlowAlgorithm.cs | 12 + .../MinimumCostMaximumFlowAlgorithm.cs.meta | 8 + .../MultiSourceSinkGraphAugmentorAlgorithm.cs | 49 + ...iSourceSinkGraphAugmentorAlgorithm.cs.meta | 8 + .../ReverseEdgeAugmentorAlgorithm.cs | 156 + .../ReverseEdgeAugmentorAlgorithm.cs.meta | 8 + .../Algorithms/MinimumSpanningTree.meta | 5 + .../PrimMinimumSpanningTreeAlgorithm.cs | 141 + .../PrimMinimumSpanningTreeAlgorithm.cs.meta | 8 + .../QuickGraph/Algorithms/Observers.meta | 5 + .../EdgePredecessorRecorderObserver.cs | 158 + .../EdgePredecessorRecorderObserver.cs.meta | 8 + .../Observers/EdgeRecorderObserver.cs | 63 + .../Observers/EdgeRecorderObserver.cs.meta | 8 + .../Algorithms/Observers/IObserver.cs | 16 + .../Algorithms/Observers/IObserver.cs.meta | 8 + .../Algorithms/Observers/ObserverUtility.cs | 44 + .../Observers/ObserverUtility.cs.meta | 8 + .../VertexDistanceRecorderObserver.cs | 61 + .../VertexDistanceRecorderObserver.cs.meta | 8 + .../VertexPredecessorRecorderObserver.cs | 112 + .../VertexPredecessorRecorderObserver.cs.meta | 8 + .../Observers/VertexRecorderObserver.cs | 54 + .../Observers/VertexRecorderObserver.cs.meta | 8 + .../Observers/VertexTimeStamperObserver.cs | 71 + .../VertexTimeStamperObserver.cs.meta | 8 + .../Algorithms/PageRankAlgorithm.cs | 176 + .../Algorithms/PageRankAlgorithm.cs.meta | 8 + .../Algorithms/RandomGraphFactory.cs | 150 + .../Algorithms/RandomGraphFactory.cs.meta | 8 + .../QuickGraph/Algorithms/RandomWalks.meta | 5 + .../CyclePoppingRandomTreeAlgorithm.cs | 261 + .../CyclePoppingRandomTreeAlgorithm.cs.meta | 8 + .../Algorithms/RandomWalks/IEdgeChain.cs | 8 + .../Algorithms/RandomWalks/IEdgeChain.cs.meta | 8 + .../RandomWalks/IMarkovEdgeChain.cs | 9 + .../RandomWalks/IMarkovEdgeChain.cs.meta | 8 + .../RandomWalks/MarkovEdgeChainBase.cs | 26 + .../RandomWalks/MarkovEdgeChainBase.cs.meta | 8 + .../RandomWalks/NormalizedMarkovEdgeChain.cs | 21 + .../NormalizedMarkovEdgeChain.cs.meta | 8 + .../RandomWalks/RandomWalkAlgorithm.cs | 129 + .../RandomWalks/RandomWalkAlgorithm.cs.meta | 8 + .../RandomWalks/RoundRobinEdgeChain.cs | 31 + .../RandomWalks/RoundRobinEdgeChain.cs.meta | 8 + .../VanishingWeightedMarkovEdgeChain.cs | 58 + .../VanishingWeightedMarkovEdgeChain.cs.meta | 8 + .../RandomWalks/WeightedMarkedEdgeChain.cs | 33 + .../WeightedMarkedEdgeChain.cs.meta | 8 + .../WeightedMarkovEdgeChainBase.cs | 49 + .../WeightedMarkovEdgeChainBase.cs.meta | 8 + .../Algorithms/RootedAlgorithmBase.cs | 67 + .../Algorithms/RootedAlgorithmBase.cs.meta | 8 + .../Runtime/QuickGraph/Algorithms/Search.meta | 5 + .../BidirectionalDepthFirstSearchAlgorithm.cs | 214 + ...rectionalDepthFirstSearchAlgorithm.cs.meta | 8 + .../Search/BreadthFirstSearchAlgorithm.cs | 229 + .../BreadthFirstSearchAlgorithm.cs.meta | 8 + .../Search/DepthFirstSearchAlgorithm.cs | 232 + .../Search/DepthFirstSearchAlgorithm.cs.meta | 8 + .../Search/EdgeDepthFirstSearchAlgorithm.cs | 227 + .../EdgeDepthFirstSearchAlgorithm.cs.meta | 8 + .../Search/HeightFirstSearchAlgorithm.cs | 403 + .../Search/HeightFirstSearchAlgorithm.cs.meta | 8 + .../ImplicitDepthFirstSearchAlgorithm.cs | 241 + .../ImplicitDepthFirstSearchAlgorithm.cs.meta | 8 + .../ImplicitEdgeDepthFirstSearchAlgorithm.cs | 268 + ...licitEdgeDepthFirstSearchAlgorithm.cs.meta | 8 + .../UndirectedBreathFirstSearchAlgorithm.cs | 225 + ...directedBreathFirstSearchAlgorithm.cs.meta | 8 + .../UndirectedDepthFirstSearchAlgorithm.cs | 213 + ...ndirectedDepthFirstSearchAlgorithm.cs.meta | 8 + ...UndirectedEdgeDepthFirstSearchAlgorithm.cs | 205 + ...ectedEdgeDepthFirstSearchAlgorithm.cs.meta | 8 + .../QuickGraph/Algorithms/Services.meta | 5 + .../Services/IAlgorithmComponent.cs | 13 + .../Services/IAlgorithmComponent.cs.meta | 8 + .../Algorithms/Services/IAlgorithmServices.cs | 37 + .../Services/IAlgorithmServices.cs.meta | 8 + .../Algorithms/Services/ICancelManager.cs | 80 + .../Services/ICancelManager.cs.meta | 8 + .../Algorithms/Services/IService.cs | 5 + .../Algorithms/Services/IService.cs.meta | 8 + .../QuickGraph/Algorithms/ShortestPath.meta | 5 + .../BellmanFordShortestPathAlgorithm.cs | 261 + .../BellmanFordShortestPathAlgorithm.cs.meta | 8 + .../ShortestPath/CriticalDistanceRelaxer.cs | 25 + .../CriticalDistanceRelaxer.cs.meta | 8 + .../ShortestPath/DagShortestPathAlgorithm.cs | 172 + .../DagShortestPathAlgorithm.cs.meta | 8 + .../DijkstraShortestPathAlgorithm.cs | 180 + .../DijkstraShortestPathAlgorithm.cs.meta | 8 + .../ShortestPath/IDistanceRelaxer.cs | 13 + .../ShortestPath/IDistanceRelaxer.cs.meta | 8 + .../ShortestPath/ShortestDistanceRelaxer.cs | 24 + .../ShortestDistanceRelaxer.cs.meta | 8 + .../ShortestPath/ShortestPathAlgorithmBase.cs | 106 + .../ShortestPathAlgorithmBase.cs.meta | 8 + ...UndirectedDijkstraShortestPathAlgorithm.cs | 169 + ...ectedDijkstraShortestPathAlgorithm.cs.meta | 8 + .../SourceFirstTopologicalSortAlgorithm.cs | 111 + ...ourceFirstTopologicalSortAlgorithm.cs.meta | 8 + .../StronglyConnectedComponentAlgorithm.cs | 158 + ...tronglyConnectedComponentAlgorithm.cs.meta | 8 + .../Algorithms/TopologicalSortAlgorithm.cs | 87 + .../TopologicalSortAlgorithm.cs.meta | 8 + ...UndirectedFirstTopologicalSortAlgorithm.cs | 113 + ...ectedFirstTopologicalSortAlgorithm.cs.meta | 8 + .../UndirectedTopologicalSortAlgorithm.cs | 88 + ...UndirectedTopologicalSortAlgorithm.cs.meta | 8 + .../VertexAdjacencyMatrixBuilderAlgorithm.cs | 58 + ...texAdjacencyMatrixBuilderAlgorithm.cs.meta | 8 + .../WeaklyConnectedComponentsAlgorithm.cs | 102 + ...WeaklyConnectedComponentsAlgorithm.cs.meta | 8 + .../matrixsizemistmatchexception.cs | 24 + .../matrixsizemistmatchexception.cs.meta | 8 + .../Runtime/QuickGraph/BidirectionalGraph.cs | 628 + .../QuickGraph/BidirectionalGraph.cs.meta | 8 + .../QuickGraph/BidirectionalMatrixGraph.cs | 363 + .../BidirectionalMatrixGraph.cs.meta | 8 + .../Runtime/QuickGraph/Collections.meta | 5 + .../QuickGraph/Collections/BinaryHeap.cs | 291 + .../QuickGraph/Collections/BinaryHeap.cs.meta | 8 + .../Runtime/QuickGraph/Collections/IQueue.cs | 16 + .../QuickGraph/Collections/IQueue.cs.meta | 8 + .../Collections/PriorithizedQueue.cs | 66 + .../Collections/PriorithizedQueue.cs.meta | 8 + .../QuickGraph/Collections/PriorityQueue.cs | 112 + .../Collections/PriorityQueue.cs.meta | 8 + .../Runtime/QuickGraph/Collections/Queue.cs | 12 + .../QuickGraph/Collections/Queue.cs.meta | 8 + .../Runtime/QuickGraph/CreateEdgeDelegate.cs | 10 + .../QuickGraph/CreateEdgeDelegate.cs.meta | 8 + .../QuickGraph/CreateVertexDelegate.cs | 8 + .../QuickGraph/CreateVertexDelegate.cs.meta | 8 + .../Runtime/QuickGraph/Diagrams.meta | 5 + .../Diagrams/TraversalInterfaces.cd | 67 + .../Diagrams/TraversalInterfaces.cd.meta | 4 + .../Runtime/QuickGraph/Edge.cs | 40 + .../Runtime/QuickGraph/Edge.cs.meta | 8 + .../Runtime/QuickGraph/EdgeEdgeEventArgs.cs | 34 + .../QuickGraph/EdgeEdgeEventArgs.cs.meta | 8 + .../Runtime/QuickGraph/EdgeEventArgs.cs | 27 + .../Runtime/QuickGraph/EdgeEventArgs.cs.meta | 8 + .../Runtime/QuickGraph/EdgeFactory.cs | 13 + .../Runtime/QuickGraph/EdgeFactory.cs.meta | 8 + .../Runtime/QuickGraph/EdgeListGraph.cs | 135 + .../Runtime/QuickGraph/EdgeListGraph.cs.meta | 8 + .../QuickGraph/EdgeNotFoundException.cs | 26 + .../QuickGraph/EdgeNotFoundException.cs.meta | 8 + .../Runtime/QuickGraph/FactoryCompiler.cs | 121 + .../QuickGraph/FactoryCompiler.cs.meta | 8 + .../Runtime/QuickGraph/GraphColor.cs | 12 + .../Runtime/QuickGraph/GraphColor.cs.meta | 8 + .../Runtime/QuickGraph/GraphContracts.cs | 88 + .../Runtime/QuickGraph/GraphContracts.cs.meta | 8 + .../Runtime/QuickGraph/HashCodeHelper.cs | 56 + .../Runtime/QuickGraph/HashCodeHelper.cs.meta | 8 + .../Runtime/QuickGraph/IBidirectionalGraph.cs | 18 + .../QuickGraph/IBidirectionalGraph.cs.meta | 8 + .../Runtime/QuickGraph/ICloneableEdge.cs | 9 + .../Runtime/QuickGraph/ICloneableEdge.cs.meta | 8 + .../Runtime/QuickGraph/IEdge.cs | 8 + .../Runtime/QuickGraph/IEdge.cs.meta | 8 + .../Runtime/QuickGraph/IEdgeFactory.cs | 9 + .../Runtime/QuickGraph/IEdgeFactory.cs.meta | 8 + .../QuickGraph/IEdgeListAndIncidenceGraph.cs | 8 + .../IEdgeListAndIncidenceGraph.cs.meta | 8 + .../Runtime/QuickGraph/IEdgeListGraph.cs | 11 + .../Runtime/QuickGraph/IEdgeListGraph.cs.meta | 8 + .../Runtime/QuickGraph/IEdgeSet.cs | 17 + .../Runtime/QuickGraph/IEdgeSet.cs.meta | 8 + .../Runtime/QuickGraph/IGraph.cs | 11 + .../Runtime/QuickGraph/IGraph.cs.meta | 8 + .../Runtime/QuickGraph/IHierarchy.cs | 104 + .../Runtime/QuickGraph/IHierarchy.cs.meta | 8 + .../Runtime/QuickGraph/IHyperEdge.cs | 11 + .../Runtime/QuickGraph/IHyperEdge.cs.meta | 8 + .../Runtime/QuickGraph/IIdentifiable.cs | 11 + .../Runtime/QuickGraph/IIdentifiable.cs.meta | 8 + .../QuickGraph/IIdentifiableEdgeFactory.cs | 12 + .../IIdentifiableEdgeFactory.cs.meta | 8 + .../QuickGraph/IIdentifiableVertexFactory.cs | 12 + .../IIdentifiableVertexFactory.cs.meta | 8 + .../Runtime/QuickGraph/IImplicitGraph.cs | 14 + .../Runtime/QuickGraph/IImplicitGraph.cs.meta | 8 + .../Runtime/QuickGraph/IIncidenceGraph.cs | 19 + .../QuickGraph/IIncidenceGraph.cs.meta | 8 + .../Runtime/QuickGraph/IIndexedEnumerable.cs | 16 + .../QuickGraph/IIndexedEnumerable.cs.meta | 8 + .../QuickGraph/IIndexedImplicitGraph.cs | 11 + .../QuickGraph/IIndexedImplicitGraph.cs.meta | 8 + .../QuickGraph/IIndexedVertexListGraph.cs | 12 + .../IIndexedVertexListGraph.cs.meta | 8 + .../QuickGraph/IMutableBidirectionalGraph.cs | 12 + .../IMutableBidirectionalGraph.cs.meta | 8 + .../QuickGraph/IMutableEdgeListGraph.cs | 21 + .../QuickGraph/IMutableEdgeListGraph.cs.meta | 8 + .../Runtime/QuickGraph/IMutableGraph.cs | 10 + .../Runtime/QuickGraph/IMutableGraph.cs.meta | 8 + .../QuickGraph/IMutableIncidenceGraph.cs | 17 + .../QuickGraph/IMutableIncidenceGraph.cs.meta | 8 + .../QuickGraph/IMutableUndirectedGraph.cs | 15 + .../IMutableUndirectedGraph.cs.meta | 8 + .../IMutableVertexAndEdgeListGraph.cs | 13 + .../IMutableVertexAndEdgeListGraph.cs.meta | 8 + .../QuickGraph/IMutableVertexListGraph.cs | 24 + .../IMutableVertexListGraph.cs.meta | 8 + .../Runtime/QuickGraph/IPredicate.cs | 9 + .../Runtime/QuickGraph/IPredicate.cs.meta | 8 + .../Runtime/QuickGraph/IUndirectedGraph.cs | 18 + .../QuickGraph/IUndirectedGraph.cs.meta | 8 + .../QuickGraph/IVertexAndEdgeListGraph.cs | 11 + .../IVertexAndEdgeListGraph.cs.meta | 8 + .../Runtime/QuickGraph/IVertexAndEdgeSet.cs | 13 + .../QuickGraph/IVertexAndEdgeSet.cs.meta | 8 + .../Runtime/QuickGraph/IVertexFactory.cs | 9 + .../Runtime/QuickGraph/IVertexFactory.cs.meta | 8 + .../Runtime/QuickGraph/IVertexListGraph.cs | 12 + .../QuickGraph/IVertexListGraph.cs.meta | 8 + .../Runtime/QuickGraph/IVertexSet.cs | 14 + .../Runtime/QuickGraph/IVertexSet.cs.meta | 8 + .../Runtime/QuickGraph/IView.cs | 14 + .../Runtime/QuickGraph/IView.cs.meta | 8 + .../Runtime/QuickGraph/IdentifiableEdge.cs | 33 + .../QuickGraph/IdentifiableEdge.cs.meta | 8 + .../Runtime/QuickGraph/IdentifiableVertex.cs | 34 + .../QuickGraph/IdentifiableVertex.cs.meta | 8 + .../Runtime/QuickGraph/IntVertexFactory.cs | 17 + .../QuickGraph/IntVertexFactory.cs.meta | 8 + .../Runtime/QuickGraph/NamedEdge.cs | 26 + .../Runtime/QuickGraph/NamedEdge.cs.meta | 8 + .../QuickGraph/NonAcyclicGraphException.cs | 17 + .../NonAcyclicGraphException.cs.meta | 8 + .../NotStronglyConnectedGraphException.cs | 14 + ...NotStronglyConnectedGraphException.cs.meta | 8 + .../ParallelEdgeNotAllowedException.cs | 15 + .../ParallelEdgeNotAllowedException.cs.meta | 8 + .../Runtime/QuickGraph/Petri.meta | 5 + .../Petri/AllwaysTrueConditionExpression.cs | 14 + .../AllwaysTrueConditionExpression.cs.meta | 8 + .../Runtime/QuickGraph/Petri/Arc.cs | 73 + .../Runtime/QuickGraph/Petri/Arc.cs.meta | 8 + .../Runtime/QuickGraph/Petri/IArc.cs | 72 + .../Runtime/QuickGraph/Petri/IArc.cs.meta | 8 + .../QuickGraph/Petri/IConditionExpression.cs | 10 + .../Petri/IConditionExpression.cs.meta | 8 + .../Runtime/QuickGraph/Petri/IExpression.cs | 10 + .../QuickGraph/Petri/IExpression.cs.meta | 8 + .../QuickGraph/Petri/IMutablePetriNet.cs | 12 + .../QuickGraph/Petri/IMutablePetriNet.cs.meta | 8 + .../Runtime/QuickGraph/Petri/IPetriGraph.cs | 7 + .../QuickGraph/Petri/IPetriGraph.cs.meta | 8 + .../Runtime/QuickGraph/Petri/IPetriNet.cs | 43 + .../QuickGraph/Petri/IPetriNet.cs.meta | 8 + .../Runtime/QuickGraph/Petri/IPetriVertex.cs | 18 + .../QuickGraph/Petri/IPetriVertex.cs.meta | 8 + .../Runtime/QuickGraph/Petri/IPlace.cs | 27 + .../Runtime/QuickGraph/Petri/IPlace.cs.meta | 8 + .../Runtime/QuickGraph/Petri/ITransition.cs | 20 + .../QuickGraph/Petri/ITransition.cs.meta | 8 + .../QuickGraph/Petri/IdentityExpression.cs | 13 + .../Petri/IdentityExpression.cs.meta | 8 + .../Runtime/QuickGraph/Petri/PetriGraph.cs | 14 + .../QuickGraph/Petri/PetriGraph.cs.meta | 8 + .../Runtime/QuickGraph/Petri/PetriNet.cs | 104 + .../Runtime/QuickGraph/Petri/PetriNet.cs.meta | 8 + .../QuickGraph/Petri/PetriNetSimulator.cs | 109 + .../Petri/PetriNetSimulator.cs.meta | 8 + .../Runtime/QuickGraph/Petri/Place.cs | 49 + .../Runtime/QuickGraph/Petri/Place.cs.meta | 8 + .../Runtime/QuickGraph/Petri/Transition.cs | 36 + .../QuickGraph/Petri/Transition.cs.meta | 8 + .../Runtime/QuickGraph/Predicates.meta | 5 + .../QuickGraph/Predicates/AnyEdgePredicate.cs | 14 + .../Predicates/AnyEdgePredicate.cs.meta | 8 + .../Predicates/AnyVertexPredicate.cs | 13 + .../Predicates/AnyVertexPredicate.cs.meta | 8 + .../Predicates/FilteredBidirectionalGraph.cs | 92 + .../FilteredBidirectionalGraph.cs.meta | 8 + .../Predicates/FilteredEdgeListGraph.cs | 71 + .../Predicates/FilteredEdgeListGraph.cs.meta | 8 + .../QuickGraph/Predicates/FilteredGraph.cs | 81 + .../Predicates/FilteredGraph.cs.meta | 8 + .../Predicates/FilteredImplicitGraph.cs | 47 + .../Predicates/FilteredImplicitGraph.cs.meta | 8 + .../Predicates/FilteredIncidenceGraph.cs | 80 + .../Predicates/FilteredIncidenceGraph.cs.meta | 8 + .../Predicates/FilteredUndirectedGraph.cs | 161 + .../FilteredUndirectedGraph.cs.meta | 8 + .../FilteredVertexAndEdgeListGraph.cs | 69 + .../FilteredVertexAndEdgeListGraph.cs.meta | 8 + .../Predicates/FilteredVertexListGraph.cs | 58 + .../FilteredVertexListGraph.cs.meta | 8 + .../Predicates/InDictionaryVertexPredicate.cs | 24 + .../InDictionaryVertexPredicate.cs.meta | 8 + .../Predicates/IsolatedVertexPredicate.cs | 21 + .../IsolatedVertexPredicate.cs.meta | 8 + .../Predicates/ResidualEdgePrediate.cs | 35 + .../Predicates/ResidualEdgePrediate.cs.meta | 8 + .../ReversedResidualEdgePredicate.cs | 54 + .../ReversedResidualEdgePredicate.cs.meta | 8 + .../Predicates/SinkVertexPredicate.cs | 23 + .../Predicates/SinkVertexPredicate.cs.meta | 8 + .../Runtime/QuickGraph/QuickGraph.csproj | 273 + .../Runtime/QuickGraph/QuickGraph.csproj.meta | 4 + .../QuickGraph/QuickGraph.csproj.vspscc | 10 + .../QuickGraph/QuickGraph.csproj.vspscc.meta | 4 + .../QuickGraph/QuickGraphResourceManager.cs | 35 + .../QuickGraphResourceManager.cs.meta | 8 + .../ReversedBidirectionalListGraph.cs | 175 + .../ReversedBidirectionalListGraph.cs.meta | 8 + .../Runtime/QuickGraph/ReversedEdge.cs | 55 + .../Runtime/QuickGraph/ReversedEdge.cs.meta | 8 + .../RootVertexNotSpecifiedException.cs | 15 + .../RootVertexNotSpecifiedException.cs.meta | 8 + .../Runtime/QuickGraph/Serialization.meta | 5 + .../Serialization/GraphMLSerializer.cs | 702 + .../Serialization/GraphMLSerializer.cs.meta | 8 + .../Serialization/SerializationHelper.cs | 39 + .../Serialization/SerializationHelper.cs.meta | 8 + .../Serialization/SerializerBase.cs | 17 + .../Serialization/SerializerBase.cs.meta | 8 + .../Runtime/QuickGraph/TaggedEdge.cs | 37 + .../Runtime/QuickGraph/TaggedEdge.cs.meta | 8 + .../Runtime/QuickGraph/TraversalHelper.cs | 25 + .../QuickGraph/TraversalHelper.cs.meta | 8 + .../UndirectedBidirectionalGraph.cs | 126 + .../UndirectedBidirectionalGraph.cs.meta | 8 + .../Runtime/QuickGraph/UndirectedGraph.cs | 302 + .../QuickGraph/UndirectedGraph.cs.meta | 8 + .../Runtime/QuickGraph/VertexEventArgs.cs | 24 + .../QuickGraph/VertexEventArgs.cs.meta | 8 + .../QuickGraph/VertexNotConnectedException.cs | 18 + .../VertexNotConnectedException.cs.meta | 8 + .../QuickGraph/VertexNotFoundException.cs | 15 + .../VertexNotFoundException.cs.meta | 8 + .../Runtime/QuickGraph/quickgraph.banner.png | Bin 0 -> 8655 bytes .../QuickGraph/quickgraph.banner.png.meta | 46 + .../Runtime/QuickGraph/quickgraph.png | Bin 0 -> 4297 bytes .../Runtime/QuickGraph/quickgraph.png.meta | 46 + .../Runtime/QuickGraph/quickgraph.snk | Bin 0 -> 596 bytes .../Runtime/QuickGraph/quickgraph.snk.meta | 4 + src/ProjectSettings/AudioManager.asset | 12 + src/ProjectSettings/DynamicsManager.asset | 15 + src/ProjectSettings/EditorBuildSettings.asset | 7 + src/ProjectSettings/EditorSettings.asset | 12 + src/ProjectSettings/GraphicsSettings.asset | 7 + src/ProjectSettings/InputManager.asset | 246 + src/ProjectSettings/NavMeshLayers.asset | 133 + src/ProjectSettings/NetworkManager.asset | 8 + src/ProjectSettings/Physics2DSettings.asset | 21 + src/ProjectSettings/ProjectSettings.asset | 226 + src/ProjectSettings/QualitySettings.asset | 140 + src/ProjectSettings/TagManager.asset | 43 + src/ProjectSettings/TimeManager.asset | 8 + 1456 files changed, 266735 insertions(+) create mode 100644 .gitignore create mode 100644 License.txt create mode 100644 src/Assets/UnityTestTools.meta create mode 100644 src/Assets/UnityTestTools/Assertions.meta create mode 100644 src/Assets/UnityTestTools/Assertions/AssertionComponent.cs create mode 100644 src/Assets/UnityTestTools/Assertions/AssertionComponent.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/AssertionException.cs create mode 100644 src/Assets/UnityTestTools/Assertions/AssertionException.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Assertions.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Assertions.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/CheckMethod.cs create mode 100644 src/Assets/UnityTestTools/Assertions/CheckMethod.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs create mode 100644 src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/InvalidPathException.cs create mode 100644 src/Assets/UnityTestTools/Assertions/InvalidPathException.cs.meta create mode 100644 src/Assets/UnityTestTools/Assertions/MemberResolver.cs create mode 100644 src/Assets/UnityTestTools/Assertions/MemberResolver.cs.meta create mode 100644 src/Assets/UnityTestTools/Common.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/Icons.cs create mode 100644 src/Assets/UnityTestTools/Common/Editor/Icons.cs.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/Styles.cs create mode 100644 src/Assets/UnityTestTools/Common/Editor/Styles.cs.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/create-darktheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/create-darktheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/create-lighttheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/create-lighttheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/failed.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/failed.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/ignored.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/ignored.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/inconclusive.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/inconclusive.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/normal.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/normal.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/options-darktheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/options-darktheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/options-lighttheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/options-lighttheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/passed.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/passed.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play-darktheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play-darktheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play-lighttheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play-lighttheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play_selected-darktheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play_selected-darktheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play_selected-lighttheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/play_selected-lighttheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/rerun-darktheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/rerun-darktheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/rerun-lighttheme.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/rerun-lighttheme.png.meta create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/stopwatch.png create mode 100644 src/Assets/UnityTestTools/Common/Editor/icons/stopwatch.png.meta create mode 100644 src/Assets/UnityTestTools/Common/ITestResult.cs create mode 100644 src/Assets/UnityTestTools/Common/ITestResult.cs.meta create mode 100644 src/Assets/UnityTestTools/Common/ResultWriter.meta create mode 100644 src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs create mode 100644 src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs.meta create mode 100644 src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs create mode 100644 src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs.meta create mode 100644 src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs create mode 100644 src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs.meta create mode 100644 src/Assets/UnityTestTools/Common/TestResultState.cs create mode 100644 src/Assets/UnityTestTools/Common/TestResultState.cs.meta create mode 100644 src/Assets/UnityTestTools/Docs.meta create mode 100644 src/Assets/UnityTestTools/Docs/UnityTestTools-en.pdf create mode 100644 src/Assets/UnityTestTools/Docs/UnityTestTools-en.pdf.meta create mode 100644 src/Assets/UnityTestTools/Docs/UnityTestTools-ja.pdf create mode 100644 src/Assets/UnityTestTools/Docs/UnityTestTools-ja.pdf.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionFailure.prefab create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionFailure.prefab.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionSuccess.prefab create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionSuccess.prefab.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/green.mat create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/green.mat.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/red.mat create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/red.mat.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/green.png create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/green.png.meta create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/red.png create mode 100644 src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/red.png.meta create mode 100644 src/Assets/UnityTestTools/LICENSE.txt create mode 100644 src/Assets/UnityTestTools/LICENSE.txt.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/Batch.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/Batch.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.Mdb.dll create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.Mdb.dll.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.dll create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.dll.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.dll create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.dll.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.interfaces.dll create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.interfaces.dll.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.framework.dll create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.framework.dll.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/GroupLine.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/GroupLine.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs.meta create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs create mode 100644 src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs.meta create mode 100644 src/Assets/UnityTestTools/changelog.txt create mode 100644 src/Assets/UnityTestTools/changelog.txt.meta create mode 100644 src/Assets/quickgraph4unity.meta create mode 100644 src/Assets/quickgraph4unity/Editor.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentAfterMoveNextFinished.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentAfterMoveNextFinished.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentBeforeMoveNext.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentBeforeMoveNext.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndCurrentAndModify.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndCurrentAndModify.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndMoveNextAndModify.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndMoveNextAndModify.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndResetAndModify.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndResetAndModify.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndDoubleForEach.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndDoubleForEach.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndEnumerateUntyped.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndEnumerateUntyped.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndMoveNextAndReset.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndMoveNextAndReset.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.Constructor.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.Constructor.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.Insert.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.Insert.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndEnumerate.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndEnumerate.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndIndexOf.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndIndexOf.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndMinimum.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndMinimum.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAt.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAt.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAtAll.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAtAll.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveMinimum.g.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveMinimum.g.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data/unit.sql create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data/unit.sql.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Fixture.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Fixture.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IDataProvider.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IDataProvider.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixture.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixture.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogError.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogError.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogMessage.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogMessage.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogWarning.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogWarning.png.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.banner.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.banner.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs.meta create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCase.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCase.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameter.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameter.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.snk create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.snk.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.banner.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.banner.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.png create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.png.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt.meta create mode 100755 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt create mode 100644 src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt.meta create mode 100644 src/Assets/quickgraph4unity/License.txt create mode 100644 src/Assets/quickgraph4unity/License.txt.meta create mode 100644 src/Assets/quickgraph4unity/Runtime.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/quickgraph.snk create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/quickgraph.snk.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/quickgraph.snk create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/quickgraph.snk.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs.meta create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.banner.png create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.banner.png.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.png create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.png.meta create mode 100755 src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.snk create mode 100644 src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.snk.meta create mode 100644 src/ProjectSettings/AudioManager.asset create mode 100644 src/ProjectSettings/DynamicsManager.asset create mode 100644 src/ProjectSettings/EditorBuildSettings.asset create mode 100644 src/ProjectSettings/EditorSettings.asset create mode 100644 src/ProjectSettings/GraphicsSettings.asset create mode 100644 src/ProjectSettings/InputManager.asset create mode 100644 src/ProjectSettings/NavMeshLayers.asset create mode 100644 src/ProjectSettings/NetworkManager.asset create mode 100644 src/ProjectSettings/Physics2DSettings.asset create mode 100644 src/ProjectSettings/ProjectSettings.asset create mode 100644 src/ProjectSettings/QualitySettings.asset create mode 100644 src/ProjectSettings/TagManager.asset create mode 100644 src/ProjectSettings/TimeManager.asset diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40ce0c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +src/Library +src/Temp +src/Assembly-CSharp-Editor-vs.csproj +src/Assembly-CSharp-Editor.csproj +src/Assembly-CSharp-vs.csproj +src/Assembly-CSharp.csproj +src/Assembly-UnityScript-Editor-vs.unityproj +src/Assembly-UnityScript-Editor.unityproj +src/src-csharp.sln +src/src.sln diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..da3dc93 --- /dev/null +++ b/License.txt @@ -0,0 +1,31 @@ +Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. + +1. Definitions + +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the software. + +A "contributor" is any person that distributes its contribution under this license. + +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights + +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. + +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations + +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. + +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. + +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. + +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. + +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. \ No newline at end of file diff --git a/src/Assets/UnityTestTools.meta b/src/Assets/UnityTestTools.meta new file mode 100644 index 0000000..0d30e01 --- /dev/null +++ b/src/Assets/UnityTestTools.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 29ca4a0c0429a4a8287ac4161c22c1b8 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Assertions.meta b/src/Assets/UnityTestTools/Assertions.meta new file mode 100644 index 0000000..229b8b8 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: b27b28700d3365146808b6e082748201 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Assertions/AssertionComponent.cs b/src/Assets/UnityTestTools/Assertions/AssertionComponent.cs new file mode 100644 index 0000000..9c6707c --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/AssertionComponent.cs @@ -0,0 +1,372 @@ +using System; +using System.Collections; +using System.Linq; +using UnityEngine; + +namespace UnityTest +{ + [Serializable] + public class AssertionComponent : MonoBehaviour, AssertionComponentConfigurator + { + [SerializeField] public float checkAfterTime = 1f; + [SerializeField] public bool repeatCheckTime = true; + [SerializeField] public float repeatEveryTime = 1f; + [SerializeField] public int checkAfterFrames = 1; + [SerializeField] public bool repeatCheckFrame = true; + [SerializeField] public int repeatEveryFrame = 1; + [SerializeField] public bool hasFailed; + + [SerializeField] public CheckMethod checkMethods = CheckMethod.Start; + [SerializeField] private ActionBase m_ActionBase; + + [SerializeField] public int checksPerformed = 0; + + private int checkOnFrame = 0; + + private string createdInFilePath; + private int createdInFileLine = -1; + + public ActionBase Action + { + get { return m_ActionBase; } + set + { + m_ActionBase = value; + m_ActionBase.go = gameObject; + } + } + + public UnityEngine.Object GetFailureReferenceObject () + { + if (!string.IsNullOrEmpty (createdInFilePath)) + { + return Resources.LoadAssetAtPath (createdInFilePath, typeof (UnityEngine.Object)); + } + return this; + } + + public string GetCreationLocation () + { + if (!string.IsNullOrEmpty (createdInFilePath)) + { + var idx = createdInFilePath.LastIndexOf ("\\") + 1; + return string.Format ("{0}, line {1} ({2})", createdInFilePath.Substring (idx), createdInFileLine, createdInFilePath); + } + return ""; + } + + public void Awake () + { + if (!Debug.isDebugBuild) + Destroy (this); + OnComponentCopy (); + } + +#if UNITY_EDITOR + public void OnValidate () + { + OnComponentCopy (); + } +#endif + + private void OnComponentCopy () + { + if (m_ActionBase == null) return; + var oldActionList = Resources.FindObjectsOfTypeAll (typeof (AssertionComponent)).Where (o => ((AssertionComponent) o).m_ActionBase == m_ActionBase && o != this); + + //if it's not a copy but a new component don't do anything + if (!oldActionList.Any ()) return; + if (oldActionList.Count () > 1) + Debug.LogWarning ("More than one refence to comparer found. This shouldn't happen"); + + var oldAction = oldActionList.First() as AssertionComponent; + m_ActionBase = oldAction.m_ActionBase.CreateCopy (oldAction.gameObject, gameObject); + } + + public void Start () + { + CheckAssertionFor (CheckMethod.Start); + + if(IsCheckMethodSelected(CheckMethod.AfterPeriodOfTime)) + { + StartCoroutine("CheckPeriodically"); + } + if(IsCheckMethodSelected (CheckMethod.Update)) + { + checkOnFrame = Time.frameCount + checkAfterFrames; + } + } + + public IEnumerator CheckPeriodically() + { + yield return new WaitForSeconds(checkAfterTime); + CheckAssertionFor(CheckMethod.AfterPeriodOfTime); + while (repeatCheckTime) + { + yield return new WaitForSeconds(repeatEveryTime); + CheckAssertionFor(CheckMethod.AfterPeriodOfTime); + } + } + + public bool ShouldCheckOnFrame() + { + if (Time.frameCount > checkOnFrame) + { + if (repeatCheckFrame) + checkOnFrame += repeatEveryFrame; + else + checkOnFrame = Int32.MaxValue; + return true; + } + return false; + } + + public void OnDisable () + { + CheckAssertionFor (CheckMethod.OnDisable); + } + + public void OnEnable () + { + CheckAssertionFor (CheckMethod.OnEnable); + } + + public void OnDestroy () + { + CheckAssertionFor (CheckMethod.OnDestroy); + } + + public void Update () + { + if (IsCheckMethodSelected(CheckMethod.Update) && ShouldCheckOnFrame ()) + { + CheckAssertionFor (CheckMethod.Update); + } + } + + public void FixedUpdate () + { + CheckAssertionFor(CheckMethod.FixedUpdate); + } + + public void LateUpdate () + { + CheckAssertionFor (CheckMethod.LateUpdate); + } + + public void OnControllerColliderHit () + { + CheckAssertionFor (CheckMethod.OnControllerColliderHit); + } + + public void OnParticleCollision () + { + CheckAssertionFor (CheckMethod.OnParticleCollision); + } + + public void OnJointBreak () + { + CheckAssertionFor (CheckMethod.OnJointBreak); + } + + public void OnBecameInvisible () + { + CheckAssertionFor (CheckMethod.OnBecameInvisible); + } + + public void OnBecameVisible () + { + CheckAssertionFor (CheckMethod.OnBecameVisible); + } + + public void OnTriggerEnter () + { + CheckAssertionFor (CheckMethod.OnTriggerEnter); + } + + public void OnTriggerExit () + { + CheckAssertionFor (CheckMethod.OnTriggerExit); + } + + public void OnTriggerStay () + { + CheckAssertionFor (CheckMethod.OnTriggerStay); + } + + public void OnCollisionEnter () + { + CheckAssertionFor (CheckMethod.OnCollisionEnter); + } + + public void OnCollisionExit () + { + CheckAssertionFor (CheckMethod.OnCollisionExit); + } + + public void OnCollisionStay () + { + CheckAssertionFor (CheckMethod.OnCollisionStay); + } + + public void OnTriggerEnter2D () + { + CheckAssertionFor (CheckMethod.OnTriggerEnter2D); + } + + public void OnTriggerExit2D () + { + CheckAssertionFor (CheckMethod.OnTriggerExit2D); + } + + public void OnTriggerStay2D () + { + CheckAssertionFor (CheckMethod.OnTriggerStay2D); + } + + public void OnCollisionEnter2D () + { + CheckAssertionFor (CheckMethod.OnCollisionEnter2D); + } + + public void OnCollisionExit2D () + { + CheckAssertionFor (CheckMethod.OnCollisionExit2D); + } + + public void OnCollisionStay2D () + { + CheckAssertionFor (CheckMethod.OnCollisionStay2D); + } + + private void CheckAssertionFor (CheckMethod checkMethod) + { + if (IsCheckMethodSelected (checkMethod)) + { + Assertions.CheckAssertions (this); + } + } + + public bool IsCheckMethodSelected (CheckMethod method) + { + return method == (checkMethods & method); + } + + + #region Assertion Component create methods + + public static T Create (CheckMethod checkOnMethods, GameObject gameObject, string propertyPath) where T : ActionBase + { + AssertionComponentConfigurator configurator; + return Create (out configurator, checkOnMethods, gameObject, propertyPath); + } + + public static T Create ( out AssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath ) where T : ActionBase + { + return CreateAssertionComponent (out configurator, checkOnMethods, gameObject, propertyPath); + } + + public static T Create ( CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, GameObject gameObject2, string propertyPath2 ) where T : ComparerBase + { + AssertionComponentConfigurator configurator; + return Create (out configurator, checkOnMethods, gameObject, propertyPath, gameObject2, propertyPath2); + } + + public static T Create ( out AssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, GameObject gameObject2, string propertyPath2 ) where T : ComparerBase + { + var comparer = CreateAssertionComponent (out configurator, checkOnMethods, gameObject, propertyPath); + comparer.compareToType = ComparerBase.CompareToType.CompareToObject; + comparer.other = gameObject2; + comparer.otherPropertyPath = propertyPath2; + return comparer; + } + + public static T Create (CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, object constValue) where T : ComparerBase + { + AssertionComponentConfigurator configurator; + return Create (out configurator, checkOnMethods, gameObject, propertyPath, constValue); + } + + public static T Create ( out AssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, object constValue ) where T : ComparerBase + { + var comparer = CreateAssertionComponent (out configurator, checkOnMethods, gameObject, propertyPath); + if (constValue == null) + { + comparer.compareToType = ComparerBase.CompareToType.CompareToNull; + return comparer; + } + comparer.compareToType = ComparerBase.CompareToType.CompareToConstantValue; + comparer.ConstValue = constValue; + return comparer; + } + + private static T CreateAssertionComponent ( out AssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath ) where T : ActionBase + { + var ac = gameObject.AddComponent (); + ac.checkMethods = checkOnMethods; + var comparer = ScriptableObject.CreateInstance (); + ac.Action = comparer; + ac.Action.go = gameObject; + ac.Action.thisPropertyPath = propertyPath; + configurator = ac; + + var stackTrace = new System.Diagnostics.StackTrace (true); + var thisFileName = stackTrace.GetFrame (0).GetFileName (); + for (int i = 1; i < stackTrace.FrameCount; i++) + { + var stackFrame = stackTrace.GetFrame (i); + if (stackFrame.GetFileName () != thisFileName) + { + string filePath = stackFrame.GetFileName ().Substring (Application.dataPath.Length - "Assets".Length); + ac.createdInFilePath = filePath; + ac.createdInFileLine = stackFrame.GetFileLineNumber (); + break; + } + } + return comparer; + } + + #endregion + + #region AssertionComponentConfigurator + public int UpdateCheckStartOnFrame { set { checkAfterFrames = value; } } + public int UpdateCheckRepeatFrequency { set { repeatEveryFrame = value; } } + public bool UpdateCheckRepeat { set { repeatCheckFrame = value; } } + public float TimeCheckStartAfter { set { checkAfterTime = value; } } + public float TimeCheckRepeatFrequency { set { repeatEveryTime = value; } } + public bool TimeCheckRepeat { set { repeatCheckTime = value; } } + public AssertionComponent Component { get { return this; } } + #endregion + } + + public interface AssertionComponentConfigurator + { + /// + /// If the assertion is evaluated in Update, after how many frame should the evaluation start. Deafult is 1 (first frame) + /// + int UpdateCheckStartOnFrame { set; } + /// + /// If the assertion is evaluated in Update and UpdateCheckRepeat is true, how many frame should pass between evaluations + /// + int UpdateCheckRepeatFrequency { set; } + /// + /// If the assertion is evaluated in Update, should the evaluation be repeated after UpdateCheckRepeatFrequency frames + /// + bool UpdateCheckRepeat { set; } + + /// + /// If the assertion is evaluated after a period of time, after how many seconds the first evaluation should be done + /// + float TimeCheckStartAfter { set; } + /// + /// If the assertion is evaluated after a period of time and TimeCheckRepeat is true, after how many seconds should the next evaluation happen + /// + float TimeCheckRepeatFrequency { set; } + /// + /// If the assertion is evaluated after a period, should the evaluation happen again after TimeCheckRepeatFrequency seconds + /// + bool TimeCheckRepeat { set; } + + AssertionComponent Component { get; } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/AssertionComponent.cs.meta b/src/Assets/UnityTestTools/Assertions/AssertionComponent.cs.meta new file mode 100644 index 0000000..26f9ab4 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/AssertionComponent.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8bafa54482a87ac4cbd7ff1bfd1ac93a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/AssertionException.cs b/src/Assets/UnityTestTools/Assertions/AssertionException.cs new file mode 100644 index 0000000..f7a2fad --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/AssertionException.cs @@ -0,0 +1,22 @@ +using System; + +namespace UnityTest +{ + public class AssertionException : Exception + { + private AssertionComponent assertion; + + public AssertionException (AssertionComponent assertion) : base(assertion.Action.GetFailureMessage ()) + { + this.assertion = assertion; + } + + public override string StackTrace + { + get + { + return "Created in " + assertion.GetCreationLocation (); + } + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/AssertionException.cs.meta b/src/Assets/UnityTestTools/Assertions/AssertionException.cs.meta new file mode 100644 index 0000000..9605bf0 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/AssertionException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ef3769ab00d50bc4fbb05a9a91c741d9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Assertions.cs b/src/Assets/UnityTestTools/Assertions/Assertions.cs new file mode 100644 index 0000000..b59edaf --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Assertions.cs @@ -0,0 +1,40 @@ +using UnityEngine; +using Object = UnityEngine.Object; + +namespace UnityTest +{ + public static class Assertions + { + public static void CheckAssertions () + { + var assertions = Object.FindObjectsOfType (typeof (AssertionComponent)) as AssertionComponent[]; + CheckAssertions (assertions); + } + + public static void CheckAssertions (AssertionComponent assertion) + { + CheckAssertions (new[] {assertion}); + } + + public static void CheckAssertions (GameObject gameObject) + { + CheckAssertions (gameObject.GetComponents ()); + } + + public static void CheckAssertions (AssertionComponent[] assertions) + { + if (!Debug.isDebugBuild) + return; + foreach (var assertion in assertions) + { + assertion.checksPerformed++; + var result = assertion.Action.Compare (); + if (!result) + { + assertion.hasFailed = true; + assertion.Action.Fail (assertion); + } + } + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Assertions.cs.meta b/src/Assets/UnityTestTools/Assertions/Assertions.cs.meta new file mode 100644 index 0000000..00878a4 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Assertions.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 85280dad1e618c143bd3fb07a197b469 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/CheckMethod.cs b/src/Assets/UnityTestTools/Assertions/CheckMethod.cs new file mode 100644 index 0000000..06f6830 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/CheckMethod.cs @@ -0,0 +1,32 @@ +namespace UnityTest +{ + [System.Flags] + public enum CheckMethod + { + AfterPeriodOfTime = 1 << 0, + Start = 1 << 1, + Update = 1 << 2, + FixedUpdate = 1 << 3, + LateUpdate = 1 << 4, + OnDestroy = 1 << 5, + OnEnable = 1 << 6, + OnDisable = 1 << 7, + OnControllerColliderHit = 1 << 8, + OnParticleCollision = 1 << 9, + OnJointBreak = 1 << 10, + OnBecameInvisible = 1 << 11, + OnBecameVisible = 1 << 12, + OnTriggerEnter = 1 << 13, + OnTriggerExit = 1 << 14, + OnTriggerStay = 1 << 15, + OnCollisionEnter = 1 << 16, + OnCollisionExit = 1 << 17, + OnCollisionStay = 1 << 18, + OnTriggerEnter2D = 1 << 19, + OnTriggerExit2D = 1 << 20, + OnTriggerStay2D = 1 << 21, + OnCollisionEnter2D = 1 << 22, + OnCollisionExit2D = 1 << 23, + OnCollisionStay2D = 1 << 24, + } +} diff --git a/src/Assets/UnityTestTools/Assertions/CheckMethod.cs.meta b/src/Assets/UnityTestTools/Assertions/CheckMethod.cs.meta new file mode 100644 index 0000000..d3f6ec9 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/CheckMethod.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cbb75d1643c5a55439f8861a827f411b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers.meta b/src/Assets/UnityTestTools/Assertions/Comparers.meta new file mode 100644 index 0000000..15d3a92 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: bb9e10c25f478c84f826ea85b03ec179 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs b/src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs new file mode 100644 index 0000000..47c7b82 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace UnityTest +{ + public abstract class ActionBase : ScriptableObject + { + public GameObject go; + protected object objVal; + + private MemberResolver memberResolver; + + public string thisPropertyPath = ""; + public virtual Type[] GetAccepatbleTypesForA() + { + return null; + } + public virtual int GetDepthOfSearch() { return 2; } + + public virtual string[] GetExcludedFieldNames() + { + return new string[] { }; + } + + public bool Compare () + { + if (memberResolver == null) + memberResolver = new MemberResolver (go, thisPropertyPath); + objVal = memberResolver.GetValue (UseCache); + var result = Compare(objVal); + return result; + } + + protected abstract bool Compare (object objVal); + + virtual protected bool UseCache { get { return false; } } + + public virtual Type GetParameterType() { return typeof(object); } + + public virtual string GetConfigurationDescription () + { + string result = ""; +#if !UNITY_METRO + foreach (var prop in GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Where (info => info.FieldType.IsSerializable)) + { + var value = prop.GetValue (this); + if (value is double) + value = ((double)value).ToString("0.########"); + if (value is float) + value = ((float)value).ToString("0.########"); + result += value + " "; + } +#endif + return result; + } + + IEnumerable GetFields (Type type) + { +#if !UNITY_METRO + return type.GetFields (BindingFlags.Public | BindingFlags.Instance); +#else + return null; +#endif + } + + public ActionBase CreateCopy (GameObject oldGameObject, GameObject newGameObject) + { + var newObj = CreateInstance (GetType ()) as ActionBase; + var fields = GetFields (GetType ()); + foreach (var field in fields) + { + var value = field.GetValue (this); + if (value is GameObject) + { + if (value as GameObject == oldGameObject) + value = newGameObject; + } + field.SetValue (newObj, value); + } + return newObj; + } + + public virtual void Fail ( AssertionComponent assertion ) + { + Debug.LogException (new AssertionException (assertion), assertion.GetFailureReferenceObject()); + } + + public virtual string GetFailureMessage () + { + return GetType ().Name + " assertion failed.\n(" + go + ")." + thisPropertyPath + " failed. Value: " + objVal; + } + + + } + + public abstract class ActionBaseGeneric : ActionBase + { + protected override bool Compare(object objVal) + { + return Compare ((T) objVal); + } + protected abstract bool Compare(T objVal); + + public override Type[] GetAccepatbleTypesForA() + { + return new[] { typeof(T) }; + } + + public override Type GetParameterType () + { + return typeof(T); + } + protected override bool UseCache { get { return true; } } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs.meta new file mode 100644 index 0000000..6d4c3ab --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b4995756bd539804e8143ff1e730f806 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs new file mode 100644 index 0000000..72c079e --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs @@ -0,0 +1,10 @@ +namespace UnityTest +{ + public class BoolComparer : ComparerBaseGeneric + { + protected override bool Compare (bool a, bool b) + { + return a == b; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs.meta new file mode 100644 index 0000000..7ee21b6 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2586c8e41f35d2f4fadde53020bf4207 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs new file mode 100644 index 0000000..d0d18f3 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs @@ -0,0 +1,28 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + public class ColliderComparer : ComparerBaseGeneric + { + public enum CompareType + { + Intersects, + DoesNotIntersect + }; + + public CompareType compareType; + + protected override bool Compare(Bounds a, Bounds b) + { + switch (compareType) + { + case CompareType.Intersects: + return a.Intersects(b); + case CompareType.DoesNotIntersect: + return !a.Intersects(b); + } + throw new Exception(); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs.meta new file mode 100644 index 0000000..ab3aa47 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4eff45b2ac4067b469d7994298341db6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs b/src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs new file mode 100644 index 0000000..ae803ec --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs @@ -0,0 +1,144 @@ +using System; +using UnityEngine; +using Object = System.Object; + +namespace UnityTest +{ + public abstract class ComparerBase : ActionBase + { + public enum CompareToType + { + CompareToObject, + CompareToConstantValue, + CompareToNull + } + + public CompareToType compareToType = CompareToType.CompareToObject; + + public GameObject other; + protected object objOtherVal; + public string otherPropertyPath = ""; + private MemberResolver memberResolverB; + + protected abstract bool Compare (object a, object b); + + protected override bool Compare(object objVal) + { + if (compareToType == CompareToType.CompareToConstantValue) + { + objOtherVal = ConstValue; + } + else if (compareToType == CompareToType.CompareToNull) + { + objOtherVal = null; + } + else + { + if (other == null) + objOtherVal = null; + else + { + if (memberResolverB == null) + memberResolverB = new MemberResolver (other, otherPropertyPath); + objOtherVal = memberResolverB.GetValue (UseCache); + } + } + return Compare (objVal, objOtherVal); + } + + public virtual Type[] GetAccepatbleTypesForB() + { + return null; + } + + #region Const value + + public virtual object ConstValue { get; set; } + public virtual object GetDefaultConstValue() + { + throw new NotImplementedException(); + } + + #endregion + + public override string GetFailureMessage () + { + var message = GetType ().Name + " assertion failed.\n" + go.name + "." + thisPropertyPath + " " + compareToType; + switch (compareToType) + { + case ComparerBase.CompareToType.CompareToObject: + message += " (" + other + ")." + otherPropertyPath + " failed."; + break; + case ComparerBase.CompareToType.CompareToConstantValue: + message += " " + ConstValue + " failed."; + break; + case ComparerBase.CompareToType.CompareToNull: + message += " failed."; + break; + } + message += " Expected: " + objOtherVal + " Actual: " + objVal; + return message; + } + } + + [Serializable] + public abstract class ComparerBaseGeneric : ComparerBaseGeneric + { + } + + [Serializable] + public abstract class ComparerBaseGeneric : ComparerBase + { + public T2 constantValueGeneric = default(T2); + + public override Object ConstValue + { + get + { + return constantValueGeneric; + } + set + { + constantValueGeneric = (T2) value; + } + } + + public override Object GetDefaultConstValue() + { + return default(T2); + } + + static bool IsValueType (Type type) + { +#if !UNITY_METRO + return type.IsValueType; +#else + return false; +#endif + } + + protected override bool Compare(object a, object b) + { + var type = typeof(T2); + if (b == null && IsValueType (type)) + { + throw new ArgumentException("Null was passed to a value-type argument"); + } + return Compare((T1)a, (T2)b); + } + + protected abstract bool Compare(T1 a, T2 b); + + public override Type[] GetAccepatbleTypesForA() + { + return new[] { typeof(T1) }; + } + + public override Type[] GetAccepatbleTypesForB () + { + return new[] {typeof (T2)}; + } + + protected override bool UseCache { get { return true; } } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs.meta new file mode 100644 index 0000000..65909eb --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c86508f389d643b40b6e1d7dcc1d4df2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs new file mode 100644 index 0000000..e4a98b2 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs @@ -0,0 +1,38 @@ +using System; + +namespace UnityTest +{ + public class FloatComparer : ComparerBaseGeneric + { + public enum CompareTypes + { + Equal, + NotEqual, + Greater, + Less + } + + public CompareTypes compareTypes; + public double floatingPointError = 0.0001f; + + protected override bool Compare (float a, float b) + { + switch (compareTypes) + { + case CompareTypes.Equal: + return Math.Abs (a - b) < floatingPointError; + case CompareTypes.NotEqual: + return Math.Abs (a - b) > floatingPointError; + case CompareTypes.Greater: + return a > b; + case CompareTypes.Less: + return a < b; + } + throw new Exception(); + } + public override int GetDepthOfSearch() + { + return 3; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs.meta new file mode 100644 index 0000000..07353ad --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a4928c6c2b973874c8d4e6c9a69bb5b4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs new file mode 100644 index 0000000..a336a3f --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs @@ -0,0 +1,20 @@ +using System; + +namespace UnityTest +{ + public class GeneralComparer : ComparerBase + { + public enum CompareType { AEqualsB, ANotEqualsB } + + public CompareType compareType; + + protected override bool Compare (object a, object b) + { + if(compareType == CompareType.AEqualsB) + return a.Equals (b); + if (compareType == CompareType.ANotEqualsB) + return !a.Equals(b); + throw new Exception(); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs.meta new file mode 100644 index 0000000..6b7edb3 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 902961c69f102f4409c29b9e54258701 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs new file mode 100644 index 0000000..003601b --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs @@ -0,0 +1,39 @@ +using System; + +namespace UnityTest +{ + public class IntComparer : ComparerBaseGeneric + { + public enum CompareType + { + Equal, + NotEqual, + Greater, + GreaterOrEqual, + Less, + LessOrEqual + }; + + public CompareType compareType; + + protected override bool Compare (int a, int b) + { + switch (compareType) + { + case CompareType.Equal: + return a == b; + case CompareType.NotEqual: + return a != b; + case CompareType.Greater: + return a > b; + case CompareType.GreaterOrEqual: + return a >= b; + case CompareType.Less: + return a < b; + case CompareType.LessOrEqual: + return a <= b; + } + throw new Exception (); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs.meta new file mode 100644 index 0000000..64f4fc3 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da4a3a521c5c1494aae123742ca5c8f5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs b/src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs new file mode 100644 index 0000000..01a4eaf --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs @@ -0,0 +1,30 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + public class IsRenderedByCamera : ComparerBaseGeneric + { + public enum CompareType + { + IsVisible, + IsNotVisible, + }; + + public CompareType compareType; + + protected override bool Compare(Renderer renderer, Camera camera) + { + var planes = GeometryUtility.CalculateFrustumPlanes(camera); + var isVisible = GeometryUtility.TestPlanesAABB(planes, renderer.bounds); + switch (compareType) + { + case CompareType.IsVisible: + return isVisible; + case CompareType.IsNotVisible: + return !isVisible; + } + throw new Exception(); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs.meta new file mode 100644 index 0000000..9cfc1f2 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8d45a1674f5e2e04485eafef922fac41 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs new file mode 100644 index 0000000..c337f84 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs @@ -0,0 +1,40 @@ +using System; + +namespace UnityTest +{ + public class StringComparer : ComparerBaseGeneric + { + public enum CompareType + { + Equal, + NotEqual, + Shorter, + Longer + } + + public CompareType compareType; + public StringComparison comparisonType = StringComparison.Ordinal; + public bool ignoreCase = false; + + protected override bool Compare (string a, string b) + { + if (ignoreCase) + { + a = a.ToLower (); + b = b.ToLower (); + } + switch (compareType) + { + case CompareType.Equal: + return String.Compare(a, b, comparisonType) == 0; + case CompareType.NotEqual: + return String.Compare(a, b, comparisonType) != 0; + case CompareType.Longer: + return String.Compare(a, b, comparisonType) > 0; + case CompareType.Shorter: + return String.Compare(a, b, comparisonType) < 0; + } + throw new Exception (); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs.meta new file mode 100644 index 0000000..a414f61 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 58783f051e477fd4e93b42ec7a43bb64 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs new file mode 100644 index 0000000..2ba11fb --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs @@ -0,0 +1,25 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + public class TransformComparer : ComparerBaseGeneric + { + public enum CompareType{ Equals, NotEquals } + + public CompareType compareType; + + protected override bool Compare (Transform a, Transform b) + { + if (compareType == CompareType.Equals) + { + return a.position == b.position; + } + if (compareType == CompareType.NotEquals) + { + return a.position != b.position; + } + throw new Exception(); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs.meta new file mode 100644 index 0000000..f3d72e4 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 927f2d7e4f63632448b2a63d480e601a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs b/src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs new file mode 100644 index 0000000..00835b1 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs @@ -0,0 +1,16 @@ +namespace UnityTest +{ + public class ValueDoesNotChange : ActionBase + { + private object val = null; + + protected override bool Compare (object a) + { + if (val == null) + val = a; + if (!val.Equals (a)) + return false; + return true; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs.meta new file mode 100644 index 0000000..b913d35 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d6d16a58a17940419a1dcbff3c60ca5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs new file mode 100644 index 0000000..cd88f8a --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs @@ -0,0 +1,35 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + public class Vector2Comparer : VectorComparerBase + { + public enum CompareType + { + MagnitudeEquals, + MagnitudeNotEquals + } + + public CompareType compareType; + public float floatingPointError = 0.0001f; + + protected override bool Compare(Vector2 a, Vector2 b) + { + switch (compareType) + { + case CompareType.MagnitudeEquals: + return AreVectorMagnitudeEqual(a.magnitude, + b.magnitude, floatingPointError); + case CompareType.MagnitudeNotEquals: + return !AreVectorMagnitudeEqual(a.magnitude, + b.magnitude, floatingPointError); + } + throw new Exception(); + } + public override int GetDepthOfSearch() + { + return 3; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs.meta new file mode 100644 index 0000000..19ef5d2 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a713db190443e814f8254a5a59014ec4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs new file mode 100644 index 0000000..3a9ff2e --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs @@ -0,0 +1,31 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + public class Vector3Comparer : VectorComparerBase + { + public enum CompareType + { + MagnitudeEquals, + MagnitudeNotEquals + } + + public CompareType compareType; + public double floatingPointError = 0.0001f; + + protected override bool Compare (Vector3 a, Vector3 b) + { + switch (compareType) + { + case CompareType.MagnitudeEquals: + return AreVectorMagnitudeEqual (a.magnitude, + b.magnitude, floatingPointError); + case CompareType.MagnitudeNotEquals: + return !AreVectorMagnitudeEqual (a.magnitude, + b.magnitude, floatingPointError); + } + throw new Exception (); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs.meta new file mode 100644 index 0000000..b871f24 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6febd2d5046657040b3da98b7010ee29 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs b/src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs new file mode 100644 index 0000000..128e98c --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs @@ -0,0 +1,37 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + public class Vector4Comparer : VectorComparerBase + { + public enum CompareType + { + MagnitudeEquals, + MagnitudeNotEquals + } + + public CompareType compareType; + public double floatingPointError; + + protected override bool Compare (Vector4 a, Vector4 b) + { + switch (compareType) + { + case CompareType.MagnitudeEquals: + return AreVectorMagnitudeEqual (a.magnitude, + b.magnitude, + floatingPointError); + case CompareType.MagnitudeNotEquals: + return !AreVectorMagnitudeEqual (a.magnitude, + b.magnitude, + floatingPointError); + } + throw new Exception(); + } + public override int GetDepthOfSearch() + { + return 3; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs.meta new file mode 100644 index 0000000..1e0314f --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 383a85a79f164d04b8a56b0ff4e04cb7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs b/src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs new file mode 100644 index 0000000..acf5108 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs @@ -0,0 +1,16 @@ +using System; + +namespace UnityTest +{ + public abstract class VectorComparerBase : ComparerBaseGeneric + { + protected bool AreVectorMagnitudeEqual (float a, float b, double floatingPointError) + { + if (Math.Abs (a) < floatingPointError && Math.Abs (b) < floatingPointError) + return true; + if (Math.Abs (a - b) < floatingPointError) + return true; + return false; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs.meta b/src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs.meta new file mode 100644 index 0000000..d4da9f7 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b35a237804d5eb42bd8c4e67568ae24 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor.meta b/src/Assets/UnityTestTools/Assertions/Editor.meta new file mode 100644 index 0000000..2fa5238 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: a28bb39b4fb20514990895d9cb4eaea9 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs b/src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs new file mode 100644 index 0000000..1860f7b --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs @@ -0,0 +1,217 @@ +using System; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + [CustomEditor (typeof (AssertionComponent))] + public class AssertionComponentEditor : Editor + { + private readonly DropDownControl comparerDropDown = new DropDownControl(); + + private readonly PropertyPathSelector thisPathSelector = new PropertyPathSelector ("Compare"); + private readonly PropertyPathSelector otherPathSelector = new PropertyPathSelector("Compare to"); + + private bool focusBackToEdit; + + #region GUI Contents + private readonly GUIContent guiCheckAfterTimeGuiContent = new GUIContent ("Check after (seconds)", "After how many seconds the assertion should be checked"); + private readonly GUIContent guiRepeatCheckTimeGuiContent = new GUIContent ("Repeat check", "Should the check be repeated."); + private readonly GUIContent guiRepeatEveryTimeGuiContent = new GUIContent ("Frequency of repetitions", "How often should the check be done"); + private readonly GUIContent guiCheckAfterFramesGuiContent = new GUIContent ("Check after (frames)", "After how many frames the assertion should be checked"); + private readonly GUIContent guiRepeatCheckFrameGuiContent = new GUIContent ("Repeat check", "Should the check be repeated."); + #endregion + + public AssertionComponentEditor() + { + comparerDropDown.convertForButtonLabel = type => type.Name; + comparerDropDown.convertForGUIContent = type => type.Name; + comparerDropDown.ignoreConvertForGUIContent = types => false; + comparerDropDown.tooltip = "Comparer that will be used to compare values and determine the result of assertion."; + + } + + public override void OnInspectorGUI () + { + var script = (AssertionComponent) target; + EditorGUILayout.BeginHorizontal (); + var obj = DrawComparerSelection (script); + script.checkMethods = (CheckMethod)EditorGUILayout.EnumMaskField (script.checkMethods, + EditorStyles.popup, + GUILayout.ExpandWidth (false)); + EditorGUILayout.EndHorizontal (); + + if(script.IsCheckMethodSelected (CheckMethod.AfterPeriodOfTime)) + { + DrawOptionsForAfterPeriodOfTime (script); + } + + if (script.IsCheckMethodSelected(CheckMethod.Update)) + { + DrawOptionsForOnUpdate (script); + } + + if (obj) + { + EditorGUILayout.Space (); + + thisPathSelector.Draw(script.Action.go, script.Action, + script.Action.thisPropertyPath, script.Action.GetAccepatbleTypesForA (), + go => + { + script.Action.go = go; + AssertionExplorerWindow.Reload(); + }, + s => + { + script.Action.thisPropertyPath = s; + AssertionExplorerWindow.Reload(); + }); + + EditorGUILayout.Space (); + + DrawCustomFields (script); + + EditorGUILayout.Space (); + + if (script.Action is ComparerBase) + { + DrawCompareToType (script.Action as ComparerBase); + } + } + } + + private void DrawOptionsForAfterPeriodOfTime (AssertionComponent script) + { + EditorGUILayout.Space (); + script.checkAfterTime = EditorGUILayout.FloatField (guiCheckAfterTimeGuiContent, + script.checkAfterTime); + if (script.checkAfterTime < 0) + script.checkAfterTime = 0; + script.repeatCheckTime = EditorGUILayout.Toggle (guiRepeatCheckTimeGuiContent, + script.repeatCheckTime); + if (script.repeatCheckTime) + { + script.repeatEveryTime = EditorGUILayout.FloatField (guiRepeatEveryTimeGuiContent, + script.repeatEveryTime); + if (script.repeatEveryTime < 0) + script.repeatEveryTime = 0; + } + } + + private void DrawOptionsForOnUpdate (AssertionComponent script) + { + EditorGUILayout.Space (); + script.checkAfterFrames = EditorGUILayout.IntField (guiCheckAfterFramesGuiContent, + script.checkAfterFrames); + if (script.checkAfterFrames < 1) + script.checkAfterFrames = 1; + script.repeatCheckFrame = EditorGUILayout.Toggle (guiRepeatCheckFrameGuiContent, + script.repeatCheckFrame); + if (script.repeatCheckFrame) + { + script.repeatEveryFrame = EditorGUILayout.IntField (guiRepeatEveryTimeGuiContent, + script.repeatEveryFrame); + if (script.repeatEveryFrame < 1) + script.repeatEveryFrame = 1; + } + } + + private void DrawCompareToType (ComparerBase comparer) + { + comparer.compareToType = (ComparerBase.CompareToType) EditorGUILayout.EnumPopup ("Compare to type", + comparer.compareToType, + EditorStyles.popup); + + if (comparer.compareToType == ComparerBase.CompareToType.CompareToConstantValue) + { + try + { + DrawConstCompareField(comparer); + } + catch (NotImplementedException) + { + Debug.LogWarning("This comparer can't compare to static value"); + comparer.compareToType = ComparerBase.CompareToType.CompareToObject; + } + } + else if (comparer.compareToType == ComparerBase.CompareToType.CompareToObject) + { + DrawObjectCompareField(comparer); + } + } + + private void DrawObjectCompareField(ComparerBase comparer) + { + otherPathSelector.Draw(comparer.other, comparer, + comparer.otherPropertyPath, comparer.GetAccepatbleTypesForB(), + go => + { + comparer.other = go; + AssertionExplorerWindow.Reload (); + }, + s => + { + comparer.otherPropertyPath = s; + AssertionExplorerWindow.Reload (); + } + ); + } + + private void DrawConstCompareField(ComparerBase comparer) + { + if (comparer.ConstValue == null) + { + comparer.ConstValue = comparer.GetDefaultConstValue(); + } + + var so = new SerializedObject(comparer); + var sp = so.FindProperty ("constantValueGeneric"); + if (sp != null) + { + EditorGUILayout.PropertyField (sp, new GUIContent("Constant"), true); + so.ApplyModifiedProperties (); + } + } + + private bool DrawComparerSelection (AssertionComponent script) + { + var types = typeof(ActionBase).Assembly.GetTypes(); + var allComparers = types.Where(type => type.IsSubclassOf(typeof(ActionBase)) && !type.IsAbstract).ToArray(); + + if (script.Action == null) + script.Action = (ActionBase)CreateInstance(allComparers.First()); + + comparerDropDown.Draw(script.Action.GetType (), allComparers, + type => + { + if (script.Action == null || script.Action.GetType().Name != type.Name) + { + script.Action = (ActionBase)CreateInstance(type); + AssertionExplorerWindow.Reload (); + } + }); + + return script.Action != null; + } + + private void DrawCustomFields (AssertionComponent script) + { + foreach (var prop in script.Action.GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + { + var type = prop.FieldType; + if (!type.IsSerializable) + continue; + var so = new SerializedObject(script.Action); + var sp = so.FindProperty(prop.Name); + if (sp != null) + { + EditorGUILayout.PropertyField (sp); + so.ApplyModifiedProperties (); + } + } + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs.meta new file mode 100644 index 0000000..eb4174d --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fd1cabf2c45d0a8489635607a6048621 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs b/src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs new file mode 100644 index 0000000..3cb2d71 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + [Serializable] + public class AssertionExplorerWindow : EditorWindow + { + private List allAssertions = new List (); + [SerializeField] + private string filterText = ""; + [SerializeField] + private FilterType filterType; + [SerializeField] + private readonly List foldMarkers = new List (); + [SerializeField] + private GroupByType groupBy; + [SerializeField] + private Vector2 scrollPosition = Vector2.zero; + private DateTime nextReload = DateTime.Now; + [SerializeField] + private static bool shouldReload; + [SerializeField] + private ShowType showType; + + public AssertionExplorerWindow () + { + title = "Assertion Explorer"; + } + + public void OnDidOpenScene () + { + ReloadAssertionList (); + } + + public void OnFocus () + { + ReloadAssertionList (); + } + + private void ReloadAssertionList () + { + nextReload = DateTime.Now.AddSeconds (1); + shouldReload = true; + } + + public void OnHierarchyChange () + { + ReloadAssertionList (); + } + + public void OnInspectorUpdate () + { + if (shouldReload && nextReload < DateTime.Now) + { + shouldReload = false; + allAssertions = new List (Resources.FindObjectsOfTypeAll (typeof (AssertionComponent)) as AssertionComponent[]); + Repaint (); + } + } + + public void OnGUI () + { + DrawMenuPanel (); + + scrollPosition = EditorGUILayout.BeginScrollView (scrollPosition); + if (allAssertions != null) + GetResultRendere ().Render (FilterResults (allAssertions, filterText.ToLower ()), foldMarkers); + EditorGUILayout.EndScrollView (); + } + + private IEnumerable FilterResults (List assertionComponents, string text) + { + if (showType == ShowType.ShowDisabled) + assertionComponents = assertionComponents.Where (c => !c.enabled).ToList (); + else if (showType == ShowType.ShowEnabled) + assertionComponents = assertionComponents.Where (c => c.enabled).ToList (); + + if (string.IsNullOrEmpty (text)) + return assertionComponents; + + switch (filterType) + { + case FilterType.ComparerName: + return assertionComponents.Where (c => c.Action.GetType ().Name.ToLower ().Contains (text)); + case FilterType.AttachedGameObject: + return assertionComponents.Where (c => c.gameObject.name.ToLower ().Contains (text)); + case FilterType.FirstComparedGameObjectPath: + return assertionComponents.Where (c => c.Action.thisPropertyPath.ToLower ().Contains (text)); + case FilterType.FirstComparedGameObject: + return assertionComponents.Where (c => c.Action.go != null + && c.Action.go.name.ToLower ().Contains (text)); + case FilterType.SecondComparedGameObjectPath: + return assertionComponents.Where (c => + c.Action is ComparerBase + && (c.Action as ComparerBase).otherPropertyPath.ToLower ().Contains (text)); + case FilterType.SecondComparedGameObject: + return assertionComponents.Where (c => + c.Action is ComparerBase + && (c.Action as ComparerBase).other != null + && (c.Action as ComparerBase).other.name.ToLower ().Contains (text)); + default: + return assertionComponents; + } + } + + private readonly IListRenderer groupByComparerRenderer = new GroupByComparerRenderer (); + private readonly IListRenderer groupByExecutionMethodRenderer = new GroupByExecutionMethodRenderer (); + private readonly IListRenderer groupByGORenderer = new GroupByGORenderer (); + private readonly IListRenderer groupByTestsRenderer = new GroupByTestsRenderer (); + private readonly IListRenderer groupByNothingRenderer = new GroupByNothingRenderer (); + + private IListRenderer GetResultRendere () + { + switch (groupBy) + { + case GroupByType.Comparer: + return groupByComparerRenderer; + case GroupByType.ExecutionMethod: + return groupByExecutionMethodRenderer; + case GroupByType.GameObjects: + return groupByGORenderer; + case GroupByType.Tests: + return groupByTestsRenderer; + case GroupByType.Nothing: + default: + return groupByNothingRenderer; + } + } + + private void DrawMenuPanel () + { + EditorGUILayout.BeginHorizontal (); + EditorGUILayout.LabelField ("Group by", GUILayout.MaxWidth (60)); + groupBy = (GroupByType) EditorGUILayout.EnumPopup (groupBy, GUILayout.MaxWidth (150)); + + GUILayout.FlexibleSpace (); + + showType = (ShowType) EditorGUILayout.EnumPopup (showType, GUILayout.MaxWidth (100)); + + EditorGUILayout.LabelField ("Filter by", GUILayout.MaxWidth (50)); + filterType = (FilterType) EditorGUILayout.EnumPopup (filterType, GUILayout.MaxWidth (100)); + filterText = EditorGUILayout.TextField (filterText, GUILayout.MaxWidth (100)); + if (GUILayout.Button ("clear", GUILayout.ExpandWidth (false))) + filterText = ""; + EditorGUILayout.EndHorizontal (); + } + + [MenuItem ("Unity Test Tools/Assertion Explorer")] + public static AssertionExplorerWindow ShowWindow () + { + var w = GetWindow (typeof (AssertionExplorerWindow)); + w.Show (); + return w as AssertionExplorerWindow; + } + + private enum FilterType + { + ComparerName, + FirstComparedGameObject, + FirstComparedGameObjectPath, + SecondComparedGameObject, + SecondComparedGameObjectPath, + AttachedGameObject + } + + private enum ShowType + { + ShowAll, + ShowEnabled, + ShowDisabled + } + + private enum GroupByType + { + Nothing, + Comparer, + GameObjects, + ExecutionMethod, + Tests + + } + + public static void Reload () + { + shouldReload = true; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs.meta new file mode 100644 index 0000000..f5591ab --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1a1e855053e7e2f46ace1dc93f2036f2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs b/src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs new file mode 100644 index 0000000..d962b28 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs @@ -0,0 +1,255 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + public interface IListRenderer + { + void Render (IEnumerable allAssertions, List foldMarkers); + } + + public abstract class AssertionListRenderer : IListRenderer + { + private static class Styles + { + public static readonly GUIStyle redLabel; + static Styles () + { + redLabel = new GUIStyle (EditorStyles.label); + redLabel.normal.textColor = Color.red; + } + } + + public void Render ( IEnumerable allAssertions, List foldMarkers ) + { + foreach (var grouping in GroupResult (allAssertions)) + { + var key = GetStringKey (grouping.Key); + bool isFolded = foldMarkers.Contains (key); + if (key != "") + { + EditorGUILayout.BeginHorizontal (); + + EditorGUI.BeginChangeCheck (); + isFolded = PrintFoldout (isFolded, + grouping.Key); + if (EditorGUI.EndChangeCheck ()) + { + if (isFolded) + foldMarkers.Add (key); + else + foldMarkers.Remove (key); + } + EditorGUILayout.EndHorizontal (); + if (isFolded) + continue; + } + foreach (var assertionComponent in grouping) + { + EditorGUILayout.BeginVertical (); + EditorGUILayout.BeginHorizontal (); + + if (key != "") + GUILayout.Space (15); + + var assertionKey = assertionComponent.GetHashCode ().ToString (); + bool isDetailsFolded = foldMarkers.Contains (assertionKey); + + EditorGUI.BeginChangeCheck (); + if (GUILayout.Button ("", + EditorStyles.foldout, + GUILayout.Width (15))) + { + isDetailsFolded = !isDetailsFolded; + } + if (EditorGUI.EndChangeCheck ()) + { + if (isDetailsFolded) + foldMarkers.Add (assertionKey); + else + foldMarkers.Remove (assertionKey); + } + PrintFoldedAssertionLine (assertionComponent); + EditorGUILayout.EndHorizontal (); + + if (isDetailsFolded) + { + + EditorGUILayout.BeginHorizontal (); + if (key != "") + GUILayout.Space (15); + PrintAssertionLineDetails (assertionComponent); + EditorGUILayout.EndHorizontal (); + + } + GUILayout.Box ("", new [] {GUILayout.ExpandWidth (true), GUILayout.Height (1)}); + + EditorGUILayout.EndVertical (); + } + } + } + + protected abstract IEnumerable> GroupResult (IEnumerable assertionComponents); + + protected virtual string GetStringKey (T key) + { + return key.GetHashCode ().ToString (); + } + + protected virtual bool PrintFoldout (bool isFolded, T key) + { + var content = new GUIContent (GetFoldoutDisplayName (key)); + var size = EditorStyles.foldout.CalcSize (content); + + var rect = GUILayoutUtility.GetRect (content, + EditorStyles.foldout, + GUILayout.MaxWidth (size.x)); + var res = EditorGUI.Foldout (rect, + !isFolded, + content, + true); + + return !res; + } + + protected virtual string GetFoldoutDisplayName (T key) + { + return key.ToString (); + } + + protected virtual void PrintFoldedAssertionLine (AssertionComponent assertionComponent) + { + EditorGUILayout.BeginHorizontal (); + + EditorGUILayout.BeginVertical (GUILayout.MaxWidth (300)); + EditorGUILayout.BeginHorizontal (GUILayout.MaxWidth (300)); + PrintPath (assertionComponent.Action.go, + assertionComponent.Action.thisPropertyPath); + EditorGUILayout.EndHorizontal (); + EditorGUILayout.EndVertical (); + + EditorGUILayout.BeginVertical (GUILayout.MaxWidth (250)); + var labelStr = assertionComponent.Action.GetType ().Name; + var labelStr2 = assertionComponent.Action.GetConfigurationDescription (); + if (labelStr2 != "") + labelStr += "( " + labelStr2 + ")"; + EditorGUILayout.LabelField (labelStr); + EditorGUILayout.EndVertical (); + + if (assertionComponent.Action is ComparerBase) + { + var comparer = assertionComponent.Action as ComparerBase; + + var otherStrVal = "(no value selected)"; + EditorGUILayout.BeginVertical (); + EditorGUILayout.BeginHorizontal (GUILayout.MaxWidth (300)); + switch (comparer.compareToType) + { + case ComparerBase.CompareToType.CompareToObject: + if (comparer.other != null) + { + PrintPath (comparer.other, + comparer.otherPropertyPath); + } + else + { + EditorGUILayout.LabelField (otherStrVal, + Styles.redLabel); + } + break; + case ComparerBase.CompareToType.CompareToConstantValue: + otherStrVal = comparer.ConstValue.ToString (); + EditorGUILayout.LabelField (otherStrVal); + break; + case ComparerBase.CompareToType.CompareToNull: + otherStrVal = "null"; + EditorGUILayout.LabelField (otherStrVal); + break; + } + EditorGUILayout.EndHorizontal (); + EditorGUILayout.EndVertical (); + } + else + { + EditorGUILayout.LabelField (""); + } + EditorGUILayout.EndHorizontal (); + EditorGUILayout.Space (); + } + + protected virtual void PrintAssertionLineDetails (AssertionComponent assertionComponent) + { + + EditorGUILayout.BeginHorizontal (); + + + EditorGUILayout.BeginVertical (GUILayout.MaxWidth (320)); + EditorGUILayout.BeginHorizontal (); + EditorGUILayout.LabelField ("Attached to", + GUILayout.Width (70)); + var sss = EditorStyles.objectField.CalcSize (new GUIContent (assertionComponent.gameObject.name)); + EditorGUILayout.ObjectField (assertionComponent.gameObject, + typeof (GameObject), + true, + GUILayout.Width (sss.x)); + EditorGUILayout.EndHorizontal (); + EditorGUILayout.EndVertical (); + + + EditorGUILayout.BeginVertical (GUILayout.MaxWidth (250)); + EditorGUILayout.EnumMaskField (assertionComponent.checkMethods, + EditorStyles.popup, + GUILayout.MaxWidth (150)); + EditorGUILayout.EndVertical (); + + + EditorGUILayout.BeginVertical (); + EditorGUILayout.BeginHorizontal (); + EditorGUILayout.LabelField ("Disabled", + GUILayout.Width (55)); + assertionComponent.enabled = !EditorGUILayout.Toggle (!assertionComponent.enabled, + GUILayout.Width (15)); + EditorGUILayout.EndHorizontal (); + EditorGUILayout.EndVertical (); + + EditorGUILayout.EndHorizontal (); + } + + private void PrintPath (GameObject go, string propertyPath) + { + string contentString = ""; + GUIStyle styleThisPath = EditorStyles.label; + if (go != null) + { + var sss = EditorStyles.objectField.CalcSize (new GUIContent (go.name)); + EditorGUILayout.ObjectField ( + go, + typeof (GameObject), + true, + GUILayout.Width (sss.x)); + + if (!string.IsNullOrEmpty (propertyPath)) + contentString = "." + propertyPath; + } + else + { + contentString = "(no value selected)"; + styleThisPath = Styles.redLabel; + } + + var content = new GUIContent (contentString, + contentString); + var rect = GUILayoutUtility.GetRect (content, + EditorStyles.label, + GUILayout.MaxWidth (200)); + + EditorGUI.LabelField (rect, + content, + styleThisPath); + } + + + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs.meta new file mode 100644 index 0000000..8e6a0d4 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d83c02fb0f220344da42a8213ed36cb5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs b/src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs new file mode 100644 index 0000000..e6e53fb --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs @@ -0,0 +1,22 @@ +using UnityEditor.Callbacks; +using UnityEngine; +using UnityTest; + +public class AssertionStripper +{ + [PostProcessScene] + public static void OnPostprocessScene () + { + if (Debug.isDebugBuild) return; + RemoveAssertionsFromGameObjects (); + } + + private static void RemoveAssertionsFromGameObjects () + { + var allAssertions = Resources.FindObjectsOfTypeAll (typeof (AssertionComponent)) as AssertionComponent[]; + foreach (var assertion in allAssertions) + { + Object.DestroyImmediate (assertion); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs.meta new file mode 100644 index 0000000..bf18bbe --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 95c9cd9570a6fba4198b6e4f15e11e5e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs b/src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs new file mode 100644 index 0000000..73b8035 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs @@ -0,0 +1,77 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + [Serializable] + internal class DropDownControl + { + private GUILayoutOption[] buttonLayoutOptions = new [] { GUILayout.ExpandWidth (true) }; + public Func convertForButtonLabel = s => s.ToString (); + public Func convertForGUIContent = s => s.ToString (); + public Func ignoreConvertForGUIContent = t => t.Length <= 40; + public Action printContextMenu = null; + public string tooltip = ""; + + private object selectedValue; + + + public void Draw (T selected, T[] options, Action onValueSelected) + { + Draw (null, + selected, + options, + onValueSelected); + } + + public void Draw(string label, T selected, T[] options, Action onValueSelected) + { + Draw (label, selected, ()=>options, onValueSelected); + } + + public void Draw(string label, T selected, Func loadOptions, Action onValueSelected) + { + if (!string.IsNullOrEmpty (label)) + EditorGUILayout.BeginHorizontal (); + var guiContent = new GUIContent (label); + var labelSize = EditorStyles.label.CalcSize(guiContent); + + if (!string.IsNullOrEmpty(label)) + GUILayout.Label (label, EditorStyles.label, GUILayout.Width (labelSize.x)); + + if (GUILayout.Button(new GUIContent(convertForButtonLabel(selected), tooltip), + EditorStyles.popup, buttonLayoutOptions)) + { + if (Event.current.button == 0) + { + PrintMenu(loadOptions()); + } + else if (printContextMenu!=null && Event.current.button == 1) + printContextMenu (selected); + } + + if (selectedValue != null) + { + onValueSelected ((T) selectedValue); + selectedValue = null; + } + if (!string.IsNullOrEmpty (label)) + EditorGUILayout.EndHorizontal (); + } + + public void PrintMenu (T[] options) + { + var menu = new GenericMenu (); + foreach (var s in options) + { + var localS = s; + menu.AddItem(new GUIContent((ignoreConvertForGUIContent(options) ? localS.ToString() : convertForGUIContent(localS))), + false, + () => { selectedValue = localS;} + ); + } + menu.ShowAsContext (); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs.meta new file mode 100644 index 0000000..424d243 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 83ec3ed09f8f2f34ea7483e055f6d76d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs b/src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs new file mode 100644 index 0000000..00487cb --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace UnityTest +{ + public class GroupByComparerRenderer : AssertionListRenderer + { + protected override IEnumerable> GroupResult (IEnumerable assertionComponents) + { + return assertionComponents.GroupBy (c => c.Action.GetType ()); + } + + protected override string GetStringKey (Type key) + { + return key.Name; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs.meta new file mode 100644 index 0000000..e917399 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: efab536803bd0154a8a7dc78e8767ad9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs b/src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs new file mode 100644 index 0000000..eb0440b --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace UnityTest +{ + public class GroupByExecutionMethodRenderer : AssertionListRenderer + { + protected override IEnumerable> GroupResult (IEnumerable assertionComponents) + { + var enumVals = Enum.GetValues (typeof (CheckMethod)).Cast (); + var pairs = new List (); + + foreach (var checkMethod in enumVals) + { + var components = assertionComponents.Where (c => (c.checkMethods & checkMethod) == checkMethod); + var componentPairs = components.Select ((a) => new CheckFunctionAssertionPair () {checkMethod = checkMethod, assertionComponent = a}); + pairs.AddRange (componentPairs); + } + return pairs.GroupBy (pair => pair.checkMethod, + pair => pair.assertionComponent); + } + + private class CheckFunctionAssertionPair + { + public AssertionComponent assertionComponent; + public CheckMethod checkMethod; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs.meta new file mode 100644 index 0000000..e542ae1 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 97340abf816b1424fa835a4f26bbdc78 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs b/src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs new file mode 100644 index 0000000..45db630 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + public class GroupByGORenderer : AssertionListRenderer + { + protected override IEnumerable> GroupResult (IEnumerable assertionComponents) + { + return assertionComponents.GroupBy (c => c.gameObject); + } + + protected override bool PrintFoldout (bool isFolded, GameObject key) + { + isFolded = base.PrintFoldout (isFolded, + key); + + EditorGUILayout.ObjectField (key, + typeof (GameObject), + true, + GUILayout.ExpandWidth (false)); + + return isFolded; + } + + protected override string GetFoldoutDisplayName (GameObject key) + { + return key.name; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs.meta new file mode 100644 index 0000000..a11d1dc --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cb824de9146b42343a985aaf63beffd1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs b/src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs new file mode 100644 index 0000000..30692a4 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; + +namespace UnityTest +{ + public class GroupByNothingRenderer : AssertionListRenderer + { + protected override IEnumerable> GroupResult (IEnumerable assertionComponents) + { + return assertionComponents.GroupBy (c => ""); + } + + protected override string GetStringKey (string key) + { + return ""; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs.meta new file mode 100644 index 0000000..f7d9d2a --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 33bf96aa461ea1d478bb757c52f51c95 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs b/src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs new file mode 100644 index 0000000..422ff17 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace UnityTest +{ + public class GroupByTestsRenderer : AssertionListRenderer + { + protected override IEnumerable> GroupResult (IEnumerable assertionComponents) + { + return assertionComponents.GroupBy (c => + { + var temp = c.transform; + while (temp != null) + { + if (temp.GetComponent (typeof (TestComponent)) != null) return c.gameObject; + temp = temp.parent.transform; + } + return null; + }); + } + + protected override string GetFoldoutDisplayName (GameObject key) + { + return key.name; + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs.meta new file mode 100644 index 0000000..cbc3124 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5e577f31e55208b4d8a1774b958e6ed5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs b/src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs new file mode 100644 index 0000000..ea9af27 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + public class PropertyPathSelector + { + private readonly DropDownControl thisDropDown = new DropDownControl(); + private readonly Func replaceDotWithSlashAndAddGOGroup = s => s.Replace('.', '/'); + + private readonly string name; + private bool focusBackToEdit; + private SelectedPathError error; + + public PropertyPathSelector (string name) + { + this.name = name; + thisDropDown.convertForGUIContent = replaceDotWithSlashAndAddGOGroup; + thisDropDown.tooltip = "Select path the value you want to be used for comparisment."; + } + + public void Draw(GameObject go, ActionBase comparer, string propertPath, Type[] accepatbleTypes, Action onSelectedGO, Action onSelectedPath) + { + var newGO = (GameObject)EditorGUILayout.ObjectField(name, go, typeof (GameObject), true); + if (newGO != go) + onSelectedGO(newGO); + + if (go != null) + { + var newPath = DrawListOfMethods (go, comparer, propertPath, accepatbleTypes, thisDropDown); + + if (newPath != propertPath) + onSelectedPath (newPath); + } + } + + private string DrawListOfMethods(GameObject go, ActionBase comparer, string propertPath, Type[] accepatbleTypes, DropDownControl dropDown) + { + string result = propertPath; + if (accepatbleTypes == null) + { + result = DrawManualPropertyEditField(go, propertPath, accepatbleTypes, dropDown); + } + else + { + bool isPropertyOrFieldFound = true; + if (string.IsNullOrEmpty(result)) + { + var options = GetFieldsAndProperties (go, comparer, result, accepatbleTypes); + isPropertyOrFieldFound = options.Any (); + if (isPropertyOrFieldFound) + { + result = options.First(); + } + } + + if (isPropertyOrFieldFound) + { + dropDown.Draw (go.name + '.', result, + () => + { + try + { + var options = GetFieldsAndProperties (go, comparer, result, accepatbleTypes); + return options.ToArray (); + } + catch (Exception) + { + Debug.LogWarning ("An exception was thrown while resolving property list. Reseting property path."); + result = ""; + return new string[0]; + } + }, s => result = s); + } + else + { + result = DrawManualPropertyEditField(go, propertPath, accepatbleTypes, dropDown); + } + } + return result; + } + + private static List GetFieldsAndProperties ( GameObject go, ActionBase comparer, string extendPath, Type[] accepatbleTypes ) + { + var propertyResolver = new PropertyResolver {AllowedTypes = accepatbleTypes, ExcludedFieldNames = comparer.GetExcludedFieldNames ()}; + var options = propertyResolver.GetFieldsAndPropertiesFromGameObject (go, comparer.GetDepthOfSearch (), extendPath).ToList (); + options.Sort ((x, y) => + { + if (char.IsLower (x[0])) + return -1; + if (char.IsLower (y[0])) + return 1; + return x.CompareTo (y); + }); + return options; + } + + private string DrawManualPropertyEditField(GameObject go, string propertPath, Type[] acceptableTypes, DropDownControl dropDown) + { + var propertyResolver = new PropertyResolver { AllowedTypes = acceptableTypes }; + IList list; + + var loadProps = new Func (() => + { + try + { + list = propertyResolver.GetFieldsAndPropertiesUnderPath (go, propertPath); + } + catch (ArgumentException) + { + list = propertyResolver.GetFieldsAndPropertiesUnderPath (go, ""); + } + return list.ToArray (); + }); + + EditorGUILayout.BeginHorizontal(); + + var labelSize = EditorStyles.label.CalcSize(new GUIContent(go.name + '.')); + GUILayout.Label (go.name + (propertPath.Length > 0 ? "." : ""), EditorStyles.label, GUILayout.Width (labelSize.x)); + + string btnName = "hintBtn"; + if ( GUI.GetNameOfFocusedControl () == btnName + && Event.current.type == EventType.KeyDown + && Event.current.keyCode == KeyCode.DownArrow) + { + Event.current.Use (); + dropDown.PrintMenu (loadProps ()); + GUI.FocusControl (""); + focusBackToEdit = true; + } + + EditorGUI.BeginChangeCheck (); + GUI.SetNextControlName (btnName); + var result = GUILayout.TextField(propertPath, EditorStyles.textField); + if (EditorGUI.EndChangeCheck ()) + { + error = DoesPropertyExist (go, result); + } + + if (focusBackToEdit) + { + focusBackToEdit = false; + GUI.FocusControl (btnName); + } + + if (GUILayout.Button ("clear", EditorStyles.miniButton, GUILayout.Width (38))) + { + result = ""; + GUI.FocusControl (null); + focusBackToEdit = true; + error = DoesPropertyExist (go, result); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal (); + GUILayout.Label ("", GUILayout.Width (labelSize.x)); + + dropDown.Draw("", result ?? "", loadProps, s => + { + result = s; + GUI.FocusControl (null); + focusBackToEdit = true; + error = DoesPropertyExist (go, result); + }); + EditorGUILayout.EndHorizontal(); + + switch (error) + { + case SelectedPathError.InvalidPath: + EditorGUILayout.HelpBox ("This property does not exist", MessageType.Error); + break; + case SelectedPathError.MissingComponent: + EditorGUILayout.HelpBox ("This property or field is not attached or set. It will fail unless it will be attached before the check is perfomed.", MessageType.Warning); + break; + } + + return result; + } + + private SelectedPathError DoesPropertyExist ( GameObject go, string propertPath ) + { + try + { + object obj; + if(MemberResolver.TryGetValue (go, propertPath, out obj)) + return SelectedPathError.None; + else + return SelectedPathError.InvalidPath; + } + catch (TargetInvocationException e) + { + if(e.InnerException is MissingComponentException) + return SelectedPathError.MissingComponent; + else + throw; + } + } + + private enum SelectedPathError + { + None, + MissingComponent, + InvalidPath + } + } + + +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs.meta new file mode 100644 index 0000000..b1998a8 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6619da1897737044080bdb8bc60eff87 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs b/src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs new file mode 100644 index 0000000..510fd03 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using UnityEngine; + +namespace UnityTest +{ + [Serializable] + public class PropertyResolver + { + public string[] ExcludedFieldNames { get; set; } + public Type[] ExcludedTypes { get; set; } + public Type[] AllowedTypes { get; set; } + + public PropertyResolver () + { + ExcludedFieldNames = new string[] {}; + ExcludedTypes = new Type[] {}; + AllowedTypes = new Type[] {}; + } + + public IList GetFieldsAndPropertiesUnderPath(GameObject go, string propertPath) + { + propertPath = propertPath.Trim (); + if (!PropertyPathIsValid (propertPath)) + { + throw new ArgumentException("Incorrent property path: " + propertPath); + } + + var idx = propertPath.LastIndexOf('.'); + + if (idx < 0) + { + var components = GetFieldsAndPropertiesFromGameObject(go, 2, null); + return components; + } + + var propertyToSearch = propertPath; + Type type = null; + if (MemberResolver.TryGetMemberType (go, propertyToSearch, out type)) + { + idx = propertPath.Length - 1; + } + else + { + propertyToSearch = propertPath.Substring(0, idx); + if (!MemberResolver.TryGetMemberType (go, propertyToSearch, out type)) + { + var components = GetFieldsAndPropertiesFromGameObject(go, 2, null); + return components.Where(s => s.StartsWith(propertPath.Substring(idx + 1))).ToArray(); + } + } + + var resultList = new List(); + var path = ""; + if(propertyToSearch.EndsWith(".")) + propertyToSearch = propertyToSearch.Substring(0, propertyToSearch.Length-1); + foreach(var c in propertyToSearch) + { + if(c == '.') + resultList.Add(path); + path += c; + } + resultList.Add(path); + foreach (var prop in type.GetProperties ().Where(info=>info.GetIndexParameters ().Length==0)) + { + if (prop.Name.StartsWith(propertPath.Substring(idx + 1))) + resultList.Add(propertyToSearch + "." + prop.Name); + } + foreach (var prop in type.GetFields()) + { + if (prop.Name.StartsWith(propertPath.Substring(idx + 1))) + resultList.Add(propertyToSearch + "." + prop.Name); + } + return resultList.ToArray(); + } + + internal bool PropertyPathIsValid ( string propertPath ) + { + if (propertPath.StartsWith (".")) + return false; + if (propertPath.IndexOf ("..") >= 0) + return false; + if (Regex.IsMatch (propertPath, @"\s")) + return false; + return true; + } + + public IList GetFieldsAndPropertiesFromGameObject ( GameObject gameObject, int depthOfSearch, string extendPath ) + { + if(depthOfSearch<1) throw new ArgumentOutOfRangeException("depthOfSearch need to be greater than 0"); + + var goVals = GetPropertiesAndFieldsFromType(typeof(GameObject), + depthOfSearch - 1).Select(s => "gameObject." + s); + + var result = new List(); + if (AllowedTypes == null || !AllowedTypes.Any() || AllowedTypes.Contains(typeof(GameObject))) + result.Add("gameObject"); + result.AddRange (goVals); + + foreach (var componentType in GetAllComponents(gameObject)) + { + if (AllowedTypes == null || !AllowedTypes.Any() || AllowedTypes.Any(t => t.IsAssignableFrom (componentType))) + result.Add(componentType.Name); + + if (depthOfSearch > 1) + { + var vals = GetPropertiesAndFieldsFromType (componentType, depthOfSearch - 1 ); + var valsFullName = vals.Select (s => componentType.Name + "." + s); + result.AddRange (valsFullName); + } + } + + if (!string.IsNullOrEmpty (extendPath)) + { + var memberResolver = new MemberResolver (gameObject, extendPath); + var pathType = memberResolver.GetMemberType (); + var vals = GetPropertiesAndFieldsFromType (pathType, depthOfSearch - 1); + var valsFullName = vals.Select (s => extendPath + "." + s); + result.AddRange (valsFullName); + } + + return result; + } + + private string[] GetPropertiesAndFieldsFromType ( Type type, int level ) + { + level--; + + var result = new List(); + var fields = new List(); + fields.AddRange(type.GetFields().Where (f=>!Attribute.IsDefined (f, typeof (ObsoleteAttribute))).ToArray ()); + fields.AddRange(type.GetProperties().Where (info => info.GetIndexParameters ().Length == 0 && !Attribute.IsDefined (info, typeof (ObsoleteAttribute))).ToArray()); + + foreach (var member in fields) + { + var memberType = GetMemberFieldType(member); + var memberTypeName = memberType.Name; + + if (AllowedTypes == null + || !AllowedTypes.Any() + || (AllowedTypes.Any (t => t.IsAssignableFrom (memberType)) && !ExcludedFieldNames.Contains (memberTypeName))) + { + result.Add(member.Name); + } + + if (level > 0 && IsTypeOrNameNotExcluded(memberType, memberTypeName)) + { + var vals = GetPropertiesAndFieldsFromType(memberType, level); + var valsFullName = vals.Select(s => member.Name + "." + s); + result.AddRange(valsFullName); + } + } + return result.ToArray(); + } + + private Type GetMemberFieldType ( MemberInfo info ) + { + if (info.MemberType == MemberTypes.Property) + return (info as PropertyInfo).PropertyType; + if (info.MemberType == MemberTypes.Field) + return (info as FieldInfo).FieldType; + throw new Exception("Only properties and fields are allowed"); + } + + internal Type[] GetAllComponents ( GameObject gameObject ) + { + var result = new List(); + var components = gameObject.GetComponents(typeof(Component)); + foreach (var component in components) + { + var componentType = component.GetType(); + if (IsTypeOrNameNotExcluded(componentType, null)) + { + result.Add(componentType); + } + } + return result.ToArray(); + } + + private bool IsTypeOrNameNotExcluded(Type memberType, string memberTypeName) + { + return !ExcludedTypes.Contains(memberType) && !ExcludedFieldNames.Contains(memberTypeName); + } + } +} diff --git a/src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs.meta b/src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs.meta new file mode 100644 index 0000000..22210c7 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bbbd193a27920d9478c2a766a7291d72 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/InvalidPathException.cs b/src/Assets/UnityTestTools/Assertions/InvalidPathException.cs new file mode 100644 index 0000000..fb9992d --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/InvalidPathException.cs @@ -0,0 +1,12 @@ +using System; + +namespace UnityTest +{ + public class InvalidPathException : Exception + { + public InvalidPathException (string path) + : base ("Invalid path part " + path) + { + } + } +} \ No newline at end of file diff --git a/src/Assets/UnityTestTools/Assertions/InvalidPathException.cs.meta b/src/Assets/UnityTestTools/Assertions/InvalidPathException.cs.meta new file mode 100644 index 0000000..a5f882d --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/InvalidPathException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b85786dfd1aef544bf8bb873d6a4ebb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Assertions/MemberResolver.cs b/src/Assets/UnityTestTools/Assertions/MemberResolver.cs new file mode 100644 index 0000000..051165f --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/MemberResolver.cs @@ -0,0 +1,217 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text.RegularExpressions; +using UnityEngine; + +namespace UnityTest +{ + public class MemberResolver + { + private object callingObjectRef; + private MemberInfo[] callstack; + private GameObject gameObject; + private string path; + + public MemberResolver (GameObject gameObject, string path) + { + path = path.Trim (); + ValidatePath (path); + + this.gameObject = gameObject; + this.path = path.Trim (); + } + + public object GetValue (bool useCache) + { + if (useCache && callingObjectRef!=null) + { + object val = callingObjectRef; + for (int i = 0; i < callstack.Length;i++) + val = GetValueFromMember (val, callstack[i]); + return val; + } + + object result = GetBaseObject (); + var fullCallStack = GetCallstack (); + + callingObjectRef = result; + var tempCallstack = new List (); + for (int i = 0; i < fullCallStack.Length; i++ ) + { + var member = fullCallStack[i]; + result = GetValueFromMember (result, member); + tempCallstack.Add (member); + if(result==null) return null; + if (!IsValueType (result.GetType ())) + { + tempCallstack.Clear (); + callingObjectRef = result; + } + } + callstack = tempCallstack.ToArray (); + return result; + } + + public Type GetMemberType () + { + var callstack = GetCallstack (); + if (callstack.Length == 0) return GetBaseObject().GetType(); + + var member = callstack[callstack.Length - 1]; + if (member is FieldInfo) + return (member as FieldInfo).FieldType; + if (member is MethodInfo) + return (member as MethodInfo).ReturnType; + return null; + } + + #region Static wrappers + public static bool TryGetMemberType ( GameObject gameObject, string path, out Type value ) + { + try + { + var mr = new MemberResolver (gameObject, path); + value = mr.GetMemberType (); + return true; + } + catch (InvalidPathException) + { + value = null; + return false; + } + } + + public static bool TryGetValue ( GameObject gameObject, string path, out object value ) + { + try + { + var mr = new MemberResolver (gameObject, path); + value = mr.GetValue (false); + return true; + } + catch (InvalidPathException) + { + value = null; + return false; + } + } + #endregion + + private object GetValueFromMember (object obj, MemberInfo memberInfo) + { + if (memberInfo is FieldInfo) + return (memberInfo as FieldInfo).GetValue (obj); + if (memberInfo is MethodInfo) + return (memberInfo as MethodInfo).Invoke (obj, null); + throw new InvalidPathException (memberInfo.Name); + } + + private object GetBaseObject () + { + if (string.IsNullOrEmpty (path)) return gameObject; + var firstElement = path.Split ('.')[0]; + var comp = gameObject.GetComponent (firstElement); + if (comp != null) + return comp; + else + return gameObject; + } + + private MemberInfo[] GetCallstack () + { + if (path == "") return new MemberInfo[0]; + var propsQueue = new Queue (path.Split ('.')); + + Type type = GetBaseObject ().GetType (); + if (type != typeof(GameObject)) + propsQueue.Dequeue (); + + PropertyInfo propertyTemp = null; + FieldInfo fieldTemp = null; + var list = new List (); + while (propsQueue.Count != 0) + { + var nameToFind = propsQueue.Dequeue (); + fieldTemp = GetField(type,nameToFind); + if (fieldTemp != null) + { + type = fieldTemp.FieldType; + list.Add (fieldTemp); + continue; + } + propertyTemp = GetProperty(type,nameToFind); + if (propertyTemp != null) + { + type = propertyTemp.PropertyType; + var getMethod = GetGetMethod(propertyTemp); + list.Add (getMethod); + continue; + } + throw new InvalidPathException (nameToFind); + } + return list.ToArray (); + } + + private Type GetTypeFromMember ( MemberInfo memberInfo ) + { + if (memberInfo is FieldInfo) + return (memberInfo as FieldInfo).FieldType; + if (memberInfo is MethodInfo) + return (memberInfo as MethodInfo).ReturnType; + throw new InvalidPathException (memberInfo.Name); + } + + private void ValidatePath (string path) + { + bool invalid = false; + if (path.StartsWith (".") || path.EndsWith (".")) + invalid = true; + if (path.IndexOf ("..") >= 0) + invalid = true; + if (Regex.IsMatch (path, @"\s")) + invalid = true; + + if (invalid) + throw new InvalidPathException (path); + } + + private static bool IsValueType(Type type) + { + #if !UNITY_METRO + return type.IsValueType; + #else + return false; + #endif + } + + private static FieldInfo GetField (Type type, string fieldName) + { + #if !UNITY_METRO + return type.GetField (fieldName); + #else + return null; + #endif + } + + private static PropertyInfo GetProperty (Type type, string propertyName) + { + #if !UNITY_METRO + return type.GetProperty (propertyName); + #else + return null; + #endif + } + + private static MethodInfo GetGetMethod (PropertyInfo propertyInfo) + { + #if !UNITY_METRO + return propertyInfo.GetGetMethod (); + #else + return null; + #endif + } + + } + +} diff --git a/src/Assets/UnityTestTools/Assertions/MemberResolver.cs.meta b/src/Assets/UnityTestTools/Assertions/MemberResolver.cs.meta new file mode 100644 index 0000000..6b1ea42 --- /dev/null +++ b/src/Assets/UnityTestTools/Assertions/MemberResolver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 80df8ef907961e34dbcc7c89b22729b9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Common.meta b/src/Assets/UnityTestTools/Common.meta new file mode 100644 index 0000000..5f0acfe --- /dev/null +++ b/src/Assets/UnityTestTools/Common.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: a2caba6436df568499c84c1c607ce766 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor.meta b/src/Assets/UnityTestTools/Common/Editor.meta new file mode 100644 index 0000000..cc14913 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: f4ab061d0035ee545a936bdf8f3f8620 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/Icons.cs b/src/Assets/UnityTestTools/Common/Editor/Icons.cs new file mode 100644 index 0000000..c47d11c --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/Icons.cs @@ -0,0 +1,74 @@ +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + public static class Icons + { + private const string iconsAssetsPathPattern = "Common/Editor/icons/"; + private static string iconsAssetsPath = ""; + + public static readonly Texture2D failImg; + public static readonly Texture2D ignoreImg; + public static readonly Texture2D runImg; + public static readonly Texture2D runFailedImg; + public static readonly Texture2D runAllImg; + public static readonly Texture2D successImg; + public static readonly Texture2D unknownImg; + public static readonly Texture2D inconclusiveImg; + public static readonly Texture2D stopwatchImg; + public static readonly Texture2D plusImg; + public static readonly Texture2D gearImg; + + public static readonly GUIContent guiUnknownImg; + public static readonly GUIContent guiInconclusiveImg; + public static readonly GUIContent guiIgnoreImg; + public static readonly GUIContent guiSuccessImg; + public static readonly GUIContent guiFailImg; + + static Icons () + { + var dirs = Directory.GetDirectories ("Assets", "UnityTestTools", SearchOption.AllDirectories); + if (dirs.Length>0) + iconsAssetsPath = Path.Combine (dirs[0], iconsAssetsPathPattern); + else + Debug.LogWarning ("The UnityTestTools asset folder path is incorrect. If you relocated the tools please change the path accordingly (Icons.cs)."); + + failImg = LoadTexture ("failed.png"); + ignoreImg = LoadTexture("ignored.png"); + successImg = LoadTexture("passed.png"); + unknownImg = LoadTexture("normal.png"); + inconclusiveImg = LoadTexture("inconclusive.png"); + stopwatchImg = LoadTexture("stopwatch.png"); + + if (EditorGUIUtility.isProSkin) + { + runAllImg = LoadTexture ("play-darktheme.png"); + runImg = LoadTexture ("play_selected-darktheme.png"); + runFailedImg = LoadTexture ("rerun-darktheme.png"); + plusImg = LoadTexture ("create-darktheme.png"); + gearImg = LoadTexture ("options-darktheme.png"); + } + else + { + runAllImg = LoadTexture ("play-lighttheme.png"); + runImg = LoadTexture ("play_selected-lighttheme.png"); + runFailedImg = LoadTexture ("rerun-lighttheme.png"); + plusImg = LoadTexture ("create-lighttheme.png"); + gearImg = LoadTexture ("options-lighttheme.png"); + } + + guiUnknownImg = new GUIContent (unknownImg); + guiInconclusiveImg = new GUIContent (inconclusiveImg); + guiIgnoreImg = new GUIContent (ignoreImg); + guiSuccessImg = new GUIContent (successImg); + guiFailImg = new GUIContent (failImg); + } + + private static Texture2D LoadTexture (string fileName) + { + return (Texture2D)Resources.LoadAssetAtPath (iconsAssetsPath + fileName, typeof (Texture2D)); + } + } +} diff --git a/src/Assets/UnityTestTools/Common/Editor/Icons.cs.meta b/src/Assets/UnityTestTools/Common/Editor/Icons.cs.meta new file mode 100644 index 0000000..267269a --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/Icons.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8571844b0c115b84cbe8b3f67e8dec04 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/Styles.cs b/src/Assets/UnityTestTools/Common/Editor/Styles.cs new file mode 100644 index 0000000..9fa41c1 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/Styles.cs @@ -0,0 +1,47 @@ +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + public static class Styles + { + public static GUIStyle buttonLeft; + public static GUIStyle buttonMid; + public static GUIStyle buttonRight; + public static GUIStyle info; + public static GUIStyle testList; + + public static GUIStyle selectedLabel; + public static GUIStyle label; + public static GUIStyle selectedFoldout; + public static GUIStyle foldout; + + private static Color selectedColor = new Color (0.3f, 0.5f, 0.85f); + + static Styles () + { + buttonLeft = GUI.skin.FindStyle (GUI.skin.button.name + "left"); + buttonMid = GUI.skin.FindStyle (GUI.skin.button.name + "mid"); + buttonRight = GUI.skin.FindStyle (GUI.skin.button.name + "right"); + + info = new GUIStyle (EditorStyles.wordWrappedLabel); + info.wordWrap = false; + info.stretchHeight = true; + info.margin.right = 15; + + testList = new GUIStyle ("CN Box"); + testList.margin.top = 3; + testList.padding.left = 3; + + label = new GUIStyle (EditorStyles.label); + selectedLabel = new GUIStyle (EditorStyles.label); + selectedLabel.active.textColor = selectedLabel.normal.textColor = selectedLabel.onActive.textColor = selectedColor; + + foldout = new GUIStyle (EditorStyles.foldout); + selectedFoldout = new GUIStyle (EditorStyles.foldout); + selectedFoldout.onFocused.textColor = selectedFoldout.focused.textColor = + selectedFoldout.onActive.textColor = selectedFoldout.active.textColor = + selectedFoldout.onNormal.textColor = selectedFoldout.normal.textColor = selectedColor; + } + } +} diff --git a/src/Assets/UnityTestTools/Common/Editor/Styles.cs.meta b/src/Assets/UnityTestTools/Common/Editor/Styles.cs.meta new file mode 100644 index 0000000..294a619 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/Styles.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a8b92379e11501742b1badcbb08da812 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons.meta b/src/Assets/UnityTestTools/Common/Editor/icons.meta new file mode 100644 index 0000000..89852ea --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: e8bb6eae11352f44da0d6d8a8959b69e +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/create-darktheme.png b/src/Assets/UnityTestTools/Common/Editor/icons/create-darktheme.png new file mode 100644 index 0000000000000000000000000000000000000000..2200e3018cd6ff33425691f61834c055ebc67c56 GIT binary patch literal 1520 zcmbVMJCD;!6t;v|tq_O?kf6ab6g+NXkK@?Mum)xAgbm=mt84^|w8hTavx(W*W9-Q$ z*^-V1@fR*X08!jqQBYIx1E8d#xWz@Hx*cZ{C%htpu>6=Aecw6XdH6iuSigDV*tuhp zB%Nrkxh?n}7tit%yzln6KfvcKuW#{9w#Nq~rBW?myHsvQq(fVj1fz$q>53#B-45GZ ze9OCoeHImoz!Zm30&GcIxiL(LzfZZmOFLm~EC0QGrO07mEBDHt<|Pj8hHHl@-8@`x z`-l5}HBfF`msf@u3`CR@c^LKL3=eH(Y!|~?9IJ{vhVXq`nTXo*He`pTR4x}w1z$r* zHq9b3%BG3_kaZ2|ss^`NKn5#{_4Hck1GNBl4r2bYDr zoIzc}sjWcyjDm&=I%*??4Fet$@^G7zVg%Sx(7us#a~)MW|j{bs8nNUac4!vdRt3 znQ~p`_eB|}+~5nhwut*@8p1C`dh=`;72VP6T1|I#&8#3)(e>J@VIm7vEM!>?(WK*M z!E0d#l^Er1zeykFt6nIN`vVhSw6LxCqGmKu^5bw$)C;}l+(DOu!Jm|I;yKIbOsxYM zTHGfpC|AXwHVH!gKEBD`rD=FTgGS0CPy;QAe>W1r4d&EuVHRdWzZwx!?J#%5ayIZ_ zGaH#ShB=wSKzw`c{$&`ZSDJ3EJ$$#j{m+BbN6vgaf2;KDwuYWAFa5Q2=HkispH`@; fJ^6d*=&~l=ezSD;)W83~5Hq-0Uw5Cc?mYSoR7%gU literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/create-darktheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/create-darktheme.png.meta new file mode 100644 index 0000000..3e77d05 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/create-darktheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: a4193b17f22b72546a632f2735b22421 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/create-lighttheme.png b/src/Assets/UnityTestTools/Common/Editor/icons/create-lighttheme.png new file mode 100644 index 0000000000000000000000000000000000000000..faf4d727842b4bfe2fcbb604ade2ceb5462ec0c8 GIT binary patch literal 1520 zcmbVMO^?$?7~S1B8LdHCJLv}DWtBv*2auSxXOq#!9%D~7 z$%+#_RXz0&^x8|+KfnPH5)u+eP8@ow#1V-fQ1MRU1X?0eVfkZb^gQpkpPzSkems5Z z+f$07oNjOX9r%7FpD#AxePeX%6@1Q#=AP*C12HBURT>fBr)oPUecGWUn%;dzHx=dN zE!Nu;d%-mv^0-VSraXyLU@OYzl}Sp%Ln_pL+GmNYy?*deQ(5F{H>-gWq#hlx?cd^`R?C%A zXdtB8b{Sb!+eVjE(?F(fz-^b1g{w9;9ksYL@RmgfxZ}49U$Aqvfe+7gquS*-ISpq~UpC*D#N=bfxVZo<)n6Xqao~Y6y+2g*aWBP4c2lP%wQ$ zQXQ2InbHgxg-cvI%7!!NQK-`)jcFosz@jAJyhP`sc?1y^xvfO!y=hAI z4$b)}3u*HRJf2?!mWvL3SDODp2l$MfVlSga@T|xAaM7^c0T(wt68TAxq@J zMd_|!P@f3uYS2EbWT29XdI(|5!pQ!?K-e(m(11tmVEQ4{#1`DOe?eh(A|l9Ia1`PL zp2Y;p#pJl_Y0{s03j*9uazT=iwtZKFP|J)(xb8S!#q)fpvE?JwtZaF$ir=i)ECV^! zmfJsgleYQ*s^TopqhgmrzMAU zHY|9X<vP)BsW^ozqM6Z2Kt^vEMf=Uk;|pv z!DcC$Gy$E=KoGC?-xwgK-?#lnZ}M{g>$7LWN1y-Wv6lGqyNxrC)fbQM|J}Iv+wade gp8opHAIfJNO1FOE_D{e3^+alLySd~4xpn9MTl{#@*8l(j literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/create-lighttheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/create-lighttheme.png.meta new file mode 100644 index 0000000..2d7a140 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/create-lighttheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 39f371f2ad7a53a4693cc4d50c5f24ca +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/failed.png b/src/Assets/UnityTestTools/Common/Editor/icons/failed.png new file mode 100644 index 0000000000000000000000000000000000000000..7c0aba4c39aadc1b13bce95c85bbd61e2a0aadda GIT binary patch literal 1041 zcmds#KQBXJ6o*e+X{j_FXb4|`fy8X8+@`%1)gTc~B#ptsAi-#{nX8E)Qj=JWHlv{o z5|YMb@+pwi^P|1Fja!?=xq04m-t*_a=RNlx6bsozd?apW2{-2~pp&9E$~xVs=26kL z*{owtJ++&Q3ZA~L+{(6D|9}YD@#!$m*p54wiM@nV$)VA`)$v`k$eHV;m&Q_|N@Vkc zjDIDMW+kY@TMOAG|0TozP1`1^id}l7Jb_C-6Fg?sL1~Ls)paSGi1L8g)&IIyr0I?8|y}`l3LFT}L z1ABmMOaN5GgeeLU0m=yi@l7E10Eu8zxD6<2gv|h;_2ftq=McoIkwo93B7aZsAX1zdmZ^E_P~Lo`GgCo|{#0je05;L|y= x{~(Obb4=I-i4_}(nu!gY0Z>P?cpd=1K&=!{=T1BqYE=Z{db;|#taD0e0suQ^D8c{$ literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/inconclusive.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/inconclusive.png.meta new file mode 100644 index 0000000..910154f --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/inconclusive.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: e28761099904678488cdddf7b6be2ceb +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/normal.png b/src/Assets/UnityTestTools/Common/Editor/icons/normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6a04f7951e1c8cd444038d7c122a43defb042d0d GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^{2Zw`%*J>AM&=;bi^NpnKYnq@(U zSV&Sc5Kk0^985t$nk`*`BN*0oQ%+BslgT}ts1{vhAi8nVW)k&JnmQ1&F<#B$d=6FfYgFbT~0LmKNuxM88Cg?!reZ9CA>Erhr$91;yYh0ix=c zLt|^1B=9Q4oC**%Qj^JXJfi9l_qg0nkpci`Sr=eDEDLtxGzDmqLSNPi7|z3Tv=^^` z2oz11vRo<}tH(mK0FgIMjU&l&x$G*tU8P{GKGppn2uSt(V4lGwy)(|VyAToOrGfJLa7 z2Eu|S7F8*kY{FZ*Ef$+-!{lcWqk3*F(MEb!gJcRC>a;FGeg;JxZV)rf6ueiO`!GlF zstXDqhaHD)l`kVs^O6d7T=x}L|L&Gp0vW%EnrkIVSqsGW1JLl(jW~0 z$1ogVcTj+%s2Vh>N^*Ag-%vNlP#jJD4T`iQ38v5%EQwrJ)r$fumu$(M)RbH`S~AHc z6vGr05hkJm0#S9zvc&Q37){6AUT-Mk0f2XhBQbZB_xl(Mcs(&H(y)!H;a@O z8{UyN)moRgo1^?3-IU)0@vb`;^MaCt=p-bG2hSwz^RS*6&%41oeP1^dhI9Kl#@E;# z|6?Ykb^6tWMgCKBwRsfkGHOvwSBr=rIwrVQ>bjrYEL*9?o@%R1tK?Ope>t`rOXx1J zhRsU|O`6vjR8YrsbV>bII?{__wxL8cl&*ZAxpVjKsNHGXVqZG{ZfA#W(@^Jodp~?_ zL+ZKU3CG~zS;td9ZaR6&UUG~V9DF~v@L1n&`>n^9&!1k-WaE0pxqtPoJquln8_paK z?mQH^VBp_$|9;hz=*N0LwWp2-Pjs&89nY_AJb2o6tF+7?IJk7}yWo`tX-&m1c4y|d zUp%k~f?u1#+kM-*Cl)Hi=5rl4&L-k_62X1+@|k1LnDonoGmj+lwto0|=K7_r!St@R z$j7gCC9h}W;fE%V3>|jZZeM$2bN5%5*8-QQeJ@CrM~@#bj9=-S3OSf9ouOZ`9ZdL% ztGiFx-@JUYe`b8?=ht5v3xS8lnb|Vd3bvD>vS@{thJgvFHck{V)CrAe6Nb literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/options-darktheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/options-darktheme.png.meta new file mode 100644 index 0000000..d6910a1 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/options-darktheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: bbd9485c1fc611b44a4ac1abfdcffbf5 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/options-lighttheme.png b/src/Assets/UnityTestTools/Common/Editor/icons/options-lighttheme.png new file mode 100644 index 0000000000000000000000000000000000000000..e33c43f258d85b27d7eb7a044fe25c31f2cbe423 GIT binary patch literal 2161 zcmb_eTWs4@72h zYE%U(*rpAYX#&d2`cM#)5ZWXjCLw{)`ZCmsPU-_fXhIX31PD>_!ZuZmpikY3dRjz_9Hba$?*VkB)Gnnzaii#$L?kkTr%43>I^OI0+3r2~)D- zC4T+v3j&uVFY&B1N=0)4n3lsc8XTJ$O^7p-qDLYI58?ww4mrp|L%@sKjG}WzFH!c( zp|QD45_lP6OnQk5sqttG52zZ%opy&!qyWHK)(#ja%YvtIngTRQp)YF#4CiDy+J#p? z1d66f6I?tPs>VVyFOfEk97mFcLcv~e*i|h>0*}XI`k-kWLfG_@VhBZ>qW9K31fec! za?X%d1vfnkNi}bH3Bk_ph3YY7L8}RYTR&Y7P&Kv3P$}5M{+&IADgWTEL)SKreyX$Ji)fqd@`y zj$t^!K1BhJqAJj+D#;V2|3V!cLveum2NY>X5)7d!SQ5DjRm%#fT(T*5GN+`<(V|f< zqUeU8h%gfL5{Rl@mL(1_EP_qrHV%}_H%~nFT zydy-@AqV5~1)O)XJ*3HK3kjJ8G)rD4 z`nO}dwuJ5ib6CHG(4>BiK?QY8LzmRJEVf}-OIIZ5OBBCNZr;8<*k)_l*LL#Dk1VHO z!0q-&Eh~rSzUhjrc0Jk2hX;4=dFxzjQpT@tV>b3DR(C~|o`aW9+&Fb$ZRjwb-*dEY zs=xHW$}RGx&yPe;S%zN!W$tv}?o`WpYs+H?Td&DON37{9k0)&xb}X+i%+Iz>?buDu z{kCuJ!hJ`ddwc!6*5{W-Gu9EywPWGUy-U|4;mydu~Q}KC$%T?2_fo z+7CD9)`$Clx5lo%w=Ug!bK)lU{`JcX^Lx+r2Ra?CKV9nWd&v9hhp!y(?RnR7cx`0= z{1Xo@oEbU0cxB@qK6diwh51n**!A(nl>7V#KLUKVePwp&;;OHE<&EQy^e!(>efpL4 dk4|h`H`Zdy$G(;)H_Sf)5q>oIiT~x-{sijwv9|yK literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/options-lighttheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/options-lighttheme.png.meta new file mode 100644 index 0000000..bca33bc --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/options-lighttheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 4e6ebb403e0c3974fbe7cbd6f89ea6a6 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/passed.png b/src/Assets/UnityTestTools/Common/Editor/icons/passed.png new file mode 100644 index 0000000000000000000000000000000000000000..1edd286044323a2188adfa110ac8269ee73376d8 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^{28_{{~`K zAT9>l+6ScJ0DFL0GMoXbD1xd2X*>_alc0PespAZDfv)%j#KuJGpp!D6bafYA#;O+} O>pWfkT-G@yGywqZQ$$Mu literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/passed.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/passed.png.meta new file mode 100644 index 0000000..4c03e10 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/passed.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 31f7928179ee46d4690d274579efb037 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/play-darktheme.png b/src/Assets/UnityTestTools/Common/Editor/icons/play-darktheme.png new file mode 100644 index 0000000000000000000000000000000000000000..c522086449d90f6e00041272f7692f817507963c GIT binary patch literal 2002 zcmd5--*4MQ9CtUCPE|V%X+@<-;JOlG(8NC5ahg-j;=~D!gu5z@L=k(~)xIXC@sHWp z#;Fi=Q>ox@*b9&2g*PN5K%l+x2x2e%2TYo%gm^^aE^#t`q{{>^L{@xv`h31WKfdqB zn;UP;%`DDv95+{AHyiZL*0UEg^#7f`l~3sFc~adbTfr{rq6l+_6YOBV?x7ZLVC3{} zeTUaLE_3QOx5>8kCbR=DhZrW8cp+tT+}gDyMD`vg{0?rpzApUo@Ofqt?F9Qo7igq|6ufX` z){oON(SnHy3Pq5USW11MV~=p*e$?qZcWe=Nu!nsTQ!E%^X_YK%1RrbG^G4{HR1auG zX>McDakCd|C${Szufr3gXc zFHou-2N5(8?AUNOh&)8gqg(`_ zs+21=#jF-rRS6XGHK{V>nt{E~+BoDokGbVZ-0P7`KOxi^XQNUDRYR*4<-9Cus{pLZ zvQbtwPynk1P$<-xNc&=e>uyXt(Mx5&g>R*+j?4G;0g=rltP3{l8Fqy9*d3GgM6W5g z+s4%36WTcN9H;k;(V`WatP}C9$YXTy7iA)9AZ>&&QJJjd z{XqY8Z4Zy=EMUvg5TcvW7{fm8SVV_Z^0oXc9dJqAG@8jzJ2yUm_rV95%*pxEjfKU< z!`oBSH}Cv#sr26azdd~Lduiq9`qJ!`QvR9Cjf>}IN?*NrZ{c|U^y=|#?%vOH{H5g| zmE&(OyqpoHmOgyx=!<6;Iwvd174PWe(fP~MckfScUU=d3ZGGyax$ozf?ygHSQ|D&6 XPw&5)%&X7IY|7TF8|G)_n|J;Ii$P?w literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/play-darktheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/play-darktheme.png.meta new file mode 100644 index 0000000..19fe9a2 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/play-darktheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: ea69579f34a673a46a1a33ca2f473917 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/play-lighttheme.png b/src/Assets/UnityTestTools/Common/Editor/icons/play-lighttheme.png new file mode 100644 index 0000000000000000000000000000000000000000..30207ad89a98319250cda1ab055c7a90c3365f44 GIT binary patch literal 2004 zcmd5-O>Em#9CtU^O4Vv*MMz~A%e(Ng#D2D8Cr{0`)OKhjT%sg`YH;X_{hC;fKWe`; zNe`&wfXa; zgW52wtmcQ9&1I#GB>=!GN*2gDMFAIBQ2-(@&_~Gt8Rirys%-k>sJGDGf;GLI`l7oc z*Cr%@Jm2f}vOOv5hbVnc z_)*&rSgo$GFPg}5y!hay*j>uNIwH8p(e}w10c1qb007D|1j;J{fPyfDn!fF94gLug zp)5f8uTZKT8xb@WY+G>44_!pd<-~I51Fw~MGfi0WB7!^%SM(xBL(Mvl4GXHONt%{Z zORG8nhP0}cCEY0GWdW$UvY?H)x^H#kHjcRVBd#)y`+DfmPY87;+0YDNl$3Ho%!z`M z2OuwsrBzu0D#)uqRm-tR6S2TGC!(Dgq_VH$opjZ4*hC)?S+RtRoE7&B+gy6=Ovrkw z*Oc39V`}g*Z5(=z(tD=Vq7|C16aKi!BeeVYxaFLviH1-T^<%1aY}^u*3Q$l-^7~hD zr^c-|@>-bQggo~jGEx42neg%LHxw5Ccg+p=Iu0G$qH^fFv>5c7fRofEKS6FW*PifA zO;u)G@+8ndUE8B0It$|EcnHzWc#L6>b}XbrYOQte79DVV6}{Bx|JYnyT6%cq=EJLp zw~vmF=5Gi~C!fkQcLzH=ci&;3-~95#N8jIny1Fp)%iMD54QccAx&0e=e*X5uGoO8Y zFn{9Or|P2k?DE^2P4?_!?f%TcxvRg)_E(?Gek~n7cX9va!~O4medcoK;QH*Xnw~(iQxA3gv33Vl_}laUhY=tU4r%hSG#( zsA#>-?_r7{9$wR{HB^(&394m86b}>W8a8GVL~6NfE9wSBWF0njQ>1?X`Z`7Gnn=AC zml@g4!j@jxabRVqR8@C2)TBl&zd)wC0v0eJQpm2+HeI1BQUhH9uf1cMA_ow(AyPx9 zYVs3H3-3g# zg^(@Kbf?pabfOWOnMqD8^(yR+cS~U4V&)bNI`gYDoEtB*VmAbWsL<)O4 z48gF+vZm{&2`7y1DmD!wj2F@XsHtO|z2&qA#x<3OZD>Ffxflz^SezwU9>XWf8pasy zqTDw2$d7Fz+O76%NSC2&Z8<8;ZDWgzBgb4+hJU8!KhQCJK(>Xf0~KUBRm*CR3bxv^ zkma^4o6J@?@{Fvgy6GL9_00JUC@Bbv6fR#Z%z!WpssISFm;kuv7$7jr5Gq@m-snw& z##tfC{|$?Khu9T-8g;n+hdO}AFD4M-!Fu2U#tbcOU?J+-hFp|{gq1xHx>$ah^up}_xQ`f z&1GY?2M{~ENXUJ0jiG3n4ODsMqe);l+kFI+^gJP~E9j&bI{Q)+12`T^p literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-darktheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-darktheme.png.meta new file mode 100644 index 0000000..b5bdc6b --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-darktheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: e0047013a792e5043b411565030f0939 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-lighttheme.png b/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-lighttheme.png new file mode 100644 index 0000000000000000000000000000000000000000..dad238581934e0b4dd5ce1bc9c6d82de386398f1 GIT binary patch literal 1649 zcmbVNO^6#+9G~>dvZh*D(OS?xrY@+v$;_K1ljO0}-E1Z?DV=pm0tWQpWae!$ZsucW z-foh$NV-taJ(NW}d5}FSMSGKiU@tAGh={0&CmRonC`B(?EUa&mNvaZzI1DrIJ$}F6 z|8xHH>dNxd$EHqBF${C8SddHf?XSZ}kI?6HYjb<_^$5vTN!eZ{E!D+LMz?Di6iu~` zOIX!A>mT8HhB^GaQK^!uat>*>8C88uv~4<+%`o!|ZAaDCFab4OH!O+0_5L*$7`nth zn^1Vg$>N4l*m7}sYq_Frt!ZhUT{r{g+lUI7n5dv_HZ2deCAP1N=-NN#SkQ-%HHjTK zRaI6%)^;&SL}L++hY*Nj6vh*x2#h~=FgD#+N=T*D!TZ2@0Vt=StyVyUNt z5KLzzYk5JMXu`O*>Tod1`yus#x;DZ&8*a02T-P|<#3r_gN3n2(rCCyx5qzwyX^zky z$!$`Pg4o8Qy-LTyTnT&jhO6P+Cbf8a=$J=J_-<l#|MT~np$GW>Su9IM{9rYNXrc|^4|T$Cl2x*9bM9m#Soos0|V zWM)Z(Fc(|O=413I73X0xk>|5Ru54=?ei?^c{Vq2%iTjLe&`(Hhj?>7BFqaYYX(1u- zVhX~PAY_)}B22Izg?*urNi`cQO;D_-_(vzPyccM z^;;KGclP)9!&mv~gNK@--tAtm_kFkeX6RmK_WbQ%@!alfOz+g<`Fq~F`e=6M!x#10 z?wzyXW7_g hZx+ryc;L_pM&5kstM6t`J?{Smin(R^-K7_{{{$U?3l0DP literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-lighttheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-lighttheme.png.meta new file mode 100644 index 0000000..193349d --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/play_selected-lighttheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: fa83cb00bb03c834889658b2c3e03259 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/rerun-darktheme.png b/src/Assets/UnityTestTools/Common/Editor/icons/rerun-darktheme.png new file mode 100644 index 0000000000000000000000000000000000000000..07f10b9109b159ed5f000813350dce0141026345 GIT binary patch literal 1767 zcmbVNeP|nH98Nc?wX|DBR60k!-lQrnxqGk4U2<)lNiJ=JOWUQ9RZ#JI_cl43++FT2 zO;Shc=47i>2VG5JNQ>fhjJ8n0FJ@~MtVl)Z)csK=%7nQM)+#C@Q|Ej6no6+Zk-K}} zm*@FCzpwjcw7avtwt7dk#bT)qbZ{Z`-iGd)s+-U=G%~h^UiF5**XU9DjTEmzi$_%Y zAQp)85g3BJm`QvBTP>E#$E0wt(Hq>$3QF9@n;2U2`-5hVK2R$ylxG)pm9;lh!c zCib%-uC1Vjc5Xas7%EE;sZ`3AYPKm_ga9s=%d|mJR)nzX8QI{|R$1Rww7@}K&?ME6 z6d5xu@_kCuaO23+dr|8+*Nc;H$w16YW@Qq!E
ol0Bg6i zfPR1kEJ@~}K}D4MGi9L+3mkugqTUgCgWnV^3T(fk#d(x2$!vE*l_NQ|V2};Sy1~l= z3~+87xoVRnkp&#%bb1(?@px$f{LNlpTQlc(Iqf819Brhp$mJ9vX_m3b6>o5v&A45f zggzlYR?dc(Ln4&l0sIt6I{|P~l*enQ0Rx;2V3;sKeT*}I;@>W-*K>(*XE6kv z#Mx}!&aP8Uum3T!H`?-{=c~i#52?0HAu~0J zonQK(A^ZKR=kvr%@1BTU8NKJ^EnOY29IMzZ&J&fN1*U#$8lS-5TdAI`S&UW&y|-G& z5~6fwhQG6Z{E45h{y2B~?UPGe=Y&w=h54mT~AMd19KUPmi)F2`o79$3AFrqzF1dTI$tAfpYnohQ1Ewo!(0tg3UGAQyM{_T| zyEI9eP@Q7zR_F(jF;F^0reEg#B;p4ZI+^%Egd(;GE3)}@%!#NJ>vMUVO0Z%sxqF_6 z-|zqb{a@~%*Jq}m?du)xB?zJ~IVGg=vmgHs^>pETdgbB{ehk_1tUasG*(K3L#H6g} z5J;+G9;J~eR~ElS;{?%pM#*IDZ0b2)(p9hMV7z73z-)pTpC}umw18}oLwQ9DQ+Gf4 zlmdzzre5%;n3NGi^UBn+iDs9lGt%;c6q2clQ((NzV*@I(MNn1?n#GsHRLw4r*Um9b zff~eK2vc=Y+0+b(=_Uex@0dqoAOsxeg+4#W!4rUGAWJj&%Xy%W_j5cO0F4iYy_xbH zpB54gUw9X$=55>HX}VM@c}rtn-OST46bd;uSk{9P9;>3+V%eivqfH9}vLsV6Y(>|A zV^PfMMLSGkrS%Y0qh(gJ8fn4_qsyW}LoefmR0GOV3uhF~Le04>(Wrn_q}dk6!WI^1 zDV1u$+nQC?7TU7oOIT4Owzg<1Q!x;oMwVVQB@|!69!HzPEIW-Jq~<@+F}y}L_?U@A zTQ@VhUT79u8aqq~YEglG#C4NpfRS~C4aoU|Ww0zB5D#a%?%N8{WC514B zrFs=b=AjS>1}6jfigFOf$D*;sm=F&IeGClv6HKhh6?CcSl(ET`A8?}waZj5HeuczB zI~!2}J7ME~7-tzS2w{+AC!;>%4LrPQjZCEBIceg7Sp5BoBLqSA zCxyvOc_+8Gzdzw(-GhUJWI7%>+Pk?L*&D2WK;FxNxBvL*&R2Iq@#4+lmoA@J+3Ip1 zuAV0E4S_i_*A1ROKfK$wwMSfgAZ;?|sf9{-d{YWm3e3#fDy4UZIR6lY(+6i}wnYF;muTLLdf9GMjOu(u8 zFM?Y{^~Q(FD?8_Us{TtGm%okOiCp=(tGW-}1atKla{JZD-qEVM^3<)-+nMa{5f?n^ z{(AG>hk6G#zDa*xeUiLR9(Qe!SF3CNk6r579E#l7I2P*LEMx~hD;2oaj`s&ZSNsC& g-v8pw+eF79;_N`-de6zqdFOv78J`xeMbEzcC$}#zWdHyG literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/rerun-lighttheme.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/rerun-lighttheme.png.meta new file mode 100644 index 0000000..a464443 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/rerun-lighttheme.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 31b9d2dd12f869348b9fbb0049cbb106 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/stopwatch.png b/src/Assets/UnityTestTools/Common/Editor/icons/stopwatch.png new file mode 100644 index 0000000000000000000000000000000000000000..ac5721c5f3acb01b587e0beebfd8818bd3444be3 GIT binary patch literal 1041 zcmdUuJxD@f6ox-D%oKA7Bbr(QTO^u_8Y-^XO%kaVqbO3Sp(yB&mIfiHR*5Jg9DCRsM4cYDijOI%J*UE(wuQOdln zYwdk*mnmi*|6<2~lAbdC+Uwqcw%;)v{RZ}OV)Fn1 literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Common/Editor/icons/stopwatch.png.meta b/src/Assets/UnityTestTools/Common/Editor/icons/stopwatch.png.meta new file mode 100644 index 0000000..ed0a6fa --- /dev/null +++ b/src/Assets/UnityTestTools/Common/Editor/icons/stopwatch.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: f73f95ae19d51af47ad56044f2779aa1 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/UnityTestTools/Common/ITestResult.cs b/src/Assets/UnityTestTools/Common/ITestResult.cs new file mode 100644 index 0000000..26dd5c5 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ITestResult.cs @@ -0,0 +1,14 @@ +using UnityTest; + +public interface ITestResult +{ + TestResultState ResultState { get; } + string Message { get; } + bool Executed { get; } + string Name { get; } + string FullName { get; } + string Id { get; } + bool IsSuccess { get; } + double Duration { get; } + string StackTrace { get; } +} diff --git a/src/Assets/UnityTestTools/Common/ITestResult.cs.meta b/src/Assets/UnityTestTools/Common/ITestResult.cs.meta new file mode 100644 index 0000000..4864197 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ITestResult.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1e4e2c4d00b3f2469494fc0f67cdeae +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Common/ResultWriter.meta b/src/Assets/UnityTestTools/Common/ResultWriter.meta new file mode 100644 index 0000000..9b2e13b --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ResultWriter.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 4ffbf5a07740aa5479651bd415f52ebb +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs b/src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs new file mode 100644 index 0000000..17f8ed5 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs @@ -0,0 +1,160 @@ +// **************************************************************** +// Based on nUnit 2.6.2 (http://www.nunit.org/) +// **************************************************************** + +using System; + +namespace UnityTest +{ + /// + /// Summary description for ResultSummarizer. + /// + public class ResultSummarizer + { + private int errorCount = 0; + private int failureCount = 0; + private int ignoreCount = 0; + private int inconclusiveCount = 0; + private int notRunnable = 0; + private int resultCount = 0; + private int skipCount = 0; + private int successCount = 0; + private int testsRun = 0; + + private TimeSpan duration = new TimeSpan(); + + public ResultSummarizer (ITestResult[] results) + { + foreach (var result in results) + Summarize (result); + } + + public bool Success + { + get { return failureCount == 0; } + } + + /// + /// Returns the number of test cases for which results + /// have been summarized. Any tests excluded by use of + /// Category or Explicit attributes are not counted. + /// + public int ResultCount + { + get { return resultCount; } + } + + /// + /// Returns the number of test cases actually run, which + /// is the same as ResultCount, less any Skipped, Ignored + /// or NonRunnable tests. + /// + public int TestsRun + { + get { return testsRun; } + } + + /// + /// Returns the number of tests that passed + /// + public int Passed + { + get { return successCount; } + } + + /// + /// Returns the number of test cases that had an error. + /// + public int Errors + { + get { return errorCount; } + } + + /// + /// Returns the number of test cases that failed. + /// + public int Failures + { + get { return failureCount; } + } + + /// + /// Returns the number of test cases that failed. + /// + public int Inconclusive + { + get { return inconclusiveCount; } + } + + /// + /// Returns the number of test cases that were not runnable + /// due to errors in the signature of the class or method. + /// Such tests are also counted as Errors. + /// + public int NotRunnable + { + get { return notRunnable; } + } + + /// + /// Returns the number of test cases that were skipped. + /// + public int Skipped + { + get { return skipCount; } + } + + public int Ignored + { + get { return ignoreCount; } + } + + public double Duration + { + get { return duration.TotalSeconds; } + } + + public int TestsNotRun + { + get { return skipCount + ignoreCount + notRunnable; } + } + + public void Summarize (ITestResult result) + { + duration += TimeSpan.FromSeconds (result.Duration); + resultCount++; + + switch (result.ResultState) + { + case TestResultState.Success: + successCount++; + testsRun++; + break; + case TestResultState.Failure: + failureCount++; + testsRun++; + break; + case TestResultState.Error: + case TestResultState.Cancelled: + errorCount++; + testsRun++; + break; + case TestResultState.Inconclusive: + inconclusiveCount++; + testsRun++; + break; + case TestResultState.NotRunnable: + notRunnable++; + //errorCount++; + break; + case TestResultState.Ignored: + ignoreCount++; + break; + case TestResultState.Skipped: + default: + skipCount++; + break; + } + } + } +} diff --git a/src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs.meta b/src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs.meta new file mode 100644 index 0000000..ca3c41f --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ResultWriter/ResultSummarizer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce89106be5bd4204388d58510e4e55da +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs b/src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs new file mode 100644 index 0000000..1108f46 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs @@ -0,0 +1,61 @@ +// **************************************************************** +// Based on nUnit 2.6.2 (http://www.nunit.org/) +// **************************************************************** + +namespace UnityTest +{ + using System; + using System.IO; + + /// + /// Summary description for StackTraceFilter. + /// + public class StackTraceFilter + { + public static string Filter(string stack) + { + if(stack == null) return null; + StringWriter sw = new StringWriter(); + StringReader sr = new StringReader(stack); + + try + { + string line; + while ((line = sr.ReadLine()) != null) + { + if (!FilterLine(line)) + sw.WriteLine(line.Trim()); + } + } + catch (Exception) + { + return stack; + } + return sw.ToString(); + } + + static bool FilterLine(string line) + { + string[] patterns = new string[] + { + "NUnit.Core.TestCase", + "NUnit.Core.ExpectedExceptionTestCase", + "NUnit.Core.TemplateTestCase", + "NUnit.Core.TestResult", + "NUnit.Core.TestSuite", + "NUnit.Framework.Assertion", + "NUnit.Framework.Assert", + "System.Reflection.MonoMethod" + }; + + for (int i = 0; i < patterns.Length; i++) + { + if (line.IndexOf(patterns[i]) > 0) + return true; + } + + return false; + } + + } +} diff --git a/src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs.meta b/src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs.meta new file mode 100644 index 0000000..7051843 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ResultWriter/StackTraceFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fe6b4d68575d4ba44b1d5c5c3f0e96d3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs b/src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs new file mode 100644 index 0000000..abaedb5 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs @@ -0,0 +1,333 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Security; +using System.Text; +using UnityEngine; + +namespace UnityTest +{ + public class XmlResultWriter + { + private StringBuilder resultWriter = new StringBuilder(); + private int indend = 0; + private string suiteName; + private ITestResult[] results; + + public XmlResultWriter (string suiteName, ITestResult[] results) + { + this.suiteName = suiteName; + this.results = results; + } + + private const string nUnitVersion = "2.6.2-Unity"; + + public string GetTestResult() + { + InitializeXmlFile(suiteName, new ResultSummarizer(results)); + foreach (var result in results) + { + WriteResultElement(result); + } + TerminateXmlFile(); + return resultWriter.ToString (); + } + + private void InitializeXmlFile ( string resultsName, ResultSummarizer summaryResults ) + { + WriteHeader (); + + DateTime now = DateTime.Now; + var attributes = new Dictionary + { + {"name", "Unity Tests"}, + {"total", summaryResults.TestsRun.ToString ()}, + {"errors", summaryResults.Errors.ToString ()}, + {"failures", summaryResults.Failures.ToString ()}, + {"not-run", summaryResults.TestsNotRun.ToString ()}, + {"inconclusive", summaryResults.Inconclusive.ToString ()}, + {"ignored", summaryResults.Ignored.ToString ()}, + {"skipped", summaryResults.Skipped.ToString ()}, + {"invalid", summaryResults.NotRunnable.ToString ()}, + {"date", now.ToString("yyyy-MM-dd")}, + {"time", now.ToString("HH:mm:ss")} + }; + + WriteOpeningElement ("test-results", attributes); + + WriteEnvironment(); + WriteCultureInfo(); + WriteTestSuite (resultsName, summaryResults); + WriteOpeningElement("results"); + } + + private void WriteOpeningElement (string elementName) + { + WriteOpeningElement (elementName, new Dictionary ()); + } + + private void WriteOpeningElement (string elementName, Dictionary attributes) + { + WriteOpeningElement (elementName, attributes, false); + } + + + private void WriteOpeningElement (string elementName, Dictionary attributes, bool closeImmediatelly) + { + WriteIndend (); + indend++; + resultWriter.Append ("<"); + resultWriter.Append (elementName); + foreach (var attribute in attributes) + { + resultWriter.AppendFormat (" {0}=\"{1}\"", attribute.Key, SecurityElement.Escape (attribute.Value)); + } + if (closeImmediatelly) + { + resultWriter.Append (" /"); + indend--; + } + resultWriter.AppendLine(">"); + } + + private void WriteIndend () + { + for (int i = 0; i < indend; i++) + { + resultWriter.Append (" "); + } + } + + private void WriteClosingElement ( string elementName ) + { + indend--; + WriteIndend (); + resultWriter.AppendLine (""); + } + + private void WriteHeader () + { + resultWriter.AppendLine (""); + resultWriter.AppendLine (""); + } + + static string GetEnvironmentUserName () + { + #if !UNITY_WP8 && !UNITY_METRO + return Environment.UserName; + #else + return ""; + #endif + } + + static string GetEnvironmentMachineName () + { + #if !UNITY_WP8 && !UNITY_METRO + return Environment.MachineName; + #else + return ""; + #endif + } + + static string GetEnvironmentUserDomainName () + { + #if !UNITY_WP8 && !UNITY_METRO + return Environment.UserDomainName; + #else + return ""; + #endif + } + + static string GetEnvironmentVersion () + { + #if !UNITY_METRO + return Environment.Version.ToString (); + #else + return ""; + #endif + } + + static string GetEnvironmentOSVersion () + { + #if !UNITY_METRO + return Environment.OSVersion.ToString (); + #else + return ""; + #endif + } + + static string GetEnvironmentOSVersionPlatform () + { + #if !UNITY_METRO + return Environment.OSVersion.Platform.ToString (); + #else + return ""; + #endif + } + + static string EnvironmentGetCurrentDirectory () + { + #if !UNITY_METRO + return Environment.CurrentDirectory; + #else + return ""; + #endif + } + + private void WriteEnvironment () + { + var attributes = new Dictionary + { + {"nunit-version", nUnitVersion}, + {"clr-version", GetEnvironmentVersion ()}, + {"os-version", GetEnvironmentOSVersion ()}, + {"platform", GetEnvironmentOSVersionPlatform ()}, + {"cwd", EnvironmentGetCurrentDirectory ()}, + {"machine-name", GetEnvironmentMachineName ()}, + {"user", GetEnvironmentUserName ()}, + {"user-domain", GetEnvironmentUserDomainName ()} + }; + WriteOpeningElement ("environment", attributes, true); + } + + private void WriteCultureInfo() + { + var attributes = new Dictionary + { + {"current-culture", CultureInfo.CurrentCulture.ToString ()}, + {"current-uiculture", CultureInfo.CurrentUICulture.ToString ()} + }; + WriteOpeningElement ("culture-info", attributes, true); + } + + private void WriteTestSuite (string resultsName, ResultSummarizer summaryResults) + { + var attributes = new Dictionary + { + {"name", resultsName}, + {"type", "Assembly"}, + {"executed", "True"}, + {"result", summaryResults.Success ? "Success" : "Failure"}, + {"success", summaryResults.Success ? "True" : "False"}, + {"time", summaryResults.Duration.ToString ("#####0.000", NumberFormatInfo.InvariantInfo)} + }; + WriteOpeningElement ("test-suite", attributes); + } + + private void WriteResultElement(ITestResult result) + { + StartTestElement(result); + + switch (result.ResultState) + { + case TestResultState.Ignored: + case TestResultState.NotRunnable: + case TestResultState.Skipped: + WriteReasonElement(result); + break; + + case TestResultState.Failure: + case TestResultState.Error: + case TestResultState.Cancelled: + WriteFailureElement(result); + break; + case TestResultState.Success: + case TestResultState.Inconclusive: + if (result.Message != null) + WriteReasonElement(result); + break; + } + + WriteClosingElement("test-case"); + } + + private void TerminateXmlFile() + { + WriteClosingElement ("results"); + WriteClosingElement ("test-suite"); + WriteClosingElement ("test-results"); + } + + #region Element Creation Helpers + + private void StartTestElement(ITestResult result) + { + var attributes = new Dictionary + { + {"name", result.FullName}, + {"executed", result.Executed.ToString ()} + }; + var resultString = ""; + switch (result.ResultState) + { + case TestResultState.Cancelled: + resultString = TestResultState.Failure.ToString(); + break; + default: + resultString = result.ResultState.ToString (); + break; + } + attributes.Add ("result", resultString); + if (result.Executed) + { + attributes.Add ("success", result.IsSuccess.ToString ()); + attributes.Add( "time", result.Duration.ToString("#####0.000", NumberFormatInfo.InvariantInfo)); + } + WriteOpeningElement ("test-case", attributes); + } + + private void WriteReasonElement(ITestResult result) + { + WriteOpeningElement ("reason"); + WriteOpeningElement ("message"); + WriteCData(result.Message); + WriteClosingElement ("message"); + WriteClosingElement ("reason"); + + } + + private void WriteFailureElement(ITestResult result) + { + WriteOpeningElement ("failure"); + WriteOpeningElement ("message"); + WriteCData (result.Message); + WriteClosingElement ("message"); + WriteOpeningElement ("stack-trace"); + if (result.StackTrace != null) + WriteCData (StackTraceFilter.Filter (result.StackTrace)); + WriteClosingElement ("stack-trace"); + WriteClosingElement ("failure"); + } + + #endregion + + private void WriteCData(string text) + { + if (text.Length == 0) + return; + resultWriter.AppendFormat ("", text); + resultWriter.AppendLine (); + } + +#if !UNITY_METRO + public void WriteToFile (string resultDestiantion, string resultFileName) + { + try + { + var path = System.IO.Path.Combine (resultDestiantion, resultFileName); + Debug.Log ("Saving results in " + path); + using (var fs = System.IO.File.OpenWrite (path)) + using (var sw = new System.IO.StreamWriter (fs, Encoding.UTF8)) + { + sw.Write (GetTestResult ()); + } + } + catch (Exception e) + { + Debug.LogError ("Error while opening file"); + Debug.LogException (e); + } + } +#endif + } +} diff --git a/src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs.meta b/src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs.meta new file mode 100644 index 0000000..2fffa90 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/ResultWriter/XmlResultWriter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9bba41ace7686d4ab0c400d1e7f55b7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Common/TestResultState.cs b/src/Assets/UnityTestTools/Common/TestResultState.cs new file mode 100644 index 0000000..98c75bb --- /dev/null +++ b/src/Assets/UnityTestTools/Common/TestResultState.cs @@ -0,0 +1,42 @@ +namespace UnityTest +{ + public enum TestResultState + { + Inconclusive = 0, + + /// + /// The test was not runnable. + /// + NotRunnable = 1, + + /// + /// The test has been skipped. + /// + Skipped = 2, + + /// + /// The test has been ignored. + /// + Ignored = 3, + + /// + /// The test succeeded + /// + Success = 4, + + /// + /// The test failed + /// + Failure = 5, + + /// + /// The test encountered an unexpected exception + /// + Error = 6, + + /// + /// The test was cancelled by the user + /// + Cancelled = 7 + } +} diff --git a/src/Assets/UnityTestTools/Common/TestResultState.cs.meta b/src/Assets/UnityTestTools/Common/TestResultState.cs.meta new file mode 100644 index 0000000..e1576c7 --- /dev/null +++ b/src/Assets/UnityTestTools/Common/TestResultState.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da3ca54ee4cce064989d27165f3081fb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/Docs.meta b/src/Assets/UnityTestTools/Docs.meta new file mode 100644 index 0000000..d636c02 --- /dev/null +++ b/src/Assets/UnityTestTools/Docs.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 8e0891bd2d8055d43af56216ad95d3d5 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Docs/UnityTestTools-en.pdf b/src/Assets/UnityTestTools/Docs/UnityTestTools-en.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3793457dbc115abb814f0fcea7ead4cf4e3354bb GIT binary patch literal 474685 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 wqM$b^UUYV;G&DU7$i%plKCf@ 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

FMo{7e0O`d*c$Az{iw3vqa0wOKElCL63bSxeUqu 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

d8eI0^N6M-CFP~ABC}PX9z`)*T!sL$? zv~pcp0B8q1L3q_Uj{P{g43DFPg!4JcY{W==fzaf2T2JD08Lid%)d**;?W1DtpVpI!?wG! z!IDvg<@^^2`s9nudQDK&qI>R5qw*h?Z4un!MBvr6&u_Rwf#q(A`0_V%1cC{lBLT~V z-!3+JtX-eSar)uE!C9*M9Bm_`-ZPYXPSDGsn&|~ZMO}?l#22yg-CNijh+*hNxBaN_ zbBI}(vLEW`=1#4-Tc`1~e9FxGq6Hu8?3P-psyHIEfrz3XF$_!+>TKRETmUwjF}t@; z`RvPZ`{Z%u*4h)GZfIFGHSbQWpJ6V|&wF*D!dptehPWS-7P}!sHwqsx@^N|!>VDa< zRkCtjv=%j{uQhdayaE50z^tDgAVLhRVii^9{t9)`fmJ+G>i+)bY^GE{M?qCw!0nLm z%UO2>UdIuK5c7&iWMX8hjex?Hn76nZ)Lp z_!18GDcfI8FSoYq+LX&S7)NU4bK4jnjSgy!rh0f zK1)>TS7swPI5^La`fmSRx8F1lxgnM1`(u)K0I2<%wj=Qs3s?+a4jaw{>hW2~%#4Qe zgP2i;vBcHY)!HX!l>vX229xx$4ESeVg$WiW}gVK=?S1g9%c-YCIMz1^H;)h*8qs2fJyY+aoHkd(s3HD{h=^NDkdlXequ+VO? z$>BKbc0{;*S8E~1lOFdmxI{04s4aUFh#lN(yNX7%HqMwA1uqQx#pgRI=H}<8F1R6| z+-L6-=Pu2Z4a95AMv1q7M7FEm0$^R~XW|HYbh*$K`Dd*L_mQYP>HKWDI*-SY*4r{* zK?gEs;-iQ6#R{0XwdU{>VONK1?tX0E8s~6ytXSZcHdXaY8};bXnWJ@``|gG$*>~MhIot_ zi!ADG;9$6;s-~8gETKUv^g$twm&({)T2u42veCF}c4U_sSH;q^KR|yk3{Ze_E6~ zS%|wH`hl?F9R~;LbMmqA@c{fps*8&Y@}%$P*tYlcVI+@&^s5@@WQ>fAEq|zZjNS4P zwME>SOEp%f!ZepurD%4~lmoXJ1S$%t<7o!Y$+)<Jum9lBW7)?9m6*9b3b zxmDsGif(_0#hh>ua+%AiMvzv{`CZ_-t17+6nZs)9e-1+%=)#T)tFRVTqHP)J^ zMx_vM0lUKm%I(g`*X&y(X);fjx|f2J#=^?!?8cD{1&4?$NdS(4lEBf2^`oGHPi!2# zj|O1#vcbleokOqX_adsQs?>_qEgmk&h$Sgzg+!#>> zWmQ$3$DnuJsbwgX`taUF$G6JeO}i2BcAqiBPMI@& zE`Q@q@KfhCKqkC? zZD9q>)V0%BtWYa5`~G7vxd;qjhOHrooW#9*lu|~5%cOI>Q;;D-@_3U0^O!EyJlpc{ zYfTiGFL(d}l-=96Z}YfGBk?nEVs2RuRym*ul<+-4RA&Y+?~uU6svka->eOSE{Hb@^ z0?bEXoDIfB`x17LBQ6;=!!1bjdI42+b*A<4!rN~jsm!qR`FAifAD+NgTWa3kw-*jl zi!uB_Yh{5ojB-7dRDN_m{;o88Vj%bSf*#$QU~{{>y9DflP0DA-E217hsi^RYiAVbT z%V!WbCx9nDfBu|Uz*ALKb-i3bLZ`Wfi<9#uIy%JT)C34Ki04(p z0~i?tsVRb|Nc=vAzBpv#Z34yS2hrA!-sncibbhTqF2LjkhEsQ#jih3_2?GuXh;;~+ z)z#Dl{2mF<@>*IT%*+b;JbsVfy1GQ3aHuhtm#)zVtgE{my-h*Sl(n_J?k;V-E(p(s z`TO&Vi_zjt1$P%r4k}0Vo7~|(i=@AN`SP-IUlQdc0o-c$F}GB+lA76$Xj977^)h+N zszSX)tK2B0jO61`;>sxu%zd@o9^~#utGXRjH-FqetnhJiRLJ0$pR86~tyqd4`rZA# z_s}6=RX&-;eUj2q;N#`RXv1;cn=V18YoDvOBGZqF1&9R?7~G}5Dcw5DusFylu&7?3 zd=z`!)hk!QXAH7OI7r11dwH}3Zm!5M6_kdyMr!Nlw%k34JoruOoWN*%VS=v9n`lTF{^%^>blr+YMzi7#PG?kw&pb;AzhS ze|vG4x~ZwD`HP`kr`n+(*KnJ02*)cKbS`{X?Bs2x!3%H{&x+{pG%s_4uOlo4p**MZ zByqhDepr{H7*~KCTSeIVDB*3l9bX)e7MleG1Xd}SasU>z=NYDqy9*P?yLTPtf}ZDv zk>mM*Ew)us!laJUAa!MYrD*<)ui~XX6sF+&@Cch)@LLHHB#jFenL?^>)z;M?y4boJ zt_!;r!g>Lill@RbM@MDlUx29uG6_*vnn0!@iGAzg;eBnZK8DEZ^DJ=LYnHtbYLEu1 zdvBK8N>U8cZ5SElia)XtVQ{Q}c&p{qkNf+3zzS@xuLH#EkPmDvX1 zp|GK$p|CKJraJ@>R7FLFdZ}JoT3WOFiBU1zwtiF$q8I~}`cIvDpF3BmsGc4%1JX7E zT6kn+Bw&SsJPDP|HzA?8xF>^+tHC{#A?ODfbqy8k*|PR*um~b4CJWhLW1hGJaPJ`} z%b8$z{RZcqCXchH)2}896qp$p7Aj05f*{^^2Z^Gg+vOzNK~XWs$5S8l4IRoo&ORdf zXp|d0>%hE!AdmGK!^9Fck|9}bL;9ml1h+0Kg>U~IoRpL_o(Vo#2^x8YtpN!RM&A}y zQc{}S71g=Tto$&G9fQOpA|eMI6W(P`^dK$^N5v>&Z`@)eK(?z`;oM^=C?~}#Azeja zUK?2u@j5aJ=NMAr0^|a2rWCsUw~$=Cf8AAmn~7xx*=E>z_RoD?!H_Oo9r&2KfLjdb zLNKN6eNc4y8P|f{39=fMXs<0O|^U+!afJY7ghd9ge;p5CQqnGBT!RLUQx+$Q~?-ptaUkJVH~5{M(R*(A2#);;rE$Ln)z~fBjw5w(zw)_>VD?St*qNLBeis*aEV5i0PhIVM zlb766CHd?1mdQDW3{)nt5WKUq^Y!ajWkQS^ZXM--4Uoeur(OE_Ss5MA4Ok^#h+Oq8 z`K#MyyNb+IaVZ8YF&|K$@Ge3J`i96013~x2yMO?010SU-1Gs%8!nl4yZw5j>*W%Vz zKLdlzrY0Q$%kmcujg4;mvjIYehFRx(g~O@DMkwVNIzCeG-ve$5+y!^kpfhMQ7_cUx3V4ToM+U443H#!Qf2;d@aLkf)Q#{QmuWe!fIX zivPcg1O5K}8*rUnjiOmUAcd>TCz2#$ps6xRt<>Sm%S-aHi3wweV<~WXFgLcdPuoRp zUES=BAUGyuNg>J6W_R-Qq8GX{q0n8G#qKS9g59K8uu{?1XhuXC@B6e1ID^2>T+GKJ zwQaI*7-j(YxAljlrbCEaJC1rIf>?;?|d?&=|qg8?B~Gkr>qw{)e1B)htpb%rCV({ z5vYE!3JLrf>&D4rm~dPb*G`V0Pw-6b_tpf#>((d;7)tikJeGx*4 z-JOoQkZr^M-d;Q`;xYooGb>A!9;-B1ljQ!Cl`8hXLpDFa=la6EzW)MjP|Seuml$L$OrNI$ib>;88T z7hvuTi_okwR-$S*L=4n;jilm@$r^1p_-WYzj z7%xbi&q*b*;;$#dFm5tc&QL}*gT+$0$HI=Ufuq>JMirkt|AH(PvTXv{?FI4oVPc7P z1wev(kuGAzb;B8UUGonX9BFR1#ZpMFOJceoFAKZ4a9T!%?l07<+sR7rEP=h<0UyvE1(Z&v#7!3}^}lY}HnhOuq!-ArVM zD6J5K{G;EMNUQ!=yNdo*3pj~LJMz=%Y>A@xFv^Z@tnRZj?hO#?EY zS2E{Lkmx3Hkc_rWT9(u)84+Z{suM`2zskOZ#lu|#5|n4gkO25qTU9k!J@d4>x>_SV z!X1CboQ>S@TagO4pdd*&K%~8l*AwIQO8&a_BX(|R3Q;SehMWo!`yqO2tgX$ziG3|* zk!*k2C;{V23>cNy=K^m#HKhBZ0Y)nZ3b1$`#O793@eqr*^z>b60z;%p*TX4X8gh|Q zQAWaKr86VxA2;ePbKf~}22AIbXh1U2xo1xA^68puZrJ`Q6@VicBIHlG`+tn~|4QBe z=I+Isb`bzT#pbXoK_YSxG?Isql=$|o=O=0qkv*pHN_73d4yq+5aUxBOmC~G+AbJM;lc4a^ky~jM7-cYg*d3t#T zX*)|@kk#>c8Htg!+#NOs1OyBWNJolBHm|O(0zq(Nv34OJV-^&_$9^YB9&wCTCwjeJ z>&OPWzr8I~0XSs+dYhj za?YIo3XtpJ;UUp#V`JlTZtg6@fSs|sejh_da~WXF97l_vd4)pW;4H{j&b*5Xx9~Zh zK_b#}zP~;hOkf^#FS)9bNdR64;4=FNtP$M02vJK*8%bJdZ?|nXcb1x%o1=fx{b9MO z1%OkL?nVFzc`qXq;Z)!8QWuDj^z}2EYtU~oG}sTi>vu4`G&N9?(><3bg!K#ghV|yT zsnO5d^T51tKk>{HB4<49IzvR!U&Y{9MA{RD07)V4l)yX#D^AUgdAMss$jt7x+4GmX-X%A{{HbASfaOZ{2Nyehp8}>cPiDQ-mcK*;-~fUx$T9#KIx-hsRmA2T+a2d z0+!YHCUd^R6!j-*#VJr8;JtqQ{Mlpu2bhfD6AXxYwu3(MCBL$=GC%)$$l;&HnF0t9 z!DWvDS#aL1??k&=cpjG~*w*=IjZZBA z?E}#HIlNI$N1-FDxU}^2fr`=Y0q>dd?&i?ap1OEq`kh|*8y{p| zIyyRl?P~CY`R2YAk?P8Xn72=@05e21iUzzigDFY>HywrHL>NH-1KNqS>cGKqKoN{6 z&wYUO%2_IGHcI@R{7+~+l>Uva%vYIUnt+svSy$BFvUx7Wq=Slep&5}{&f-Zx$no01X2-A4tsJLyuZDdK- z?(Q0YCQDEEe^-7e)dMVhf5~lPG{A5IGp$B51WSvG8r@G;mzRNwPe~Nm9GskFr@)M_ zly^39vE-Q-=9cf*Vt)PJu@d2dP_YVMUyxBznf^oIpeA(Wn+PhT>m+@l{AI0Qg`Di~ z7ChMcNDyW+0L+h(bshSCd+Ry5ls*L{4l+UH_m|CA<4?{4n5!1|^=k<6HV|2(uqcc# z&dq760RN-bp0|JYUhcJMBf%X7V zsD6vL#no)SC&`p2`S8$C*VGc$_y19Pv2(Z&Q>&{+TQGhhTwg)cf$HxnT%JcfQVyVl ziTv+-s5lxIj>=b;mmSZAoD^exZc{qgK#d~RykbIoveiitYaw_0%<wV;G*hYZL$(CpO+lX_sKsBcgs?t6j!ID{U9-o z`5PV>!bw(cZXk%dN=5%QUIdWLqeqXPY(Gtr=UUs?_>tq1Sgj`pZO%1*4CsNN3MeTl z`La~e8cPdAeVJ9xmClO6{r$30u6k!jM&J9+6SQIhk!`Ch@+pX*l4PQuznle2k?6s+lrXnIOSG~evwqpFIBfPlR{U+aiA z^H7agWE)mN9gQ&yn|~F*vzcDeI5i*uAE|F*G9F9E9=LFT zr~WOf&6@1`5_9nAm*ACT9%_hsxO*7Mnegznk|T>3?ua@nvu$s&5i*t~ zq0EX7>Ke}PA_{t5l=N%ws1E*wRoLm1Pi+T;q@C?;=AF{l7PhwMzYk%ktT8BmC?$ef zeC5m1?6ZUzu(H;dxVj&h9<~#ZlG+2CJ_-NPy*AONxPqsptAzW?r6}uVpXY@a z6Z(o?182BJD!5qhI%MEQYHN5gju;XThluC|Hv#{VU+vW7^8oDe!s`2>&jRKP=e1wH zm1FbADt6QfAkky_eSx))rgQh@T-BuAR|roHovMRAiob>$(jI9iXRO=`ESqB{p1rrnTNZ3ru@I00Tc0R z`A9|#gw+s76kTkni{TIgz*)>Dx~C>0oEU&w)cw-_Eb+>h85CH=0`3!8 z77&}awY33;FZX79^^$jlkdhJ>_-&wJ*E>Q`rCMn6st*uY_5#?32;O~_3JsLqG;8cg z69~|*qLY)6e;C}|T!Q0bh4biwa@k|-?99xTY;+3?3yctxzJ!5vK73Y@dtAepyFZod zU?-R2zRE^QLB_>}e-*t($;bDU4uwL!L?8BkOz>B}LG9T=DBlLQH~q~LBndCOUG(;QO-M~W@J*}f_skwC9e1}b*> ztw}sbr&DerBtnGxg3F5RJMI77*7BrZ^%OTdMV7)0^7!@}^;&2koCj0P7*RJC@kqet{;q zo;2qc)5Q=L&3KVRuc36sN6nwi4i4XO!Hi=mtF3LQMivR)E**ZXb4cg+a_)(`q`q^- zsc>+N)TD!`ROS`WD<%4@`e^xV56xWrl;O)sm4sT{mxeC?CeSEQNYct~hib}pzr$UxKapJ zlDXP0%s!qiM?!wIxWweSC0enV@%r~RBu`wyqyN5G@HVmEAD;Cgm9We#x59@VpNnQe zbI9=$J)wxSoqcs8S$k4nbWCadmInBhPa&=HD7|yJ=XgR>(Y{YN4{L?Po1E^MEWbcm zge>$3Jf^D6_A=M2!vQ`ob&R~L!)sb)AeO8f@fZ>ghd0mQ9N4&mE1Z8FH1qgFG>g$y zH1A+J9Tf-tKngrkY6;dpOsH9fZzAb8+RON0Y zGuz8iZyRb1Ll<eCwF!)aU}ZF-c+3Nd5KT<{lTc5%cR3 z_AElj)MbA_DfZ36QSJA-W)WPP8k)>(`2E*>lgfKCvyX zK2{TD<+0`EWl&_|w4S9P1Dm1O>GniS45paPT$P-dsj2BlK35xk{pFDyNpW%Ugg0N$ zaKr%T*UQQ2J~`7Mu5d1oH-FK&hyYnI4&&kB0pJ4nvjb3W{dEGA5vS+pIhntHIaI19 z6j(xv^Yh)#c4rO`?X}RI0ndz6=pF6WN0VC^VSzX*QwdI%}AKH1gRK$v<#&!o@6IU)}$mRB+M!sPA>P- zw1ExF;jZak*{}+i{!w5MJ6$t;3r8jN=38o`m^JMzmH8>GBO$9l%pztLk@&ghw&`U) z!!3y4xoqaAn|+$^zw8uOVa{GKJr89VK)OBZ4#npN7-0eU(nH&3bbq?PyRLo`w$Qw43MC{EwT_b6i9`5Md}lRy(00w}>x^)@3O5;7(bE(2!pbiaCT zdpCYeNfA&b1fuX3-h$+r^x@?}Z(4TIXO2C)w9|jz&q%pzU6KvD`(2fa0Y`hqNF9MR7a6d>*LmHCgX=!L$ z3cq)N$H2Y`n)#1u&UcQ>6Ed?|s0)gB8|vwa`TX_PbW7qir^;y@<1wg0h2R=6rF7ug z=b*Qep}kw-Hirwt%16gr)pzI=#+Hizx02}mrs%I&g6U>yP;xZ7uHP7XdJNTHTzc#k zI=JDAEh5s3=rw#D0=N{hHUGL+gn@XaE1AuQ%cM7hTA>TYuTG;JuJ3!3SvXXjB21QO z^S|G|_ny-r!X*S%^WN~jEO9{oy(O0rk)YMD55##ia#2!44SI2;0xiWa_ztK96yW>( zKv)#6K7}X+pq3#IJq!%QLZ)y$df!`LQPyOaML@yb1uQ!+FQ9%bYrk6kHc0nld*Um& zQ-HV*68J*^h;leytD4tYQm{zM?ug3B^bW;Qt5H!#)>fXoRWWHI$hGjbt?Bthin8Xl zkAo6I#6nLjr~Y}b+tw)Mih{%K)#+dn)@DIW2N{^x0&X{_D}5d=P&QNB1L${?=jEsd z9zE;?9eH5qzJk(qOwki*daRwl*~Q*^jm*t~nrUiWT)>+;y{pXNQr+(E?qNKGODVNT z3Ow-j;C|`FyBoL^g^y^!pO$pg`s$n4;);J0028%q`uh6dCqsZtMMX``$g30}&SqYj zUnQ_2z+!`B1Lz!jRC3!%oYp={Sh`3z{1#Yb6YMTt)77>acHwT@<6nGF4SsY*MiC1> zfBw7)xY=!P=8J|oO-LDH#tG1?oRabs{2SUrFgR+^wL4q6b9Z~aLLVQ^OmZXm?q&1b zD`GtQTqxqpnkzto0@5?UNeu62&w5((z2t<{XiFY`{H zemP}Mj*Aui60zaIKu#KWcTF~ z;5}2m`ihPL`%PeZH6kzMNzNeCwAv9bdOJoQm>$p|&a0eqR6)D^aXd%O7ety4W zaww(iX*S1bdTnlQa(my@czI>57oIYJ{YpbwIRG1wEg@6!6cSdc09z!!!hkt>DjlkTr3$200{=q4`ito5pQww$Y%?t-faj#zvPTe$ zsiaU0Wr-6yf(34TpqD(lF-4txHw!jBd&v}!q%pjZnve4o6UA*4C{QUv1>D*M$lFwj z8Z}~vW0I~iojCxC{uW?f9sGcck)PjfsJW(LgzKOLE?gM zyk5^9bLHi7L9hsrzoNUS#r?Uv$_@<-;1=o24pJ|q?Tj&e=xO|!%w~4a_@tqw1&c6d zj3)7ivl}_ut$|nsiMH(kr2HZ(AWj?`8=Fv0OYh^!*eOIu+o!Z2IoRAhbeoXge>ruP zU$J2;BMpYlyedtcHZrKp@s8(xUy*yb!UnLhFSsHh9wjADUw{}|z?f|A@2kGacK&ft zI^g79P9Yq4Mbci<54I-+HkdboV0(J2&7I-It@eET;NZJE>?6mY-I#~>vA1XE(OdMi4-L>A&6kS9$mOjPxR6zVN&3UEmK?h&%{llaC3~YWBn%?i(vsmG(Wk*74V)v zEv3w>AZ~)*U4z=F`g@z1vIpf_pZGm5m`$S{pR8m9#UjEAD1rcb;D>~Sv-9%^1WoGF zZ80`V#fU1|{_SncmE>M0_cw3eI6AV;CM70r6r!IPK(w*auVBi`%h8|n(=_(J!Mq~b z=k#+Ij!XE-P@0P~)e2xAfZY}XELLnC)WqR`SV+*TeDoL1wa2M?H!Juk)ePg$C$`}ym)j(Fz9@f|y;^3A{SW<vYzLAn&T#Ua@F1u_FFq`2%N>VZw@O*3+8 z9F+aV7(hj;&GY-bg1o$L0UHU1)Y&$C=&SodN=tbSk9da)0`?&b(D3zpEnpeRl3~=E zkC06hfJ-m^ihd$YO(wb>unz#V1}KJEe;N<=mG4$D2Pupb{5Gt;RLax1t4tAMC(=`4 zL~@zy>mW_KsPl7_lcdJ4(m4L74?1A6SO9sF6jMJ8A0d#N#4kDq#Fbb|9Z=%5jQC!t zU1j5tBFg8U^O&?Og zl|QdS5QFi1tDA`$n#|KxNXTX`h!JatNvG_v!9Nj7m)ZZvQplq}@aze!Vq7<))k))X$u3%U*(JdC6u^OjB zI*qOlPaAS;rH!tbjZBGdyoHgDP->fCEEZ{@^2B&iTkSV*b-j{arUHgttgn=po0*_n z*Bm-{H@*d!RN-q-vJ+kO>6TJZ@G3@MguZ4{JrD$8y|hr*3_2JD?T<71z@;||dJzRZM28-B;_Fc~LT}0LPWfwR4oKjEcll)sW_7B>FpQbRurMKO`b9uC52Om5@&>cM$|4BO#^N=p_`f zv9TnWp-|Hqu3zU7++&FMAH`K4+19{=#sR(y_$F@dH8k*-wkiuj<5)Tny`&WI2Yv2~ zp4YHrVmDBOq6?_#yQPd=s5Bv=DKsv#rse`@4}Ou~3U*)+doR7dgZh@ToI$rApmf~{ z@_c_I*s*&jca`z35Go!2U_r>9HTW*a5J{YvwWR6L?bHAO&OH%vOVB3TJH2OfSKy>% zto?V?Bf6U^E-qD1r0)k2a*J>1b+iISKR7jzw_5Vagi3#~yUGx&21)76{+{2NDC&_e z@!~foC3{bYR)p$B_UVP+_?(8EiqGE(hGSsS zlOWxfi}CKO$3WQb0=xs>W5l|3H+KRe8L$Nq5RqE-t5vuL%J|O6TOlOU{|Rn57&zu^ zoR4g%B{ITrG(KS;py1U#Fwh7}6~n{B-Q7}JT60Za*EhX_HF{TbM+hut5L(jS86_F3 z%FdtHWHLyZGMHB4M>n-TP=^G!TYhM&luA3b!0E~#s2+d^`@6e=a^dqrP!5~$R0zp> zmlE7y_!ToL-az6ii7vE?h86cHOu_31hD`n_&JK5B?0O1BfP1{31}`U}4hE*Jy0hL&T^7KX=us0WuZA?Y=u* zdUxlI^IBK8XwP7bGCpaZ@xv8>MERENk_X{;Tr(D*^jiEmpX-VID}Mo^ z2}p8hpSui)Oj|}!(s`^_|7f&(1M#~JQ(e|(KLn7(@Z;QD}_$g=0i;}dW0ivqF9?9yLtoIXTa?jY@YM;OEBU8rAxH!Fj!1&l< z`EA1#+-C5N_sb@J(rc#$t4Dm2{vf5#G~A9waO_?Euu$vt?&T>d{u#ocV{euXm0=Ns zKr=1Zm9NXnuUoLhkb1876Vm6{E!cNU29HpW_B0P|KUn_6mv+Ov(Qe)2%JpJHJ);kU z@?ty$&;|?#BARf6=_Wy5(DcR=lVFIoYX-YaVQS#+y%6l{oueP$K_u0&t@Nb2ggHy6 zX16T`7d?^X!+UXT%@7qOz~62hEEDS{(KM^>sl-)1q7z7&%O2=8x^t<>(|7h=vvhW@ z{CJB?t!OOQTVxx5R#pLAVCxJ(> zjn=gl1{68R*Vor;@LPx0Xm5|)5Ct8C2oljz-C|nwyc98GYRJHPDD)cF05j|j&5MAt zk{cdC<`&(mNon~Q!az~XZJBODo0LkBEfwbaw%x`53PTIro;8-8fU5ZTcpP*85<2GT z@tufr0U@@mwD$IP;JiN!gqa&sj?dE!B$6-=bVn@t-Kfr>H1^75PR=Osm|A|pzHXKg z$lZM)HrQWkCf*9Ccm%rx-$biDNM`u)L5y39^3gaRL(R!w>j04K7N{Eb-+FHRw?WT; zjE#_r1g5<{?JYGogG|meq6H8(aYl9rAx012!c@Eh5~WS$ZE!2K zoOp4GxdNi^f*w!??j&ykvzLD{j<_cW6B0G6l!=ZJ0>Hqq>xXc%O0q82?s2y;cB+z+ zA={>Usfz%RKfSuTVr6BW=NcpP4eX#aP}kEJhD9NcK#^?+q@`}j&V_ncrjpa3R8dRR zN1)6aM_k$@#6jOPm?5|{JlsO75Gv!guK*Ugh!QuEYNW*Yc);@ryN;`IIhe1-euEL> z2{(y|AV*4f*OG8HbBE;XFlcTf@DQ8 zwhgWh6jw1NGIMjqQt7Xt1FMSdifVk!Ud$7{cYJMP4snuuH9eC&$A9Ih=pS}77zuY= zA|@)b_nHasM;u0k{UpjR>hA4zzq_fu(IXN7bn0H{BKJ?_!g$o)6l@f4sDoqA04KGSHAY+ew}OFW?S@j;fMZQTn`Nl5{kLXL;T zKn&%zZg;fW30NGW>fpb@1Rp3?aGKDNrE5J=n%``{k478afk_f|-IVagKlMk54<7;- zi;0|sc~E`(2g&@HY5>$h0X&VX2BlW`XmyWr04jE7RkWUgI`3;-3kL^>3NJ&8;_lBt zg8Sh+rSwhb8#_A;;t8n63W_+zi*k!GDo9YJ%45|WdPxRzL|oL*f3vHyKU&az{o1(T zU1MItRX5g1<3Di`r)w!BRkeKWdY8v##a+ueH?|)|YcCc7`LZF0KIHk>Csgs=s*ed$ zA@9?X_V+>nj-6>9QZV~tqE}5tMHsiQw|5x+Eaw+azX0hqL7?GKJnb<6Log%!0e8vs zKuH=r{C>g_{`aOfU&F8T%Z!o?KBR!GwY)L=PQ9JX6I4W|z4P+&E_jXMP<7PF0o4&G zi>q+HeX}fiVj^hS1GMWvk_K<&0kRrUZXXTpoOqOu{-LGY%GQ=krK>j2lA!!4IUeCh zZhH~qO_q0o`p!X*s1i-$&;(YubN0wie}J{66VIrDe0SJrHa;uV$^6SPPAa#+DJdui z$8BzneFgx-_@H?R)$|y-k4LUMUXz$7Cem_5OX6zuB@ibQot1&KxJAYQdUs3EGN^)U z@{HFBDHt|560kz&bt~^?tMqx7W6i?GRXNln%ZQ!3_567RczFwKJVK=PH9o$f`!TP? z@vfG>Aka0CL2_ad1x$DgT>M7_gbQJM(wHrH`1RFU4%#IIAYB1eeWx+szoI7~=Y4zU2zgm_+NxWz9-uwvujxX8bEw_m z|4d)ILf10gGG)*+KWa%24{Vu`c|?4A`FH@5BdNk=HBEw;OX-;016HTf-Yz%nPpp&O zXnW2%=<2y7T=WrODP)lR{qXKez6>@X_j@kjed7iS-brGk4-j|XcC*SNz3T^cwB#2# z)?YM(*iA@Oq5-O$b1JWK6URbcpGofgZ zDirPpw!gGCsbEmqA&2-4&eu7k&>k_`KB%7xX=&0!W?#Cy4mwk_@~B;{+6IiNJ z-l)U18nH_Bt=^&g4~VGQ)N8|R;l{BI{G>e?>`LV>?*t1dCNH2!-7|7WKj!TrsH9bXW8;{4 zU0u!S5;zkvd6uQOkmo(V{)vGLwSJra5+N^+;dc4xiUxR8eJd_j^D(H-*fgcr(8Ro5 z^2f`#T0V@YgVaj7fME1;q-jZ#%B9)y`x@0V$jGd{iC|v^bn|efy{u=jKBI!tQp?P; z>`VOpnJk{ZIS_5G>x*?f*)1sV_HS5y z4D0fg?_PV2+xD&vK1)n>q8ER2+UlKfd`BKqwyQ4T-{?Fj=Q8c`(@`?1s?<`Zxek)* z$o^kP_pL0Sk8wZW*YRXeCumU*zq1vNQ20I9=|F7PE9pE3CErsbrl(!78ZE_%9Lu}t zE8I2XIS_Q9=^I2iZGAfz!?|0CKA7y$<*FvTTaa2KaIuR>zqZk-(0svEkAIId=V0?GJ~z_j%^(Va%N|4^3UOv>jk^eEemq}DrW zsa8y#jRNN95f)uwR(xg@ji9(5fNM4)=)ZT6Pd@ap=x z+?aCF?wWf8dO7y_Fqjr&!*f1YZJYbCyV{$f>xKVcoMt_KzMZZ`l4WG~&y$ExRA*9d zLNfvlh`;DPC0BQ%$C}>{@6>Vj??y|df#O|2Et}oGl8=4}=Vz(=$~cJBS^ZChRZNvw zw(D)YRqd}gdl+9jNcV+~5TrnbZya`IQEksIt+qi&MA6GV0aZ0`!7{ZNAItTUT$2!tlsOFQ0u( zz4^x*J-0>Uchg5W^{!u&E7Uyq#SMPOHR}mCy^4d_NL^kBYT=uk=4xt*vl(Ypsa>gc zmxD^b&(LH)3Y&3-LFr*u;gWdvMIu&F5QYww&jyGLt?a``7R#qp1;m1dHI)52P|SQJ6J)DvZ{7G_m4^w zH>KZ67R+$T^DZkBXB!{9vk08au*9iC)DJTI9{G~WmqEUC+GCbCr^m&1J`Rr1m>pRH%%IMOBYI|I2g2Lj6t5q-@UQNm zJtceTEE>zO(Y|vXhIQv6uMIJ-fuN~YATaXcf|LA#$B?||3G%c<}Z?1H!mfA_SbSg&-B3I^pBtqr7*io|a}(dKC-ftcnCxZ}~#nli5TC9ug-ABXyDmn>_Q> zepuaVgi*#!%R2p#<;FkmTo|YA^Kx;sXnsINAemg&<1&6{hBZx#9udnQC%Ic2smnt` zh?v8lmk=yk@p#1SReyRsSvnJ&dZlhm-yhn-;K^dAzJTzC{k?!x_-8j)Y*Zh6Q=w=z zNJ{e^+8qhm)a3w!_XF)IUn8wAIMWa9YqD}q*zuqtT}M7IZGDoJP{X;+f&|-!4`JPy zTHfn?&dq;`n_P0tIe*fCt2HKA@{)tKl%RPlIXW&wJ~fo7VK2S}@drjKz2WzxU1$rw zkt_`bcGH8i2xilus6Bs75*&PxJB#M zC}xn-`BEyOCjF8CKe&kNJp0M=ek2ucN$-jOgiK?QG_hKQ_W+&2XXTw75BtOYa9F}0 z;;eL?4N}SHA*}1IZL=rx2*zX$)v6VAmGyUb=fUUCM);mR`z|=?z_D2qI>6u*6IWsM zor`TbUyqD0YZ~0p_tpx}Xk0Z*$>8FS65MNcYF=yR;s;YklKqv!;a+IfX^t~;^Ez`BfZ6iHC|H(JVo{C<5*G@8jS0*Xv;PiLG5~a5Cz#Us`*5e zIl`k8=%yyu)1(@1`CW?zER}C&U(%^>JDMlp}=GQCEbr% zG#UaNYl3LdJ$SK^CiWXy%CGnzEVQzu8#^Syk*JDZ-O-W#@ywJ;jSEvKAqO?GDDlUZ>ul6#QzCMuM_eVCkX7WfXr7b&#>aQC zsQUY+f4An{8c1V*|3~iXT)_MK4;%D*cXi-@{)ZDbSO))JyQ>R;*Z;{< z{kPBiU#-*GnE$!1{=c(MXW{xU>vT5Gf0%c3asB7j`me_6j|Bh4INdh{c4Ig~(k!UJtB$f5)?ioqLI;9{giU}msV48I9D{FE{?+W=*`#i^Iy zdPs-?+SDn;mp;hGl9HM_Wc7W`ffT-slD$()M_s+9uI|P6H*<--O-)UJ!gEh+6`<1M zbJ?8+ib7x_d#I_aYg2~9`g3Cg9Ssd+Z7bFm7PP8t1j!#i78Mtpy$uf!2ZrA$C_wsZ zZE4BsmaudnS!K>1?(AT0z6k;-x4Fs5F1GuGJBC?TON)*x`a!(26dfp{0lF8+E1{wA zvC*)<2ObQs4cu-4tX1cxL*Q3bR0Q;)pmfJbPv1Q`Y)fGCZVF5RsHvEP@#y1MMFf;qI1ew$?4AMUpL^+0AiNI${h>zzcLUSV-g7GPtv3ec_ba>Pb z@Q=5nRrT#yvg9)ayev^JwrOE0NCTva^)n$W$c7C>>#(v~Yh|?+6@mNWFvUoz^m!55 z+S)%W-EXfrB0BmRXlSJNH4Kvwm-&;{kDlZgifa0`cBTO@<*$+O@~!~3VQWTfF#}pH zVE6o@3yfF2Kc~|k74wIEn3@cJn7^SM!69saZ*B%97XSgyLfyXf^5)_aXj@$Y_4Egp z4wxKZcTU)U4dXkfPumi2U|Z^Dh%A0?$ir~}e<9`nQd~D960${BN~r@1ggZPgZ>?bI zu_DUn_PUgO8rF}PmQ zmm*)_yi;n`j~;SbOI9rUeev6o!HKr7@N%>>v$9&>q2DZZXDaw~>D$>8&~PFUb|V^> z^&m2ju?#p`Y_v- zvh|31oc0Q10P=y79AhHnGv)Qg5xFM`(Q`qkO+^vqNz0yYM5Tvgu?8p3SY_+$>$R7c zz_#Y@c6|UmudXNcEBlqkPvJC)cvJy23m(9P#6);MUv06(0&W-oF^X8p=&^FXXcp!YNb*?uphwp_WmeW zXMeJ{zb`>>8iSi~ia3u2*zEYI0Wdvhv_ge26EMQRqGK?4Hm zGel*0PlVFw_t7ul=tr`;m^`kue17mi{7kd`kKnh&imK01$gcvwi6_zL7mRJi|7A8h zJz*q;PvFO*fcfe&&BfLjwHPZYVXPD+VL{)n)H}Sl^m*~rmP6~38!Brwx-kncgN6a> zD|rdcvO>x6SbH%ZLW`cV=cBQhPb_+n{7HWQDUpYCB}K$AKeg~4MMSAI&TMM(HZ&x| z3ZrQ74D%%MDp752z*srlteWp)^ z^b}BU&kFiZ(eQ|#Aed+N6ek5JF2 z)Y8?(^J&0-L%CBNf5j44?F?9d0`4c~z~ zhgKGT`4V<+KB7O$Ffp<8t8a!I&$0*55VJ>Uo^PDG-#a=~bzjltdH4Uc)&aON0aARY zvYXoXIPacLaoUt!_%8eu(x>wTQB6);N;EjE$D0ckuM3;k63gxB$75k@D(3diu5aVw z;(omq8rK8j3@Y25HgPL06n{7vXPX(Ei?m1aU-7t-eaaYEyEcYjWx$;XZ;Z_Qz_*!uX# z5m>p|=3(d8jK5C~pi&kha-{t_Xfp`l@6VIXjgh=>3_cEEcD)ED2skBW|tj){o@ z-!MS*0G?*?@d@CSc>hXCN=gDnLx3#U~>hrVPRn*2-ZPR3%V_ol$4Z~mVz)J@MbG2DjJ%b0gb$) zqocE{v#+mrWMpJ%>0(*-4Ip=@;4n*Y!y13ogB) za4GJ$%7lEyj;gB4Yz9qSQITvH@I9!kx+_ipF4rB42w`oV8MsaFnO{ium@FsGNF}pkt84HpMh=Og4fVJ;0+yD?+6=N01}>Vmzk#=Ua8 zk&GPUGg;gFln!nU3D(%datUzr?29po3>++zQ4Y)>*Je82=XB^O#Py*%#pS_pMG|!f zJj5n!eHxW$ami~Bg|AACjM26UpPJpan8Yp#(+NYwo{152YATv!j-@qsohRz=H)MU{ zH)oECF*h;!mTvu%B;ILk{r4GYH;3+ru%uA^F1Cz$Y}Pw@&xAbG=7n;LTzb>}M@AYO z&K}S*9G7}vTQNON*Rof>bx~6DZb`RAU;YGhGbe&%)hbtyN!PkC4j1);w1U7D+fW#% zd5Rphn0Vp!B#nx*O(My>^Tg(-vaYJRSMbES;h(xn>5@r>da>%u-fZysPuD`E*Hfc^ zb=W8e8k9d(_(j$Y#)e_Pxe$LAQcE_hmpA-o|7iww|G>cQ$vWZN&|a~RTCDEXhVfKV zl-RDyKR%fA^HXd;KUJeWOgZyYZoh?(->_{eZ(Y@r$dt{Vr%05Ym*Y}!(_Wa$bx>Zj z^NAk4?(=Dudr@+cfJqZa!_@L`ww z-F>$j#$OOkyQ8W5L{{-EhBI*eS;rS9W+o<1k0Pds(WFG&CZY)y}^>`xn}bms$d@ud#3v(B%ve%h?9pAWB$ z*s3oP{a^eFfBRZNRz=XFe&X8tnE#-r_OL00V|c0{j`4_)^{1lh8})#@LX3D(zac&7 z0@u+mjW=3SSX_kBVf2z0ayzNrF-R(`(GV&->@3c~1A866*0{dy+AoAnd%(#`vTRHL z@z)8bupux;EZ1YY&A~^)$edgudM|xWhdcmpx2z_tBuv(rXWvkKNo)uq|9*7#Tnn4_ zZ@ci6AN6OLDr|T~$>+Cr6YMA|c%+2U(0P5t9A)6W&rfyrrkg0bLr%gz(AzgBmON4RS6$DBGp`Qg=f16ztNyi5A3j&3w;1%q zK&UJhUT++xdo!HYAgGgsa)Fs&8~xwCYn+&QnalO4!E zfP*2k5N}e65&h$@JJ;IfW9uOqxcBCXO|Qn8T%42GJTwr3bSBbf`tnGKm}L&AAjVA9 z6tcoEQrJC`-C0>qA|Gs(ASZO|+DIq)zh*Z(QzFmb4xmPlDx0IqK@e_p>Q8BuU0Tf^ zQAugY4SCJG2%D#lE0@w3=yy#sZk~XB5B}Rr;0`FPeUF+(g)LX-T8zan@iSspEx;)WoXHi|0hR4WG9gkBK;c>t4Hyj$-dKP_3SA3akHR~gBjfz)x}M0(5ockjR~ zPYh;uJac&3x|>HTo7Oll&+K7=)UW#l4*a48{2%xc^^YGzDPK)MVIxR)=Kn7Ky$9+3 zZ=pREC21OSCnq~z&^^r6mC@$D!#$&|gBjC(zk4QDMovanCQ}P56UY00qs~@Nj*M=O z#{a3cIy)O^sLn#d&c(q98j*5vvM}-RNSFc0s0;#cVer%c`=N4^uyb-S^01R|^Dwf4VS+KU{>w1`(uVXOP2ky? z|8qca-vr)vjvEU!ffwFQbSXwQYJ@!4_qCecH!T&PD~xDtUsD{$diM1LrCRpR73cxK zh$=arx+fJuCd43)iRYj6H#u>O$$SMu7lpH6v} znW57b0%nGXRPp)aDboY@D!7;AQ)MEYH{ztEj-II=c%gRdO&Z1(b~>Q1yy3x&mB{+D z7o%mD1^B^*-;1fk*ipTf(5DX*=a>21T?t}h=aC0^cZwJi3yZ6@evVBDK4kB1-#P40 z;m9|0eVgJO6}DqA%_)Jw@U&K;j35aPdAKrH_enTxyC!1scUb;;qY;faJABt#wkKiH zVPnU^8c%yneH7x>P4*(Yf-3of8DI7on-A7bSIM8g_Zp38H^um5^!)R}wgRi^bG!P! zu|f~oWfPprOX0r4a{eJh{cvfdI0J(y!8x7;D*I1gQs$UA1)_IP1?A7uFZxA+e+K|m- z-=WJ}*Hhx1peUxrBf-NOaSFp1VF&h6QVBmOU|ogy@MS4t-3oBNZ@|V-2RRmpHAsWkulWbC&BV~5%z#a zmSXTVR=upN2=lI(eyxOoqje&Q^$A-#m9YKDS9MCo{`? z7csy&5GZ5d+%vApN=c_u>Xl+5yZgG-&$hI?44%$UqA;F5`G%?wekXQOaA_^M@WnvZ zwE^X*EY-Q7pmqIZ5d-e{`*9dF|22o90`>K>NerAGVU%x%r61m!1-z(8`Sy%VL0vU8 zkU{(=sABFzUO#S0LM0D}LKWTw0>{fJ$=vl917ns9SwHbw4AcnI6Jo6)hkhc?FOK9a zk#m<{Fwk{Uhg!T^ev+M8OF*0!Iv~`mR1~hn8LT1`|HzP{NtnHZHO{K}VfC%k;E-Tx zh2fEAmmXDcQD=tWROd%ZCBMu^<3=HJe8kr7)P! zkUZi{aip>cE^?;fmsU$fbi#?|%VR8cDB>U6Qx(XlRuJ+N6u!&EJb19h#qefkUwVshv%7KVq{+hgS3B@PU@Fi`hj!9SvzUi!K1H5nV z{FFRG7)XDz#+8bsv&2PUS@ob}vv+xGSL2V;h?@yz`&UbNEyAAc{7mgOLjF*x{HRdK z{jlUM48w&n}FGj1v9$a#N$fNmj3fquK z&6`frl>3?(&5p9U&n=|qLcP~A@k>nG6kICR@r!R&$=t6wKC9bsj1w*@S|8!7gcB4z zYZF0|`c<#AOHS(o(=(21Y^gt}LtWNt5unGmI*p-`W}>NT6PTvYErJ}H@1PaWt8sPq zK2qjtc>6e%-%D&4O?RMmkS2Dwns4~itRLZcmf}Xk?qQ`5S*sHA zJTIr+6L-vCt{Hq^_nVk-{WgBKHZkGdym5&}zb<}h_W{S=*~BqpPK~CbE`^|lxs7M( z)W8af-Sy7Z38g;XwUW45ttV-PF+#{@uf(gm`@RHZ>*{#q~L&&wiPLOk$9GWE#^KhE% zFEgk?LTT)TtX7&c$%rr>>M;bvc+AqBA{9%Lc{eFWjm+e*F`v+8oVYPD--U+q+`QMX zH`0LrrB)W+_qzIhobc(8#WMH&F<AXpA_ zyE2C@)1(Sh2N0gSh>QEPN6Tk-L16YQ{QnniZy8o)yRHi>CEeZKASEqG3P^{vgtRE2 zQqtWeARt{zh#)Q9ASo!NbV*7h&AxcwIp5uzOOv5^L*N! zR*U}`KZ^Fim|w6RQ|0yZmPHhw+pp5!&4{TKEGP4)3g(JpoG~znSVU8$ocWK>c3P!Y z@%S(sDG(edA1EB$POqj64>BGjH~l(sw$bU3NxUs_@oT!fUTu4O=Hl|ys+HS0Yz@8s zye{CKt3Ju3VNpsUlcNEfux(x5cT35DOZWY~%ST@ZjxJ{e2DVe}r}&@gEuJ7)>rv5q z>2rGvcE$m#YFV-=XeR`+x~w%A-%x3QfU? zvW3=76v8X5$5`EpY3et`%yPKbmc+1P?0q|1?B0&D4IX;>Rr#%XFe3VqV=t|(-%!WA z6Yy<7vn_>z%f<4pQ`losyBoN-MHNg_G-xQt-Jdx{yi|ShK@)iqms(q0YeDe&xS8Q; zd2ajar>_da`05zgZ(kHY`16Z9I{&+|KIv?f$27X}QUGS92d;^NUz1Eim%LjdiKA#2 zTa&5V+!)d#>XN>(qOgAS*JC_pnUIy?G$Xolee(C{*cAev=;*Xj`JxHwQr3B#Mww@K zSxhDFneYEd{WEm-{_-(#=*k!ywnNrb$kKZm+}bH71Fvsc1JdIe>^Ft^+Oq@B)soaY zHDl}q3WbDjg>oDAAd0^N>h(VR+iy9rOuPBm*y|8A*W~wTC}ufV*RgMQl)jwE=O9T@ zrW~L1octWuz{ZsG_yraJE5R)zm8PF#Yo3?{mRF1}IGufhe6y|Mw~Rd*O^F4YqthaG z?On1@S|@X51m5Vlpw4WiPKV7RL8`vIY#QFG~%Yb(kS_s z_$s?A{pX_v7leQ{LDe6RR%SG{$r~E7EWYciG3c#HRlPEP^ev0eamT7i#s!}}%JFQ)b6i?SqEpR4PV!S|Di1pKV1VlglT#I zfhM^AO$2`XORfI;Z-PAV+h3aX|382|Zp#CdKCUasw3_gBt^;Y!|1DPA{IW&+-vA*0UN!I;qRR}`|GD72 z{Qp?;|B+%n|KF&cf3qC;pYNETkLTaN=X4Ks?aB0Rj`~!kr(5r;U!Q+UDd`^*eOE0g zri#ap8ugXdAyzlHhXRy;rQ+_N-9skC)t>P$@b%3SCohvrQQ`a2pG?NjFUFr3miwi{ zy}${dDwkiC&#*APX!^&6YNp%z^X<=DTfyF6FC|7toqumU`nUv*{s*EABX84c659o)t#)?jq2|xc-3IxZt6MwF+e8se69IPEvQyG-e4C> z^70%C1Iw7Oz+ivMWgMUuDINmpa)pUZ>JtMl8a50W@A4=e`W-obqX z6?qzcDTGuW_I&vw9$@ZCm23I9NkNE0jX{#~%ja--vc{p|s5Skz+)7sxy_Uxuk8Bs& z`yfYO=oY}M2M1MMo#%Su7*=o8&40wkRchL+a%gVM*s!AbDnByyGoBP;?T?!E!i+olGMYO3 z#Osnn=hx2O+VPr+cnSqg;iysgi;5taRzH;9-o|& z>FDU7xk4PlL{IOp4=gZMAT$Y01R!*FhOvI&JkS22*+)P|7FNy7!U7$SExQOuYM%>N zwey{U7)-gS6_Qzs%Xu+Z$&1?!D48DhPOFKh*+~^DcVQMsiyf1Yfs-?`u=gPcCsyur zDMmx4{Jgv#LKI@N*(_?BnYxSC`>t;U@76SIbq|>|vKew;telp(vtxGinhk3<6cwS@ z0}+kWbLhD`W;)jr)jVG0fibkQCorNoH8MPW^8pZ2o&Ws)UEAgZ#wnu8V{4DrpY)WA z#aBB^s~F?v&!3!H-8N~y$a=Cjz_23p+jGyoy`>LJCJFs0t-*QYp`Kk(W$1Um$#TmF zc|?rgr$|%UOdFm~l=<~xjFh3Cp&YtxuWa|1HlHQ-?k0VlG40Dg%q=xOUXIf2GbC{E zLXC6EXj?rzh34b%u*Osp=!2r@22Os$?|9eQ+tU-OI*erVJ3#f8=nz!0F z*Vg=a85jZ#)!+BG`38V`LWms@$xomyCH_6$**Y0-j5oiFeijb|)&fS%okYx2?X%vC zg^z!E<7Iqmd~#ZHfp~iytBLROn~B%)*{wsFq;(XN!P#jaAlWZF5J4v(C3Rc^NAF0BWgim3gBlDoEyZc3ultGDudW@@NgAV`xsiclt`LgEP_YJkpiq)9&O5jA41y;X+8l#^v(d)oFA!*v%YH2{&vVBhAxRk!HKZ>s zS!4*3Vk%_W+GZptlRm75;o-;WFc_OSmg^E}ck+~yd5n3YGfCmbx3uMusXGD!JH`s_ zdKwyZjRb7V(uF*|i#kUv?CjxHtecGUubOuA)HWtI{1lm!b4A4Y%B9%>w;O^V6YkI;iL^VAa+`LOo% zazKUQwuF{s*fPHCO4qjJk!^WP{E6yehl6BO%<}7fLKGqWwPb6dhmNNQw)WUKIE(WA z%fmN=%(OHeT*Dw z3a77kpN5KRpgZ6V+|MnlSZdUHm!_%?*Q=Hx&s+@hklQ+cnktLWPS!|1YFC>S*oc{o zJ(sA@xkd8e9S+rM739D9awP==2F>OCza$F9JP1dYKDahy2ZvnCS`cf7fv(i zaT}k^js3BcZ+`S+TT5uS>h;XXaMJG?*PJ%fSLKuJeQ4XrAKQRXtBhpZu2TePs3(wF zWUZ|2eEGjH2Wete=JBel!ApfBkCoI@Tv7g6OJcvFNFdSZVYAHVgql?hY_TR*~(veo_4vdkp1`iB@kz3+Y-K^%@tVtIF|EaXNduFxHTMp8!1-Uyxe)$4fV7RW7T* zoo{vpx87ksBjb7)+rs>ex2)aS3>(uUP%P77s?qtdQRrjCpY-q<>nHc$-8S}KOB(my zit(qKfJ}-j8oxjBmPJr3j3b1C5}6)5dPfzePil_ z{@(9Cqxs@gwcc_T+0UG9)y*y4x|#|Ou_QyMViObV0m(ADaPy|$!#wKS-%(uEF3Ao& z30FpIdBx8 zi(Ua*Z%#^2gp5xK9$e7g208PJV)m68#{s7J$COzG{x%ojp zw|=K!P#n8}t^Wh+R=^ZuGy2|f3z57VUR6xgiL$({e$-)F^@3vrxtL6C^8HhuXj^2q zND2-3L4{YBUD?WNMUg{6c&gydATD>;qaZX4j3-Z@UUO>#*9%afq0Xi( zS^@tqQ1b{ozgJCP;C}@(*uqz}p@8zpesMuFncNx_3Sfq?Fe$9v-CaOsurfVWcu2er zTeQnrwiW0e(7Mfxjnjdv`_toF_*1MKufNiZ6ITK|%r(J_RQ@JrUwm@%1PGpe(%Z?1 zjcvhTuP?Gs_!`}a{$gjY6^PRTtZ;Dfa>^;$$^W&H3)B}0ixtw zcPI@UhfOFa3r5&OO-=t9z;(!^+aCmewN+0BXafWafWiQX@@=1F2V{QGx5KJ~SVq;1 zP1V&^h}+fOU4-}!D0Z|REG6#H^Uy)PV<<<2>}SvnxF3qtZiUD{8jikpqA?QvWc{U+wi03C$27OoL_-NY#TAD?v1 z9Jw6#EZq-Y-4&p5C7@P1jYDTpiHVGyi$=6gMYb%D(|SvMbp2#V)9Pw#g(nqSPD1#< zj*X#&sOyCX=pg=H0l1igkbnRHYd-bhWXEWdR*5?K#C^0ZD;#6WmviGJCqnswUzEc$ zQdzDcEq27-Ki?iQPx^QlAL2o$&PY9pc8}KAl)B;iWe9DryIr1YI&_%wWT6l*jLNIp z8cYyKzn3xtj1Gi?5mh&cnE}_+AKHnq@&k74$;)=Wn@!=*`)P5;_y84?{qRq_yN#SyBS={HGoRJeS~-*ICr%I~tYDjI`fb7lj z_Tw(V_AV?fithcY)FZ5*eIRJJxYpJt{e~<_v%U@0LwdFH?iv8hTbTlA5VqsU=KU9{ zAt8=FyHioNk(2gNcz@H(p}_f$pQavdANlJyRV6&EKY{tv zRO4DV-8F?uMkBYaKODgn<<_n7(a~0fq#KD3A_^{O>vD4uE9#q@P3*M0+6h+@4om9l ze%K4=XegeRFQt5uTrJgwO^lP>jB7ixIBUqFj zD|k-wDwH6!n%k(hELiUxh;oZdOL4aO#JDS6f;3QCK9rVrzYG|J!wvkYtJL{Cq&Wa! z>!G2b=!>Xj!e?@4Qu31~7~%H>j~cOm4IadP4fRCPJF z)3}?MEjx|Oy$Wg~@hkK?h*o~dK%w_8KYw06;7ha$DJY{L$N4eKaJfrSerPpqNui{q z>=4_NvEp@`cw|e!ilIx!l4khbC7UjivXZ;RPcQF-NpsUSox%fGGgdoY(l@cet7V>7|%4Vu&GPv~lN#?p1s`Z5OT>rSpyiI36@ggFFY8;5_(j9&+Qaju(~GtD!mc%H%UL$ zwvY<%;!04Hl7{bVka9W-I?VK&BZKsllB?N?uN=|}r>Fh1j#tf$u$zk;8`B-k(J&3cXoIZWb2BvvV8B7bbeoyKN=z-jRoBP6l-J%TR+F>Qtx zX^Iy4Pb~wMrBC(s6gu-%&tmr6MzKwVbnPww+AOSr0{tTQ{IoPRiHiiMwrS5WbSUQK zdBFME?QmB-X8o~aCQg>Ui7Q&%R@RJeu;U{V;zlj<+#=hq9iQSEriZtx+f6;$KF;j1 zd%bx)kKmY^n$n(&emFZonrG%Y=RxHqBq?mewFA4rWzr;0OM642$neb)(#`9?HD6t9 z7hl-<>g64uoh^R!<2dW*9}-u=eTLAE6M!q@Wae|C;D%89uGZ-oKhUt1wnP29#sLag zEi|@Bp-&04;+UGG4sG4tw`SIq{C95f5U$NCH((yc*grdwN0RC(`$IFiYRH;_b5YDW zFY;H^qpM2rnlB`dT^WF%K)Kgx?zGLrKy669)?WMMU3{Bxq_)}dbZcXKq?Wx~&@TyN7pc)Nv6UlUJ5+CJ(cFs0Fjw^$O$Xv zgAdwaC(MyXe|q%P@_6<`2!nShS4w&8Y|WNL?*wVcw=)Dek!q5*y>QHELuD98%l(3u zJFmDnjOQYSF5`whsFlp4u_S6HAYvvUZYwU@#vPc+G|ZwDXjt}#!Zq-h%xo=#_$^J+ z?SShKRxoS8dB>v{E01^mgcyT%B^;%E?%`4+UK@7Rpufsv@Uj0XaKuHL7yru-P{V@B z18fygti_42Z7&D$!J_rd{g%Lw!IKWkCRL9h^zpd@5vlku0DMg-y&=CT?SG*|ELD5s z4o&cqC2zTTCwh+pU|!!P0tB@GGij8(#XUjSKM8I|Uvqdsd)cv!i}-_}!n`0j5qbG@^rm6ab4NzDqBQ`%4; z+v8&(uhcg3Sx5*RRV2Fr}?~l-if|6DZAFYe_jSS zz^Dd2mt^Qa$SNtQs4!iBp(BSWWF#b0G#?OYuyze|BvlA$H7&dFS^oRZqR{yT1zkX> z2VlT=o{ZII=>|T&CpwpZPu`z#_3%}ORfHC7Fw3u{C=Fpm91mMYG11UkH3h`Q)0$tD zVUVrDKI*$p9nLQMjbJgZw+5-@mcvMOSkOxLe|hta#;HpL=BL z6AlQXmEe$3lAkU_+y<%h4hhx0{s>h!GU=eO=x6{wXQZWxLkf{C69Vbv^oUT+(8DM< zRY`aw>=zOuBC;rX_!;yIWz3?fHV*gqzs0rTa!VEPz-STh++(4k4R0I*lo(*k&(>0Z z^&9>C>)k3g5u9#TAdTF!_RZ&VKhx)Ql%=qgbetc%D%9DtMf0kHEpt`s4!YX=`BfZiS8q*DOG4BUl052U1SMhfd4 z+u9MEvE(~RSu-i9MI3pvQ#g~_5)ME$kXpQ=p+DL9HEa)V*~ikoll|ZHo65oc7CFXba#UoSy&#s zR2;wugP@a=j<$Azeqee+Co)k6@z#a5;5v_ZxRtBx(2&UmOk$ns(+6uE3^q(Jj=w)YcQTjwBuSPzi)e8a% zbjcuIAmRF(a>%!nme?0~4=sq$x!P2F-#XGxWmabP%2Nf)4F`sgjSICrz7|n;aS?n* z06K4tFW2y2_M7tTu)e*1+-^(OinUtpqt>>{;l92%GOW;S5T5Oh&?`moJb(8!wAyht z=?)!-rI`BrvhOh60(3oP&!xKEP#Pb_5NQDv9<(Rl%1wMZ;fNF{vHx!7MyPT_t`RN+ zBW=6hSC}x7 zsmk|>3D)a{Mvt;72Cq*4Sb#jpV7KR9dYh)Boa34N&?oshGIbozx@A9%8BemwBy!K~^@3*!}_21$A8u*WIptq`G09=DH z+7!dM7V(m2ItH-Rcj8i0``D9ykIbl9=3*nRfvJ#t!TH<@%nL9Gf}STf14ee3v3NK$ z8|FNM_z9fxMz9GgijS?{BqseLi~8#MObX@NEL;~4%30sO;uyL2c7*lq%V9JU$QV=< za&4aH`3dA}2&};w_9g5}E#nAhHh$TLtbTya3 zIT$akFhD~r7aufWK_}o&tHKCWbaAcIUX0WXf$02VBrJEfX56<_irUOH1XP%{Ad_!G zApL}acKY*vn`Hr8B*t6jAbm$Y!U3S?r54vBR{drpK#zE)dK+BN7W%iTDR5gKDlYd< zfiX$k8W=TU0G6B_W;e{`&6X7PZB!^EUYFIDIY-TlCZ?zPtUef$C707eb=hToi!_f= zS^B!Iy&ZJ3F;UugcFF`Wjo~a~FuXWe)vzLz&(IDY)83~K>LC9?zBR%coTrx7uKpmy*tx&H zxs4C@_4Cu#&a04kBKP(eD3rG^^ng8}p5R*y6(sz$6+1e7S_&eS_D8A_+O)eLY zJd_apH9_wB-PhY~g6R5z++d4Lx_Rguu~3ZQ64!wHG4THpvHWYBbzdPOZ~e6Rzx7bB zDG&ZZ!1CYBHNnu7i|u2}|4E}528;gLCyB_ct^lnUm0>eQi6P5W0zPPV$;O76~;L$(#s3RBqFp zWX@?};&(LH?M0W)xcbNMe{TI&{b~D|VRAa`z0o%v{yY1JV#9@f(=$P?ez!a&<)%gd zxDMU@HTA;hmxs@<#_rD`UcS#1h-*%8###jb&=eDml00&o-$$8?t*QAVS{08gJv9%k z=8{{IZ~lCq?!G*03N*fqz8k`4f;})r@n)VTg@Di)*OT+MIOoip@P`~lxI;eY%iYbV zOPSt>YR#9&ncf#)B(ILP18^iy=MA?rnzb>EfvB*Q3yUETxBmFHPr3C~Ttm^jY!je4 zy7WPjWlE$-|NZNi>i`-)_l7}0!R0xLn&f%6b+g-PUrdGwvhj^azBe(GsHxft?X+>KAz`lhOU#}jw=&y9^<735!shy75p$WljdEXIjQ{+SXDc*W3z5h>;IvN9P@vHg4AQNy;8JW?muGohCUn zU0HLPoTOu59RHj?8uba&ojscrYPv$%V^y1kryct(FA-v?n8@hM6`|&n_2SYuiHWw0 zKmGh}MiSbO&m@lNxtLehTR{|ok`4oEFx!{*_HFN%FHX(<18sR~Ku0MIm2BYh#K))S zghF>6ke$PP8&vwB6kutYZ|qFAjE03JXAE`ln>TM37e#F1ULH1|^(UEJ=_}7v6_z&N zJzu8rJ}ABlYHq!KG56!E&_;06JZtj>h+~u#NK->d78sl1Oh3Z&HZXTj9WrX_19rI} zWEV?s)D<3%Nk^5Jow_rgCWj&|vyEqdO4`|PzQ#i|aeRDS3sm*LVAM|n zv?76+e{ksbJ(R=(>btLAo`@*ak7j=?dmyJ{RO@)NlbDETo*1Se>E4z%hGVtoMZn~s z(<-Rrjf_B*7ULaVGRJ)M;-~VPTYixdGu4gUb+PdRg4qj)5j^2bG z3mswOk36>G)g)TEvFQSov~NFZ2<7Di)fBFg5pU2shv`Lk7Rbby0TYZzuIw{{+e4HFx%7MwjCujgQ}!QS9JDg+u_+WV*FR92WyC`vAD#P(kRn)2|3|f zFk+dXLyr}~E{U|?EqRf(GVglz;;{0VGRtPAKJ&Bq_Utan)n(hk@6;<9U2UlGz%VLg zI(SLm$MYfBAu!Onlp6!X->Y~6ED)gHxue5W1hF#c;;KK0B+SdF61@>Yc$0v^oP`vR zEgPMY)~W5;$DAT#R-zF|xMIB+vvhmKLnU`#-b29pdc?(?C!DwCo@AL*YC)c!%V{!! zLnFaCxV5=yWO)6gQcZMKk&|C8#-^PivZnUn1i`RqQb=s@C!mTr2^DIlk{>UAs-~xx zT%b`CXA!c0D|339Z+H4)IH*Kxw(-@KMqh_3AQLv4PdENNIeS#xw12p%``c$fbrw@u zkN2Xx2MZg!OAnX*?YwNBSqB|Q4tg}D2)!JU?Nc~4sgmwj2R-AiqbgSi0XW&k+ZXM( zU4#Z19$hT1-}1SNu)aF(i>b$%DoGUw}57bW7CGq1#-m#@#%9HQsdI< zyEeXi(x@7H_k9+eE$2!b+A2O`Nf!O~sw&#xs4(%!-5k@j-7w!Bkh{P3)Gb;`dp>qY zwEuObiFPZh-0S+#iv*S;S)ygyAAULJ#b;qRk@iCz8VvEnRym>{wGH@s9dv=Y zp}n~E+#K|J#teaStC8#Ym5amq1vw6#$)n+k&-@T}!dFLcA*P1qeoZUX{PO9M|9#hk; z9=y1SH%Sy!%Qs#hDxy+kt-B*ETyQ3*16dEGvOp2een5b>Nv|aSay9m=p}h`w$ptpX zp!+o>!ucmk>v?O;jP2P-jgL^xS-nFOqOsRjh-BEB+i^Ngvunc(jq^bzjv{sE{z0DK z>YPYBK%ukUbjBUIP+>wTZ4l1>ma&U1hh$Uwd0epEq&8vshm@Dak_>(v z4@K{%Jamr3-?AHI(AicHM*EV&@_OaY~Nq?B9s_i?|>FQNi8N6&!eE0 z_BGwB?;AEow&T10hTRwjBSWq<1GeICe-e6~zOqo_3V#1vt%x?6v^lmgRW-JSn|im5 z;U1A$(fVV}k^*zidm&L0+`gvXR|7T8f4YA982vbVzSXmt+g*A&VCZu)?(-)g({rb) z+1=37A)jb;Vq!uDJ^XieEbn4M!YsL~Q=3mR9ey+ci;cp1aE87_DDis|Sp9-UJS+U!WW z5X`PSbMxI{G5`PHL%v$LzzFw*(+VJA%fYb+qgYC)7c^y8vK zkaRF9y?e`LE8?uQiN$0hvrb5$Tc~`sN<}1!644;t3Lyo4Ofeq-a8Q3CDj#O>`EFSIN)gB7)Y`O)6Y$A zii|_3GkbU*!yYjnQIvE-qtk(4Mwe~YYBt{*f^$r>i!OYUGqiiPlDd;}+f7Ep#B;Y( zhlt5vZ_8Cp@S|qF(MKis@R*pPzT3?W9)Et5V71U$%w1g)NLSyasK{VPBJe9nx+yFx z#}sIfQ>$=?E^s2$Spy1hFN7(9{2&SK6U8x6!-GHXhhK^>d|Ev%k<;ir5El{oTu=b5 z?g6RL>6X$t;~n17TT<|XFMqw@@aTw}gX00LE1#vi`=mG`oqS9E+~XokXD-nhQ7Ip0 z?&0gtf#{VTXioLM>?s8@nU!ek>c&Jz14S0l7y$O_!)MBJCP-($lFvUb%H-G(&FDds z#G64#s@BZy6)8C`61!BcW_ox&R#$MX%3y$IG??FsWVr%}D@$nZLBz(@-`BUXw)W`} z_T+O$W@aeWnirS1cUR^VIXCq7_5$P$X!diFj{CoU#pUGY&=Gl0WOC2*@u(pw{27tf&}v#Hugp7yzmS2{nqo^&g0I zN*3uvJDAI- zbFOaAODPI5i7lm(oNn(x5KXyV2ihY`d*AsUe* zA4Yab6iIx>(4eZ{V@DOX$*O(56z~*rN-ZWoGuD4ZrcT~K!f`TdMZ&5#_YyQ~rNpYI zH`dl>Jdk8(2M|YLNy$I~rF-2o1Su;isaBxa*U0Y`%&_}ZCRFhSRVBY#3I(+>!?y_=oH@*0UUCmzqT;G_W8!=WGPqfWC_KnLl z1=qcoKZb{SH^7wjrm@%f$uh*au|<|8dt5*M>W-Z2$FH33FHRwRZYAWWN6*Rm0fdST z6OBKA_#G@lJsqs~*K0;WoN2jygc?=8`}$=}?CeUGey*)>7V2iA@7K_ceOjm)lhbK{ zu~piZOx$`uldy3uJGsQ@`{KmL%~h8UMNqWg-QUM}-t;jD*Tc`Gwf@noHKwiR!jaw3 z?wpO9F%oS*!o?}zacjKyPm{3a&;AdaahQMQNc?@mCfine3TY<4{-Fp}j2oXp^D_M? zB;O2#I*_R1g|mb0L6u9ym9`JeQ9`8?l-7U@og%vcUph2OT^o(AL;kN^9bTT(_Y0M- zSSp$-oPF35pdLUna)wIxu|=WPE$*>3ja=gDO%@SIV&8GmR6kWSO+|hf|p&U~rqac|I3?-jGi}V0xzYn;! zGKYqOoTI!v#y?N)*FcQ35SGj3!XU*DY%-1kf=zZ@N*d6da1y4holae=4Rm9F7H$Vf zEhyjvJzO|CDyr|XQR6Ee${%hTIwmd!xhm-3h8KCD27JuPK_IZ+HCHl&Uc8;Ht(2Y^#81#DG7BV^36I0#rCa&Ygsupp zhM-vM|Lg<~(SmWYw96YTo+82!$4`fchpe(XdnJZ7(ABaKwAA=fp*?`>4s1_w}{6DEwVc)iju7NrdExG$g+$M*~X;^Q#Wuy$so?eq$YweEo zl^C+|5fT!v3Q{iwlYM-qA#YvymX6z~fvu^m4EG}PgfHVZ^A^+-pjp(V59BlDdIFD4 zOHyCLt!K4Xz8xBhFR^-o}hKezOY;IXv{ST3*jXb5YNseHgVK6&Wcj zDC96}T89#Ij*Ijz|WrSwBQ2k~gY#D$l23|l4n6R8nmU=uNfd7w6 zfM(5OzKij9crnPgZWTY5)=s2n-ZKG)!ivY0>NPu1VT?v72{qh@>Yct9wt!SY@H-x;$g7o4v#k9Q8rl6&~B}zA{X@_iI}l5lg~-qQ}Z@ zWg8AGv%0o38y8n6qt}a{zBXg?j`q(e7~!yU!pVM!n?nv8QW=#OwpQWl%q% zTp#~2wExBwOj76A?agX#y!w5_3_u>Jdgw^?y+8>GmVj}P`!Uof$H(?A{AjzJP>x%m zA%d*}K6dHqM=8PBa&(TJm^wVoejrN%PXJ^|{fXk<=cGA5zJ1%++G?ESV(O^S3n(}h z)h*y)WhEse)6bMIDd?L?JIbh!`fp1~U{#*FJb+7%F&8xrCT=8f_>gl|n;0A4y>kZ{ zgyAX`RZYGHUFbah>gCi@*Ywi#7D5#?wG|Z^TV# zL78^i9j!!cUCR$0YYDyYBRWi6Z4$nhTD_5vC`M3Vsi`@F$Kp0~*X#5Eq|_!r4i`wg zj3>aIvlRsv=U}Vu&`*o~U(!_Y3mTuSG>~ES;eip_=5`*Pot{F%`4belzZRrwxypGhn_ns+M43=# zDgQhi@k>Yhj*mm$PX&}!umeL}_ zv*C-90boPww5GH;1~{tD?(Sd9NhZMX`6mJeGVC3ntG_-^{vHor=qoZ`8EtLp%76Mf z*`y&n>4yQ7V%N^@_jEn9zyIJ#8~Mex)fD0YXK9d081cSjN!sw?qHU*_?XUHFnk~(!M3hd$x zOQ6;xe;44?*Q9M?Vn3&*HrJa<$hQtMbCg241y!%|^Fdx*iQdI|{AUQ>0wP&tc=(7h zx6Zq$8QLu436uI@Nf$te#NIOo9=9J|G8?oi!pr9;`wN67i;ly+&RmAxRerxa*U6*E z3%C4IQpi|EBEg!~CCy=9o1Jp%xT5FdHjQ49UOL{!io8AnEfSq=mp|^D%ScOi)T08S zT2-IcnWzpbLMT$T0)=th;l^usqoyA%bp>yQG$#>J&+x8(t*nHfAAtqypx@vss@vF- zaikS1I#&S9Q(@$a1FrhJswc;Yp~^6t2I_#%7N_xagiM~ACKa%MyS%)FkXz{4)au5@ zw?-saIP2zdhr~M5hev=Qe4wP1RookN0mV5=>|1%cWo7E**Y{nbS|8k8y8l=nRpZsG zx@U`Y)qrdmdw<1U`ebsi7%RbnHshJP>_FJIQB zV4XFmeK2;X&OUGN6M{%*g<`|^pO0QPUy#@rUEwb{*`LN-MalLP)0zV!Z9}&y+_~}1 zK#=4mO9%Z=J?)G0bKI)+CJx7RxKn9CW9=_*?uFU`^Bxaf2Wcb(d_YuTfkW3pejNbn zv-~r<`yU5`)~J((wIVL8MY2h^y>}x(T?3Wgg5_pr$gldp{+FcoArSE~(utuRi_0Z` zAduFM`H%s1n>%T8p)6(kIZ)k$5K;nI1SKVB;jFxQvtmUNdJ9ep*qo_d*hf>l)z#G_ zBbo#?c?GXaA|7a{C@PXsQU=C9j;MT=G5Q~&-ZLNq1j<1$dqD84tAj9!&no9^YMND4 zw0^w12(*RZFo2to`I({ylOf3qji7Mgo8)I_N4K?)8-w<4xE+AT33dLcL+#qynuT7^ zept|~1Gl)Ogy{A$2RHXK8yjEd$3l=@TNQl#80=(YgUVaR`PANi6VB=4;^JP3OHbGs zDDk!b-tcUG^xy$TQF|DS{^*VB;3h#$FFi7(a17DuKFBu)qq;zzeD|&~c_&q7Mg{;s z(s(k&-SHp!-6Iik+OQl1eUMgu5)zWAJ>2rRABdO4C)6>vJJS_AO$HajCofCn)j58Jn!^7ozJ={z%a&esSI z92KNGpv+DZ0b)o%x>~*tiH+(o(q0x@t3+dhW?oPba?iWpbh4aZ>ihkaFa6!r1}9 zraS6pPL=C$g{NnCNZ`bl;l!THcUMe|gF$mkBVIhvo-uVVh23hGRAM259dZoiM!+C- zWRHzK>|d$;=Hvb`u0UQ^Hmd+y8eLuTX0k-Ed2oM00f9lI(fdO5T|P9Uq$MHLD_Lg` zeUOmz3UD}3&sdBOO}T_VV-S@qBO4pq5sbIZ|9+7BQX>UOC!3!yqgM(^NL&JF_(z(& zJL;r@;POu&Unlq&s7xOMz5*a-<>h>4I5;>VRA!jfsC+@g;RQ#Bhx43~Y-H~LiW1`r zP>_-D2njLZFy{e}V{s$8d9h72;XUR3D)aXQ-tNn2;i&XHh8@J>VH}6%46yOiZhOR@6Rt>kD-?v6f z`^)Lg@jYgXU+|hh+!+7=lp{_G=Bxw7q@yqpRB{tY_XOW)_1nDXnP5>s zRj70n2uQce5qJHN6h#blHKxmEv#woQVj@h5GERmc3n^Qg>sU|foK;(Rm{3iM+;gFo zh^1w_4|@t&D*+Rwtfn?JFaWpyYiTLjVut5mWvnoxZ5w-gW$GZN)*D-Nw!9*JN+M4l zYq1;i7e8%zCzKp}2RJ#i??^wQmC}rc2o+p9$c5f@+sV>X$p@)l#(nv4J13{z!o(~W zdpOEN>0%-8TM9=Rl+>9YI=@N%P(oR6XTncRQMR_lXi@dAik6J$6y7K(9evgd$Dc+% zH~Uaf04c5;h)!Brz2jN`II+D_bXl7N(=Lk~QYjM)uZM#{;y53VR?CMz;kd)1L21>4X5sI{!%p*U$dhFNF$2g~IDq2i7C^t;27>A9 zYF5$RA9c{18s=Xuj*G*yT(LxE#!`QT_xlIzLSR(Zh!AIg*oTM3zs@19HjlY#n2W-C zyEV_DibOTkT2n{oTFdegS02)%t>^;tRkIuB3o&%KczD@_I$H>reM3nXYKn@jEqLJRYx@QdrKrL zCH?0E)VBe1Wv_AP73SUB6fSL_Pg#q)=vXmbI@e-J3YI4(lCN(}Df3 z;;=^Z-@oreLVB2Tv&P=ctTnIHk@%f-?5kXqRq`sY;zmbl@!0R*zc>A&EfGiBb-J%D z1%3^D{?n&hEiJz1%Fg-@H?J%k^DmusH%(j|bbO5PP-^X-BBgl%?npqhiES;^91B<0 zygQmo%fN`*A1@@qy^?rYAAGypK|)fJNt37kXmxNfN{1gRGhSNXx6VU)^6yV$%DH=t zm6apc&2`ZBQEc}6ko-o(ogb^H&%3gA_c! zYCnbP>lO=2GjO;yiA^KS30U_uY+N8@Q=GNCorXJ<2R(Iwb50a(;?lUv5(N;}g-hKE zvVHap8x1Y)`FrCQ6J71=wXLo$Y7Q%)C&e(h>voUU#h^Wm__O=|3fQgj((@?$mREm> z=%`h}ovWx|RkMqAbbnlH#%K8alhjcTDhXh2Lmnb#V1&Ny(6!x=g7bC%ezz!5Q!AF< zb`!nD16(4a{PJrX^ixwC{9O#H$X^9IX+b1ZY>Qh971TL(pWQq>wkIpPhlX&nkKcJt zNTW{r-Gi9)cH_Zov8#9MDNuKwQ}lcA6NY^-0&&afuK$ReiDjs6$e|yX0J#HLaj5AhEG#S{dCYcD zU5C6IYJEBDa1L$wTq?@TErQqA?MOp{gK-i2M!LGXpdBDAApz0`TrYB}pww1&CTfB` zF*4%6?zj*}z!FLR0e=+M7@Q&FS0dC3l^9 zR+GA_K$fWOk(O2fl6GZ5K~El5-LlNxth(AX2zDP_R9X7P&#jR);=fGjeSUT6waQNI z={AOnAuj8jGbY{hhT+bgs%;Sk4xHA;X}o{NT&UPD(a`MUh~*1y{}FMSWnV{J^n{dD zRC3Ng()`!fY){PApl+uTpko~r7)bj_+T6`e?~MJaCB@6W?X9h+4i5Ke!a1h9S`T0`v)}L91P0h`cIpyHc=WLhD*SWCLkm4i2 zF2XW|YVYsu(bLmwyC}==xbfBCmIo;)D>s}`<|T&kTtEG^Xk1lK4dkHK@3pzPGL-(x zbcDmISIeIv@S_XM;h}M`w#v>p=bQ4v zRtP0@SB9&lYCMf-4T7xWJ?-pu=NKWAE^@tJZkDV9bon%O`2wD-1;Yxup;o4 z9z!=>IvUDglDHSOLDVvdcklsyi|6ipfeTn zOn6Ht@1r^)%cFNiP>KQ0PZme`iyz`G!R7b9f%aTHnwvyALOx5M&6@F+V>EPw{!#mf zxWnM|2`&f4p^Cs`Z||o1dNFqP-t_0ny|aGX*y`bS!0)cBJ3ciXYhVxz;v1v zAAiA7*pXm-_5$q_%^$hZd`qmL4`dqJkP1SC^rZ;u!z0o7noLR>pe$79dBP{K1DrNd zQBi-tpEXl|WBW32V(2ui=y&f`)7v}eQ3%G2(9Qy&4z;*jEZBrdDB=R`dZ^jo6&U3o zh{ke)@o$o~E$}1O!`JtEU2zLsqU>~6c0BX1Oc}y!rC3dIH z4SQ5bMaH>565YjV@(Z}Rxy^&ASJU1zlsL0bV~#~3gtJfPd@#u?s#mD$yK`REOS|9pqOq{gW6iHR$g zk8<7eg2##h41_u#ZR#haym@0~tUWL*m1P)LuE_nrYJ2XmCbI3N=%d&WP!+IFp0q8+EGCe%d_h$qN1YU3Sz-RSr%DPVNp@Q0$6ZGQL(ON zd1odOl8O6%@B8-q`44iqb5FVFo^$WH_nuS38|JrNJn=Sc#*L-xL3N=%FznplSg}@- zefb?SC@2c->5F*~`B+?E4BKD0V+6&5U^iX!V*i!qh#SDdmT5j)#a(DYXMPQjA=34A zKKit?v+}q`@JUJ0#OkcLejV<9HsU%DMuoMg`&Dtoe`gs|M#3#$qm77++vbcQB)Rha*{NaKpJnn(n0@p=m$96=YUhj9YEVAZeXXM3K z@>Bl086hDK_tuZa@rJs(tgAnV*>|*d+1Co4Ck{%K$(Rl%LB)6Xwp_S3KxhPMXGTws zsc`s(Jj^S~HZ?PI=5n{fs^7%KWboiV`!6NG&AqGDG>Vzq*~bRba7-xL+lv$$)$D;qbiuov9P5npUp~Db{d8mfVb|||e0usSlT%Rw zN6@-DE^sH&^)N^p%?e$5CrWr1}eCUC9r54MK!*0pR7CoE+U zQy*@OlpUY*c#;re9Uk{fmYMB*CHhtBA6!%=y0?RS#!Nc??7p8%U;B;B&J9?sn>*yx zpBj&o;hBWRdX3#M<9)JbmJ`Da-oqh<{5nH?e_-y6Nj>av2Th3{IOMj4Lx#`s8Jpr} zThFks{7Df9O0T_?5!xSiBMxR?OzfN9F<*B88&VGsoqofHz+onY@~xlC8rS6M@6lcv zA8EC5(vwz$0Xj!A1tc5hk9CQtaWCp_wuK&JrGb7ZQHl+ep6HK)hyBB8eA08V!30^h)~_OgjYK<*R5Nr zbE>FFckG&F`GzS|%U5=?JsH}+9*l^N_6S7mE}w&^Bu!WP5aHKG85k_Q-G_*}TY0;F zsfKk>(!q6D&b#Qs8n2DI#8RuXW2XM#IQP<=*|TleTldY@ILqC^^GvUCwCG&57_Lp^ zeoAd_%{;D(Mt!|Ct02Ax4qpE4_YU|&%T z&qd2uwwGrZzLvA4GinBZ_G;Z-*e;{g$ujvi$=^c8E2 zwd; z#^%+x?R-ARxy4dv4`L>W@b-^&T*2ke%~@mv5^Q^6lb> zXg^K;O-obrv#xpaJQ=xhO4v zZm?Bf+$i4-Dt2OLv-D1Ce%7v?>*SJ(nv9;}_7+b0TvGF9_@+7T8=Z2zpFFw_5uJ$8 z!VQDl^fHVxh6xhh&Gbzh6~9^QUjs$e-Ws}%v#A5AXQ#}vX1k^?V3=1Jccw3RGv@f` z5}dd`-fsN(i-m==gk||%B_CpsCO04WdKA^1Cp!pNyO0(c=48O+wDBxF`EMebtTD=P7HQp)8Yx2aaugLMFZ@* z1AKjB{yjvObX?KL1FW5LO zR&M0w2cRPx|YqFW%$s@ z!n(x4$MM1oN#nAe{tmZJgjb~1hlfhQXC`gMvAKV`-Ao8+zCYrwxO;1fMruaJv(C=F zyLbQMZ$E!p)wL8@8Tq$t=+-?6SAYUnzGq*y|#TSm|R_c<00nkO`7R$vt<_%?xc-hfmmQ*Szp2R>gNt*{<*REbiniWr(HajNde?yt*dX z1Uy`URJ#r-+ot_e*Xf1M{Fkdgf4-V!8K&oHQohc0;q9MxbsFVt`I8gso%!X<=Ff~> z@h`p4Gs0X7P0m)e$+G^aU2HMv`Bdx67k}OC%dB$tNU5%!5I=EM|1Q0eAMOh(&}k7F z%tM=&|L7LF#;C<_Y5Re(dTFaN){L|mV_e4Bm5}-&Qv1N9wI0)5Q<3b2PIgOHj+?lV zZTfcG)E1T}tHFNg&TgiEy#I-z3;Vq2Kj%yBq|MXAFEPC~#utX>`mf-$Y||6%Kc#u} zRiz-v{`Z#R&>N5PScx-s+-!E=H#|5Z7@q`w$Hj9FyMZ}A=!d^0oAPZv2}@!q8k@ZERUMyd*4(h>htl4>8u-Z z-v>zc$DCn#58f1Sn=Q;Vzn|A$l$yGZ^`WpJ;a<>{_x~!HDrzQJ3oBa0EgZE)=m#+PBvVAw3szws7}FeQFe(# z<3IRz#Bwt}ZtzHMO5jaDo&P{qJ?6;l!l#!;w(D$M?k$`b+)*!Tz2$Yiyz-jSRPBtM z-!(?PzZ08BoC$jR)N}BfXukt`hpXqFU_M+r_g$Gd=1S)CN5hZ&m_K91-sGXRH6yLI zm>vJLq3Nhw^Vn;@A6VV7zF}?5Bf*Aw{F9Ag+WE1ewNC!#;oY^*&6hrMvh-iFXW@rj zefwjJ!}d+dT<>G=m$qoh^+Rr%!_U@CwCcz?AMHo1vARpdT{v`^+p533g>^M~+OmET z-D@One`zi(X1@B?Y(nKPE+NzK-z6%hCY;azQimF6L;hVd4XzKBniy)oapVsW$wb8% z{6?h`rv3(1;pDk*{~yv8|9!6F2@^;Wzynh~$l}t&_;ex(5(kq7?tpNG6i}#KNB-(c zNM*tD{{{xl1`wa)h(pre5GP-uOhhoF2A&Vv$QIfD& zB2g@fVJV|kl8+k}!%0 zUyvHZy@&s=lu*4XQ=&+j+)IgEUA{$$TucgK@Nq{z49Yiz;Rm&17!-P+MR9S2q(=(W z_sY0QRPxF+-$ExBi5wjp!^!e7J?Q+T!npa2Z-`tz_H;o=duX6KRi=SdEE)||E^l?U zgX@J#1OSsi$hq_ti$zj~t2km&EQ~oNeHK)bTofl`z@z6d7zPxR3)NjHp?*_S2StfW z7zFCcwf7>KNEipjb>zL^Uwe^Hg0H<$zbUaoWeJzF;u0n$+{JM+vIB{bkjT5GAZ~F` z@DhaQ6d;V76ekt-{QmWYGD!j2+b!0sAoN}xT*RWtf6z5q-%=s_o~}IzQ34?oMua(d zhl_+z+TkDc-z!!1?*BozRIYcLoO{V8W%AESM|%x~I_>{h?!5-EXWq%(LQf|Aud0V4 zPF})DX)x)cd>E9*G33q&Y9vuGN|za2`JcFyd0{|)e6l$%|G}evC?%ukt2sOr`#gD;M1&lrd>GZ(hQ#i2wiS5QKISS` zz+Y$V&%5IFSjCOS%GO#Vb;k{N__nzIJo)Xt`to7PBp0b3M4CxkwhH1 zD1wkMg}$U~WIG~`e8wDR_zw(`I5BL#kZ_C;$IfA~oS<{pFd4yg9m7UY48ai&SvZ!9 z+aYWl1hD~2Bq1o9^j}-`5|Jb!qV%Am0hg@@r+$im3`nR0#S)?z3K)}#_adH^O zLvS3doH7hSxO|+}4&i|@q`}w-!Y0L~{4EB&kOdc1V31M{0Yy`Wk^e_wlxQ#@Uk%2l z(+uB0Su(YDT%I}(pjxdRpVW3`ydVPsY3XUOZ?)s{)bOIX0CZLPTi}eZP9G}Z(c}W+ zLlGKYfPv4X_s8b&)%aj@NynjzmyL7PzvV$iG$84nsJVRK5i%v#noXLSsg>=TMnY$9|uwI4+9fJ?+-KxrH>_G;L~&i zGz}&t4KEkR*tEHTkXL!>IB?*Xjsq7Uq`uK z2G7z}_Qt`2mar7E%=lhI807y+<(~ zPmN!Uj|gaE4wh4G{sOxgpC)^N;e7hHIMf%X%MWK$`#}}na4yt4q|uCX`J_u%X(s@g z(s2lQps4hAJOSM{VLTM!(P#!AfYI$ez^Iz&%6P$1sL=;72tTRfWn-Yav@r)IfU4%S zc3hAFjSpZ9BbU7@czGCbM~Cs)bQ=bgKv_$*cDR71S8P7`YB~-+FhZw~&&TQh2(oqX z={5qK8;?FlYylfq1FE!e5H^ooyeRWVnmTfQqzVJ&rP0iR*~_PY%jT;2Uk(V6P5+jI z2*~A|3Jwm+hIoZ44CAWFfCF=eK5hVmfAnv`u+d>S1~Z-34##kEt*Al^4`Z|Gyupr- zzP11>&Qs%qha+k@csQ5t^T0lXpjGjLOHuPZ0E73*YVEiPZC;Y@NI=sUfbr@67uHg0 zb_if<^1~o4CVe~r##6(=;R)z-731(xx;_JpL)S?RLj?4>ih*yW`)+^kS zU7s-w=aYc}<*|gxi_+~b#>KdFdkQcx?zC^g3)06DJP(^bf61|A)9K?OD1D7ddM&yw z0hqe%Vf9D%0nkp(W&>VCO{P4QjnMS~U}}26LpjQ85Sb(lO883jU=!mb7DJeV+ST|t zdAc%!$8m8E9)_a?PK1MV7hq9rusM7piU`NTxse2a!Z=>IAcAy{1cBfYV9{Yw!GTqK zB*G=wY?veyLYzF~qQuZGj1R=|W(kuCa$f;^4XG?lBBOR1FjN>{pl4;}=IyTcAJg#? A-T(jq literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Docs/UnityTestTools-en.pdf.meta b/src/Assets/UnityTestTools/Docs/UnityTestTools-en.pdf.meta new file mode 100644 index 0000000..75f9868 --- /dev/null +++ b/src/Assets/UnityTestTools/Docs/UnityTestTools-en.pdf.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: a53dc58cb0c6c474b9c48185829d59c7 +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/Docs/UnityTestTools-ja.pdf b/src/Assets/UnityTestTools/Docs/UnityTestTools-ja.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b3acfca96655f9dcdd92c969ceca2b94b0b4078e GIT binary patch literal 893461 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

sqPl58^=RZD{>nh$7wS8;x}`YvdO6_{Z=1s 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

%rEc-N*x$+g= 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

5wvk8 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� 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

op@=)d!;47fGFk7FV4s@#m-qf18>n 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 literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/Docs/UnityTestTools-ja.pdf.meta b/src/Assets/UnityTestTools/Docs/UnityTestTools-ja.pdf.meta new file mode 100644 index 0000000..1a13ff0 --- /dev/null +++ b/src/Assets/UnityTestTools/Docs/UnityTestTools-ja.pdf.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 13f9f9d67f694b54bb311e079f2e7d7a +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework.meta new file mode 100644 index 0000000..da22872 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 241054a0fe63fbb4bb51609fce9b3112 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner.meta new file mode 100644 index 0000000..c65a67d --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: da93545c3ab1aa043bcfb22281b1f66c +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor.meta new file mode 100644 index 0000000..bd38839 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: caee08596a5965747b8edfde19e2f873 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs new file mode 100644 index 0000000..048824b --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityTest.IntegrationTests; + +namespace UnityTest +{ + public static partial class Batch + { + private const string testScenesParam = "-testscenes="; + private static string targetPlatformParam = "-targetPlatform="; + private static string resultFileDirParam = "-resultsFileDirectory="; + + public static void RunIntegrationTests () + { + var targetPlatform = GetTargetPlatform (); + var sceneList = GetTestScenesList (); + + if (targetPlatform.HasValue) + BuildAndRun (targetPlatform.Value, sceneList); + else + RunInEditor (sceneList); + } + + private static void BuildAndRun (BuildTarget target, List sceneList) + { + var resultFilePath = GetParameterArgument (resultFileDirParam); + PlatformRunner.BuildAndRunInPlayer (target, sceneList.ToArray (), "IntegrationTests", resultFilePath); + EditorApplication.Exit (0); + } + + private static void RunInEditor (List sceneList) + { + if (sceneList == null || sceneList.Count == 0) + { + Debug.Log ("No scenes on the list"); + EditorApplication.Exit (0); + return; + } + EditorBuildSettings.scenes = sceneList.Select (s => new EditorBuildSettingsScene (s, true)).ToArray (); + EditorApplication.OpenScene (sceneList.First ()); + GuiHelper.SetConsoleErrorPause (false); + EditorApplication.isPlaying = true; + } + + private static BuildTarget? GetTargetPlatform () + { + string platformString = null; + BuildTarget buildTarget; + foreach (var arg in Environment.GetCommandLineArgs ()) + { + if (arg.ToLower ().StartsWith (targetPlatformParam.ToLower ())) + { + platformString = arg.Substring (resultFilePathParam.Length); + break; + } + } + try + { + buildTarget = (BuildTarget) Enum.Parse (typeof (BuildTarget), platformString); + } + catch + { + return null; + } + return buildTarget; + } + + private static List GetTestScenesList () + { + var sceneList = new List (); + foreach (var arg in Environment.GetCommandLineArgs ()) + { + if (arg.ToLower ().StartsWith (testScenesParam)) + { + var scenesFromParam = arg.Substring (testScenesParam.Length).Split (','); + foreach (var scene in scenesFromParam) + { + var sceneName = scene; + if (!sceneName.EndsWith (".unity")) + sceneName += ".unity"; + var foundScenes = Directory.GetFiles (Directory.GetCurrentDirectory (), sceneName, SearchOption.AllDirectories); + if (foundScenes.Length == 1) + sceneList.Add (foundScenes[0].Substring (Directory.GetCurrentDirectory ().Length + 1)); + else + Debug.Log (sceneName + " not found or multiple entries found"); + } + } + } + return sceneList.Where (s => !string.IsNullOrEmpty (s)).Distinct ().ToList (); + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs.meta new file mode 100644 index 0000000..248a6ce --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29d4fb050362c5b43aea52342045543a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs new file mode 100644 index 0000000..526dd7d --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs @@ -0,0 +1,612 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + [Serializable] + public class IntegrationTestsRunnerWindow : EditorWindow + { + #region GUI Contents + private readonly GUIContent guiOptionsHideLabel = new GUIContent ("Hide", Icons.gearImg); + private readonly GUIContent guiOptionsShowLabel = new GUIContent ("Options", Icons.gearImg); + private readonly GUIContent guiCreateNewTest = new GUIContent (Icons.plusImg, "Create new test"); + private readonly GUIContent guiRunSelectedTests = new GUIContent (Icons.runImg, "Run selected test(s)"); + private readonly GUIContent guiRunAllTests = new GUIContent (Icons.runAllImg, "Run all tests"); + private readonly GUIContent guiAdvancedFilterShow = new GUIContent ("Advanced"); + private readonly GUIContent guiAdvancedFilterHide = new GUIContent ("Hide"); + private readonly GUIContent guiAddGOUderTest = new GUIContent ("Add GOs under test", "Add new GameObject under selected test"); + private readonly GUIContent guiBlockUI = new GUIContent ("Block UI when running", "Block UI when running tests"); + private readonly GUIContent guiShowSucceededTests = new GUIContent ("Succeeded", Icons.successImg, "Show tests that succeeded"); + private readonly GUIContent guiShowFailedTests = new GUIContent ("Failed", Icons.failImg, "Show tests that failed"); + private readonly GUIContent guiShowIgnoredTests = new GUIContent ("Ignored", Icons.ignoreImg, "Show tests that are ignored"); + private readonly GUIContent guiShowNotRunTests = new GUIContent ("Not Run", Icons.unknownImg, "Show tests that didn't run"); + #endregion + + #region runner steerign vars + private static IntegrationTestsRunnerWindow Instance = null; + [SerializeField] private List testsToRun; + [SerializeField] private List dynamicTestsToRun; + [SerializeField] private bool readyToRun; + private bool isCompiling; + private bool isBuilding; + public static bool selectedInHierarchy; + private float horizontalSplitBarPosition = 200; + private Vector2 testInfoScroll, testListScroll; + private IntegrationTestRendererBase[] testLines; + private string currectSceneName = null; + + [SerializeField] private GameObject selectedLine; + [SerializeField] private List resultList = new List (); + [SerializeField] private List foldMarkers = new List (); + + private bool showOptions; + private string filterString; + private bool showAdvancedFilter; + + private bool showSucceededTest = true; + private bool showFailedTest = true; + private bool showNotRunnedTest = true; + private bool showIgnoredTest = true; + private bool addNewGameObjectUnderSelectedTest; + private bool blockUIWhenRunning = true; + #endregion + + + + static IntegrationTestsRunnerWindow () + { + InitBackgroundRunners (); + } + + private static void InitBackgroundRunners () + { + EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw; + EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemDraw; + EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate; + EditorApplication.hierarchyWindowChanged += OnHierarchyChangeUpdate; + EditorApplication.update -= BackgroundSceneChangeWatch; + EditorApplication.update += BackgroundSceneChangeWatch; + EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged; + EditorApplication.playmodeStateChanged += OnPlaymodeStateChanged; + } + + private static void OnPlaymodeStateChanged () + { + if (EditorApplication.isPlaying == EditorApplication.isPlayingOrWillChangePlaymode) + Instance.RebuildTestList (); + } + + public void OnDestroy () + { + EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw; + EditorApplication.update -= BackgroundSceneChangeWatch; + EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate; + EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged; + + TestComponent.DestroyAllDynamicTests (); + } + + private static void BackgroundSceneChangeWatch () + { + if (Instance.currectSceneName != null && Instance.currectSceneName == EditorApplication.currentScene) return; + if (EditorApplication.isPlayingOrWillChangePlaymode) return; + TestComponent.DestroyAllDynamicTests (); + Instance.currectSceneName = EditorApplication.currentScene; + Instance.RebuildTestList (); + } + + public void OnEnable () + { + title = "Integration Tests Runner"; + Instance = this; + + if (EditorPrefs.HasKey ("ITR-addNewGameObjectUnderSelectedTest")) + { + addNewGameObjectUnderSelectedTest = EditorPrefs.GetBool ("ITR-addNewGameObjectUnderSelectedTest"); + blockUIWhenRunning = EditorPrefs.GetBool ("ITR-blockUIWhenRunning"); + showSucceededTest = EditorPrefs.GetBool ("ITR-showSucceededTest"); + showFailedTest = EditorPrefs.GetBool ("ITR-showFailedTest"); + showIgnoredTest = EditorPrefs.GetBool ("ITR-showIgnoredTest"); + showNotRunnedTest = EditorPrefs.GetBool ("ITR-showNotRunnedTest"); + } + + InitBackgroundRunners (); + if (!EditorApplication.isPlayingOrWillChangePlaymode && !readyToRun) RebuildTestList (); + } + + public void OnSelectionChange() + { + if ( EditorApplication.isPlayingOrWillChangePlaymode + || Selection.objects == null + || Selection.objects.Length == 0) return; + + if (Selection.gameObjects.Length == 1) + { + var go = Selection.gameObjects.Single (); + var temp = go.transform; + while (temp != null) + { + var tc = temp.GetComponent (); + if (tc != null) break; + temp = temp.parent; + } + + if (temp != null) + { + SelectInHierarchy (temp.gameObject); + Selection.activeGameObject = temp.gameObject; + selectedLine = temp.gameObject; + } + } + } + + public static void OnHierarchyChangeUpdate() + { + if (Instance.testLines == null || EditorApplication.isPlayingOrWillChangePlaymode) return; + + //create a test runner if it doesn't exist + TestRunner.GetTestRunner (); + + if (Instance.addNewGameObjectUnderSelectedTest + && Instance.selectedLine != null + && Selection.activeGameObject != null) + { + var go = Selection.activeGameObject; + if (go.transform.parent == null + && go.GetComponent () == null + && go.GetComponent () == null) + { + go.transform.parent = Instance.selectedLine.transform; + } + } + + //make tests are not places under a go that is not a test itself + foreach (var test in TestComponent.FindAllTestsOnScene ()) + { + if (test.gameObject.transform.parent != null && test.gameObject.transform.parent.gameObject.GetComponent () == null) + { + test.gameObject.transform.parent = null; + Debug.LogWarning ("Tests need to be on top of hierarchy or directly under another test."); + } + } + if (selectedInHierarchy) selectedInHierarchy = false; + else Instance.RebuildTestList (); + } + + public static void OnHierarchyWindowItemDraw ( int id, Rect rect ) + { + var o = EditorUtility.InstanceIDToObject (id); + if (o is GameObject) + { + var go = o as GameObject; + var tc = go.GetComponent (); + if (tc != null) + { + if (!EditorApplication.isPlayingOrWillChangePlaymode + && rect.Contains (Event.current.mousePosition) + && Event.current.type == EventType.MouseDown + && Event.current.button == 1) + { + IntegrationTestRendererBase.DrawContextMenu (tc); + } + + EditorGUIUtility.SetIconSize (new Vector2 (15, 15)); + var result = Instance.resultList.Find (r => r.GameObject == go); + if(result != null) + { + var icon = result.Executed ? GuiHelper.GetIconForResult (result.resultType) : Icons.unknownImg; + EditorGUI.LabelField (new Rect (rect.xMax - 18, rect.yMin - 2, rect.width, rect.height), new GUIContent(icon)); + } + EditorGUIUtility.SetIconSize (Vector2.zero); + } + + if (Event.current.type == EventType.MouseDown + && Event.current.button == 0 + && rect.Contains (Event.current.mousePosition)) + { + var temp = go.transform; + while (temp != null) + { + var c = temp.GetComponent (); + if (c != null) break; + temp = temp.parent; + } + if(temp!=null) SelectInHierarchy (temp.gameObject); + } + } + } + + private static void SelectInHierarchy ( GameObject gameObject ) + { + if (gameObject == Instance.selectedLine) return; + if (!gameObject.activeSelf) + { + selectedInHierarchy = true; + gameObject.SetActive (true); + } + + var tests = TestComponent.FindAllTestsOnScene (); + var skipList = gameObject.GetComponentsInChildren (typeof (TestComponent), true); + tests.RemoveAll (skipList.Contains); + foreach (var test in tests) + { + var enable = test.GetComponentsInChildren (typeof (TestComponent), true).Any (c => c.gameObject == gameObject); + if (test.gameObject.activeSelf != enable) test.gameObject.SetActive (enable); + } + } + + private void RunTests ( IList tests ) + { + if (!tests.Any () || EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode) + return; + FocusWindowIfItsOpen (GetType ()); + + testsToRun = tests.Where(t=>t is TestComponent).Cast ().ToList (); + var temp = testsToRun.Where (t => t.dynamic).ToArray(); + dynamicTestsToRun = temp.Select (c => c.dynamicTypeName).ToList (); + testsToRun.RemoveAll (temp.Contains); + + readyToRun = true; + TestComponent.DisableAllTests (); + EditorApplication.isPlaying = true; + + if (blockUIWhenRunning) + EditorUtility.DisplayProgressBar ("Integration Test Runner", "Initializing", 0); + } + + public void Update() + { + if (readyToRun && EditorApplication.isPlaying) + { + readyToRun = false; + var testRunner = TestRunner.GetTestRunner(); + testRunner.TestRunnerCallback.Add (new RunnerCallback (this)); + testRunner.InitRunner (testsToRun.ToList (), dynamicTestsToRun); + } + } + + private void RebuildTestList () + { + testLines = null; + if (!TestComponent.AnyTestsOnScene ()) return; + + if (!EditorApplication.isPlayingOrWillChangePlaymode ) + { + var dynamicTestsOnScene = TestComponent.FindAllDynamicTestsOnScene (); + var dynamicTestTypes = TestComponent.GetTypesWithHelpAttribute (EditorApplication.currentScene); + + foreach (var dynamicTestType in dynamicTestTypes) + { + var existingTests = dynamicTestsOnScene.Where (component => component.dynamicTypeName == dynamicTestType.AssemblyQualifiedName); + if (existingTests.Any ()) + { + dynamicTestsOnScene.Remove (existingTests.Single ()); + continue; + } + TestComponent.CreateDynamicTest (dynamicTestType); + } + + foreach (var testComponent in dynamicTestsOnScene) + DestroyImmediate (testComponent.gameObject); + } + + var topTestList = TestComponent.FindAllTopTestsOnScene (); + + var newResultList = new List (); + testLines = ParseTestList (topTestList, newResultList); + + var oldDynamicResults = resultList.Where (result => result.dynamicTest); + foreach (var oldResult in resultList) + { + var result = newResultList.Find (r => r.Id == oldResult.Id); + if (result == null) continue; + result.Update (oldResult); + } + newResultList.AddRange (oldDynamicResults.Where ( r => !newResultList.Contains(r) )); + resultList = newResultList; + + IntegrationTestRendererBase.RunTest = RunTests; + IntegrationTestGroupLine.FoldMarkers = foldMarkers; + IntegrationTestLine.Results = resultList; + + foldMarkers.RemoveAll (o => o == null); + + selectedInHierarchy = true; + Repaint (); + } + + + + private IntegrationTestRendererBase[] ParseTestList ( List testList, List results ) + { + var tempList = new List (); + foreach (var testObject in testList) + { + if (!testObject.IsTestGroup ()) + { + var result = new TestResult (testObject); + if(results!=null) + results.Add (result); + tempList.Add (new IntegrationTestLine (testObject.gameObject, result)); + continue; + } + var group = new IntegrationTestGroupLine (testObject.gameObject); + var children = testObject.gameObject.GetComponentsInChildren (typeof (TestComponent), true).Cast ().ToList (); + children = children.Where(c => c.gameObject.transform.parent == testObject.gameObject.transform).ToList(); + group.AddChildren (ParseTestList (children, results)); + tempList.Add (group); + } + tempList.Sort (); + return tempList.ToArray (); + } + + public void OnGUI() + { + +#if !UNITY_4_0 && !UNITY_4_0_1 && !UNITY_4_1 && !UNITY_4_2 + if (BuildPipeline.isBuildingPlayer) + { + isBuilding = true; + } + else if (isBuilding) + { + isBuilding = false; + Repaint (); + } +#endif + PrintHeadPanel(); + + EditorGUILayout.BeginVertical (Styles.testList); + testListScroll = EditorGUILayout.BeginScrollView (testListScroll); + bool repaint = PrintTestList (testLines); + GUILayout.FlexibleSpace (); + EditorGUILayout.EndScrollView (); + EditorGUILayout.EndVertical (); + + RenderDetails (); + + if (repaint) Repaint (); + } + + public void PrintHeadPanel ( ) + { + GUILayout.Space (10); + EditorGUILayout.BeginHorizontal (); + var layoutOptions = new[] { GUILayout.Height(24), GUILayout.Width(32) }; + if (GUILayout.Button (guiRunAllTests, Styles.buttonLeft, layoutOptions) + && !EditorApplication.isPlayingOrWillChangePlaymode) + { + RunTests (TestComponent.FindAllTestsOnScene ().Cast ().ToList ()); + } + if (GUILayout.Button (guiRunSelectedTests, Styles.buttonMid, layoutOptions) + && !EditorApplication.isPlayingOrWillChangePlaymode) + { + RunTests (Selection.gameObjects.Select (t => t.GetComponent (typeof(TestComponent))).Cast ().ToList ()); + } + if (GUILayout.Button (guiCreateNewTest, Styles.buttonRight, layoutOptions) + && !EditorApplication.isPlayingOrWillChangePlaymode) + { + var test = TestComponent.CreateTest (); + if (Selection.gameObjects.Length == 1 + && Selection.activeGameObject != null + && Selection.activeGameObject.GetComponent ()) + { + test.transform.parent = Selection.activeGameObject.transform.parent; + } + Selection.activeGameObject = test; + RebuildTestList (); + } + GUILayout.FlexibleSpace (); + if (GUILayout.Button (showOptions ? guiOptionsHideLabel : guiOptionsShowLabel, GUILayout.Height (24), GUILayout.Width (80))) + showOptions = !showOptions; + EditorGUILayout.EndHorizontal (); + + if (showOptions) + PrintOptions (); + + EditorGUILayout.BeginHorizontal (); + EditorGUILayout.LabelField ("Filter:", GUILayout.Width (35)); + filterString = EditorGUILayout.TextField (filterString); + if (GUILayout.Button (showAdvancedFilter ? guiAdvancedFilterHide : guiAdvancedFilterShow, GUILayout.Width (80), GUILayout.Height (16))) + showAdvancedFilter = !showAdvancedFilter; + EditorGUILayout.EndHorizontal (); + + if (showAdvancedFilter) + PrintAdvancedFilter (); + } + + public void PrintOptions () + { + var style = EditorStyles.toggle; + EditorGUILayout.BeginVertical (); + EditorGUI.BeginChangeCheck (); + addNewGameObjectUnderSelectedTest = EditorGUILayout.Toggle (guiAddGOUderTest, addNewGameObjectUnderSelectedTest, style); + blockUIWhenRunning = EditorGUILayout.Toggle (guiBlockUI, blockUIWhenRunning, style); + if (EditorGUI.EndChangeCheck ()) + { + EditorPrefs.SetBool ("ITR-addNewGameObjectUnderSelectedTest", addNewGameObjectUnderSelectedTest); + EditorPrefs.SetBool ("ITR-blockUIWhenRunning", blockUIWhenRunning); + } + EditorGUILayout.EndVertical (); + } + + private void PrintAdvancedFilter () + { + EditorGUI.BeginChangeCheck (); + EditorGUILayout.BeginHorizontal (); + showSucceededTest = GUILayout.Toggle (showSucceededTest, guiShowSucceededTests, GUI.skin.FindStyle (GUI.skin.button.name + "left"), GUILayout.ExpandWidth (true)); + showFailedTest = GUILayout.Toggle (showFailedTest, guiShowFailedTests, GUI.skin.FindStyle (GUI.skin.button.name + "mid")); + showIgnoredTest = GUILayout.Toggle (showIgnoredTest, guiShowIgnoredTests, GUI.skin.FindStyle (GUI.skin.button.name + "mid")); + showNotRunnedTest = GUILayout.Toggle (showNotRunnedTest, guiShowNotRunTests, GUI.skin.FindStyle (GUI.skin.button.name + "right"), GUILayout.ExpandWidth (true)); + EditorGUILayout.EndHorizontal (); + if (EditorGUI.EndChangeCheck ()) + { + EditorPrefs.SetBool ("ITR-showSucceededTest", showSucceededTest); + EditorPrefs.SetBool ("ITR-showFailedTest", showFailedTest); + EditorPrefs.SetBool ("ITR-showIgnoredTest", showIgnoredTest); + EditorPrefs.SetBool ("ITR-showNotRunnedTest", showNotRunnedTest); + } + } + + private bool PrintTestList ( IntegrationTestRendererBase[] renderedLines ) + { + if (renderedLines == null) return false; + + var filter = new RenderingOptions (); + filter.showSucceeded = showSucceededTest; + filter.showFailed = showFailedTest; + filter.showNotRunned = showNotRunnedTest; + filter.showIgnored = showIgnoredTest; + filter.nameFilter = filterString; + + bool repaint = false; + foreach (var renderedLine in renderedLines) + { + repaint |= renderedLine.Render (filter); + } + return repaint; + } + + private void RenderDetails () + { + var ctrlId = EditorGUIUtility.GetControlID (FocusType.Passive); + + Rect rect = GUILayoutUtility.GetLastRect (); + rect.y = rect.height + rect.y - 1; + rect.height = 3; + + EditorGUIUtility.AddCursorRect (rect, MouseCursor.ResizeVertical ); + var e = Event.current; + switch (e.type) + { + case EventType.MouseDown: + if (EditorGUIUtility.hotControl == 0 && rect.Contains (e.mousePosition)) + EditorGUIUtility.hotControl = ctrlId; + break; + case EventType.MouseDrag: + if (EditorGUIUtility.hotControl == ctrlId) + { + horizontalSplitBarPosition -= e.delta.y; + if (horizontalSplitBarPosition < 20) horizontalSplitBarPosition = 20; + Repaint (); + } + break; + case EventType.MouseUp: + if (EditorGUIUtility.hotControl == ctrlId) + EditorGUIUtility.hotControl = 0; + break; + } + + testInfoScroll = EditorGUILayout.BeginScrollView (testInfoScroll, GUILayout.MinHeight (horizontalSplitBarPosition)); + + var message = ""; + + if (selectedLine != null) + message = GetResultText (selectedLine); + EditorGUILayout.TextArea (message, Styles.info); + EditorGUILayout.EndScrollView (); + } + + private string GetResultText (GameObject go) + { + var result = resultList.Find (r => r.GameObject == go); + if (result == null) return ""; + var messages = result.Name; + messages += "\n\n" + result.messages; + if (!string.IsNullOrEmpty (result.stacktrace)) + messages += "\n" + result.stacktrace; + return messages.Trim (); + } + + public void OnInspectorUpdate () + { + if(focusedWindow != this) Repaint (); + } + + private void SetCurrentTest ( TestComponent tc ) + { + foreach (var line in testLines) + line.SetCurrentTest (tc); + } + + class RunnerCallback : IntegrationTestRunner.ITestRunnerCallback + { + private IntegrationTestsRunnerWindow window; + private int testNumber=0; + private int currentTestNumber = 0; + + private bool consoleErrorOnPauseValue; + private bool runInBackground; + + public RunnerCallback(IntegrationTestsRunnerWindow window) + { + this.window = window; + + consoleErrorOnPauseValue = GuiHelper.GetConsoleErrorPause (); + GuiHelper.SetConsoleErrorPause (false); + runInBackground = PlayerSettings.runInBackground; + PlayerSettings.runInBackground = true; + } + + public void RunStarted (string platform, List testsToRun) + { + testNumber = testsToRun.Count; + foreach (var test in testsToRun) + { + var result = window.resultList.Find (r => r.TestComponent == test); + if (result != null) result.Reset (); + } + } + + public void RunFinished (List testResults) + { + window.SetCurrentTest(null); + EditorApplication.isPlaying = false; + EditorUtility.ClearProgressBar(); + GuiHelper.SetConsoleErrorPause (consoleErrorOnPauseValue); + PlayerSettings.runInBackground = runInBackground; + } + + public void TestStarted (TestResult test) + { + window.SetCurrentTest (test.TestComponent); + if (window.blockUIWhenRunning + && EditorUtility.DisplayCancelableProgressBar("Integration Test Runner", + "Running " + test.Name, + (float) currentTestNumber / testNumber)) + { + TestRunInterrupted (null); + } + } + + + public void TestFinished (TestResult test) + { + currentTestNumber++; + + var result = window.resultList.Find (r => r.Id == test.Id); + if(result!=null) + result.Update (test); + else + window.resultList.Add (test); + } + + public void TestRunInterrupted(List testsNotRun) + { + Debug.Log("Test run interrupted"); + RunFinished(new List()); + } + } + + [MenuItem ("Unity Test Tools/Integration Test Runner %#&t")] + public static IntegrationTestsRunnerWindow ShowWindow() + { + var w = GetWindow(typeof(IntegrationTestsRunnerWindow)); + w.Show(); + return w as IntegrationTestsRunnerWindow; + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs.meta new file mode 100644 index 0000000..86b5775 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2c898357efb599944818326bb43ba879 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner.meta new file mode 100644 index 0000000..f8df9bd --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: c44e9167d633ee94bb6e078238178308 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs new file mode 100644 index 0000000..fa75587 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs @@ -0,0 +1,147 @@ +using System; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest.IntegrationTests +{ + public class PlatformRunner + { + static string resourcesPath = Path.Combine ("Assets", "Resources"); + + public static BuildTarget defaultBuildTarget + { + get + { + var target = EditorPrefs.GetString ("ITR-platformRunnerBuildTarget"); + BuildTarget buildTarget; + try + { + buildTarget = (BuildTarget) Enum.Parse (typeof (BuildTarget), target); + } + catch + { + return GetDefaultBuildTarget (); + } + return buildTarget; + } + set { EditorPrefs.SetString ("ITR-platformRunnerBuildTarget", value.ToString ()); } + } + + [MenuItem ("Unity Test Tools/Platform Runner/Run current scene %#&r")] + public static void BuildAndRunCurrentScene () + { + Debug.Log ("Building and running current test for " + defaultBuildTarget); + BuildAndRunInPlayer (defaultBuildTarget, new string[0], null, null); + } + + [MenuItem ("Unity Test Tools/Platform Runner/Run on platform %#r")] + public static void RunInPlayer () + { + var w = EditorWindow.GetWindow (typeof (PlatformRunnerSettingsWindow)); + w.Show (); + } + + public static void BuildAndRunInPlayer (BuildTarget buildTarget, string[] scenes, string name, string resultFilePath) + { + var folderExisted = AddConfigurationFile (resultFilePath); + + var tempDisplayResolutionDialog = PlayerSettings.displayResolutionDialog; + PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Disabled; + var tempRunInBackground = PlayerSettings.runInBackground; + PlayerSettings.runInBackground = true; + var tempFullScreen = PlayerSettings.defaultIsFullScreen; + PlayerSettings.defaultIsFullScreen = false; + PlayerSettings.resizableWindow = true; + + BuildPipeline.BuildPlayer (scenes, + GetTempPath (buildTarget, name ?? Application.loadedLevelName), + buildTarget, + BuildOptions.AutoRunPlayer | BuildOptions.Development); + + + PlayerSettings.defaultIsFullScreen = tempFullScreen; + PlayerSettings.runInBackground = tempRunInBackground; + PlayerSettings.displayResolutionDialog = tempDisplayResolutionDialog; + + RemoveConfigurationFile (folderExisted); + } + + private static void RemoveConfigurationFile (bool directoryExisted) + { + var batchRunFileMarkerPath = Path.Combine (resourcesPath, TestRunner.batchRunFileMarker); + AssetDatabase.DeleteAsset (batchRunFileMarkerPath); + var configFilePath = Path.Combine (resourcesPath, TestRunner.integrationTestsConfigFileName); + AssetDatabase.DeleteAsset (configFilePath); + if (!directoryExisted) + AssetDatabase.DeleteAsset (resourcesPath); + } + + private static bool AddConfigurationFile (string resultFilePath) + { + var resDirExisted = Directory.Exists (resourcesPath); + if (!resDirExisted) + AssetDatabase.CreateFolder ("Assets", "Resources"); + if (UnityEditorInternal.InternalEditorUtility.inBatchMode) + { + var batchRunFileMarkerPath = Path.Combine (resourcesPath, TestRunner.batchRunFileMarker); + File.WriteAllText (batchRunFileMarkerPath, ""); + } + if (!string.IsNullOrEmpty (resultFilePath)) + { + if (!Directory.Exists (resultFilePath)) + Directory.CreateDirectory (resultFilePath); + var configFilePath = Path.Combine (resourcesPath, TestRunner.integrationTestsConfigFileName); + File.WriteAllText (configFilePath, resultFilePath); + } + AssetDatabase.Refresh (); + return resDirExisted; + } + + private static string GetTempPath (BuildTarget buildTarget, string name) + { + if (string.IsNullOrEmpty (name)) + name = Path.GetTempFileName (); + + var path = Path.Combine ("Temp", name); + switch (buildTarget) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: + return path + ".exe"; + case BuildTarget.StandaloneOSXIntel: + return path + ".app"; + case BuildTarget.Android: + return path + ".apk"; + default: + return path; + } + } + + private static BuildTarget GetDefaultBuildTarget () + { + switch (EditorUserBuildSettings.selectedBuildTargetGroup) + { + case BuildTargetGroup.Android: + return BuildTarget.Android; + case BuildTargetGroup.WebPlayer: + return BuildTarget.WebPlayer; + case BuildTargetGroup.Standalone: + default: + { + switch (Application.platform) + { + case RuntimePlatform.WindowsPlayer: + return BuildTarget.StandaloneWindows; + case RuntimePlatform.OSXPlayer: + return BuildTarget.StandaloneOSXIntel; + case RuntimePlatform.LinuxPlayer: + return BuildTarget.StandaloneLinux; + } + return BuildTarget.WebPlayer; + } + } + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs.meta new file mode 100644 index 0000000..5ecced0 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3581fa3f207a8a4c9988b9f59a510d3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs new file mode 100644 index 0000000..4749692 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest.IntegrationTests +{ + public class PlatformRunnerSettingsWindow : EditorWindow + { + private BuildTarget buildTarget; + private List sceneList; + private Vector2 scrollPosition; + private string resultsPath; + private List selectedScenes = new List (); + + GUIContent label = new GUIContent ("Results target directory", "Directory where the results will be saved. If no value is specified, the results will be generated in project's data folder."); + + public PlatformRunnerSettingsWindow () + { + title = "Run on platform"; + buildTarget = PlatformRunner.defaultBuildTarget; + position.Set (position.xMin, position.yMin, 200, position.height); + sceneList = Directory.GetFiles (Directory.GetCurrentDirectory (), "*.unity", SearchOption.AllDirectories).ToList (); + sceneList.Sort(); + var currentScene = (Directory.GetCurrentDirectory () + EditorApplication.currentScene).Replace ("\\", "").Replace ("/", ""); + var currentScenePath = sceneList.Where (s => s.Replace ("\\", "").Replace ("/", "") == currentScene); + selectedScenes.AddRange (currentScenePath); + + resultsPath = EditorPrefs.GetString ("PR-resultsPath"); + } + + private void OnGUI () + { + EditorGUILayout.BeginVertical (); + + scrollPosition = EditorGUILayout.BeginScrollView (scrollPosition); + EditorGUILayout.LabelField ("List of scenes to build:", EditorStyles.boldLabel); + EditorGUI.indentLevel++; + foreach (var scenePath in sceneList) + { + var path = Path.GetFileNameWithoutExtension (scenePath); + var guiContent = new GUIContent (path, scenePath); + var rect = GUILayoutUtility.GetRect (guiContent, EditorStyles.label); + if (rect.Contains (Event.current.mousePosition)) + { + if (Event.current.type == EventType.mouseDown && Event.current.button == 0) + { + if (!Event.current.control) + selectedScenes.Clear (); + if (!selectedScenes.Contains (scenePath)) + selectedScenes.Add (scenePath); + else + selectedScenes.Remove (scenePath); + Event.current.Use (); + } + } + var style = new GUIStyle(EditorStyles.label); + if (selectedScenes.Contains (scenePath)) + style.normal.textColor = new Color (0.3f, 0.5f, 0.85f); + EditorGUI.LabelField (rect, guiContent, style); + } + EditorGUI.indentLevel--; + EditorGUILayout.EndScrollView (); + + GUILayout.Box ("", new[] {GUILayout.ExpandWidth (true), GUILayout.Height (1)}); + + buildTarget = (BuildTarget) EditorGUILayout.EnumPopup ("Build tests for", buildTarget); + + if (PlatformRunner.defaultBuildTarget != buildTarget) + { + if (GUILayout.Button ("Make default target platform")) + { + PlatformRunner.defaultBuildTarget = buildTarget; + } + } + DrawSetting (); + var build = GUILayout.Button ("Build and run tests"); + EditorGUILayout.EndVertical (); + + if (!build) return; + PlatformRunner.BuildAndRunInPlayer (buildTarget, selectedScenes.ToArray (), "IntegrationTests", resultsPath); + Close (); + } + + private void DrawSetting () + { + EditorGUI.BeginChangeCheck (); + resultsPath = EditorGUILayout.TextField (label, resultsPath); + if (EditorGUI.EndChangeCheck ()) + { + EditorPrefs.SetString ("PR-resultsPath", resultsPath); + } + if (!string.IsNullOrEmpty (resultsPath)) + { + Uri uri; + if (!Uri.TryCreate (resultsPath, UriKind.Absolute, out uri) || !uri.IsFile || uri.IsWellFormedOriginalString ()) + { + EditorGUILayout.HelpBox ("Invalid URI path", MessageType.Warning); + } + } + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs.meta new file mode 100644 index 0000000..8fed609 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3819282b0887bc742911b89745080acb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer.meta new file mode 100644 index 0000000..374f5b4 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 5944b82e46f1682439d20b4c3a4f029c +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs new file mode 100644 index 0000000..c628c78 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + class IntegrationTestGroupLine : IntegrationTestRendererBase + { + public static List FoldMarkers; + private IntegrationTestRendererBase[] children; + + public IntegrationTestGroupLine (GameObject gameObject) : base (gameObject) + { + } + + protected internal override void DrawLine ( Rect rect, GUIContent label, bool isSelected, RenderingOptions options ) + { + EditorGUILayout.BeginHorizontal (); + + EditorGUI.BeginChangeCheck (); + var isClassFolded = !EditorGUI.Foldout (rect, !Folded, label , isSelected ? Styles.selectedFoldout : Styles.foldout); + if (EditorGUI.EndChangeCheck ()) Folded = isClassFolded; + + EditorGUILayout.EndHorizontal (); + } + + private bool Folded + { + get { return FoldMarkers.Contains (gameObject); } + + set + { + if (value) FoldMarkers.Add (gameObject); + else FoldMarkers.RemoveAll (s => s == gameObject); + } + } + + protected internal override void Render ( int indend, RenderingOptions options ) + { + base.Render (indend, options); + if (!Folded) + foreach (var child in children) + child.Render (indend + 1, options); + } + + protected internal override TestResult.ResultType GetResult () + { + bool ignored = false; + bool success = false; + foreach (var child in children) + { + var result = child.GetResult (); + + if (result == TestResult.ResultType.Failed || result == TestResult.ResultType.FailedException || result == TestResult.ResultType.Timeout) + return TestResult.ResultType.Failed; + if (result == TestResult.ResultType.Success) + success = true; + else if (result == TestResult.ResultType.Ignored) + ignored = true; + else + ignored = false; + } + if(success) return TestResult.ResultType.Success; + if(ignored) return TestResult.ResultType.Ignored; + return TestResult.ResultType.NotRun; + } + + protected internal override bool IsVisible (RenderingOptions options) + { + return children.Any (c => c.IsVisible (options)); + } + + public override bool SetCurrentTest (TestComponent tc) + { + IsRunning = false; + foreach (var child in children) + IsRunning |= child.SetCurrentTest (tc); + return IsRunning; + } + + public void AddChildren ( IntegrationTestRendererBase[] parseTestList ) + { + children = parseTestList; + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs.meta new file mode 100644 index 0000000..0051064 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f6dc74195aa98ef4da8901199cda4a63 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs new file mode 100644 index 0000000..183f3c3 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + class IntegrationTestLine : IntegrationTestRendererBase + { + public static List Results; + protected TestResult result; + + public IntegrationTestLine (GameObject gameObject, TestResult testResult) : base (gameObject) + { + this.result = testResult; + } + + protected internal override void DrawLine ( Rect rect, GUIContent label, bool isSelected, RenderingOptions options ) + { + EditorGUILayout.BeginHorizontal (); + rect.x += 10; + + EditorGUI.LabelField (rect, label, isSelected ? Styles.selectedLabel : Styles.label); + + if (result.IsTimeout) + { + var timeoutRect = new Rect(rect); + timeoutRect.x = timeoutRect.x + timeoutRect.width; + timeoutRect.width = 24; + EditorGUI.LabelField (timeoutRect, guiTimeoutIcon); + GUILayout.FlexibleSpace (); + } + EditorGUILayout.EndHorizontal (); + } + + protected internal override TestResult.ResultType GetResult () + { + if(!result.Executed && test.ignored) return TestResult.ResultType.Ignored; + return result.resultType; + } + + protected internal override bool IsVisible (RenderingOptions options) + { + if (!string.IsNullOrEmpty (options.nameFilter) && !gameObject.name.ToLower ().Contains (options.nameFilter.ToLower ())) return false; + if (!options.showSucceeded && result.IsSuccess) return false; + if (!options.showFailed && result.IsFailure) return false; + if (!options.showNotRunned && !result.Executed) return false; + if (!options.showIgnored && test.ignored) return false; + return true; + } + + public override bool SetCurrentTest (TestComponent tc) + { + IsRunning = test == tc; + return IsRunning; + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs.meta new file mode 100644 index 0000000..25c9f11 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 212be02e4a7da194688b08ab0c946fbd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs new file mode 100644 index 0000000..802d76c --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using Event = UnityEngine.Event; +using Object = UnityEngine.Object; + +namespace UnityTest +{ + public abstract class IntegrationTestRendererBase : IComparable + { + public static Action> RunTest; + + protected static bool refresh; + + private static GUIContent guiRunSelected = new GUIContent ("Run Selected"); + private static GUIContent guiRun = new GUIContent ("Run"); + private static GUIContent guiDelete = new GUIContent ("Delete"); + private static GUIContent guiDeleteSelected = new GUIContent ("Delete selected"); + + protected static GUIContent guiTimeoutIcon = new GUIContent (Icons.stopwatchImg, "Timeout"); + + protected GameObject gameObject; + public TestComponent test; + private string name; + + protected IntegrationTestRendererBase ( GameObject gameObject ) + { + this.test = gameObject.GetComponent (typeof (TestComponent)) as TestComponent; + if (test == null) throw new ArgumentException ("Provided GameObject is not a test object"); + this.gameObject = gameObject; + this.name = test.Name; + } + + public int CompareTo (IntegrationTestRendererBase other) + { + return test.CompareTo (other.test); + } + + public bool Render (RenderingOptions options) + { + refresh = false; + EditorGUIUtility.SetIconSize (new Vector2 (15, 15)); + Render (0, options); + EditorGUIUtility.SetIconSize (Vector2.zero); + return refresh; + } + + protected internal virtual void Render (int indend, RenderingOptions options) + { + if (!IsVisible (options)) return; + EditorGUILayout.BeginHorizontal (); + GUILayout.Space (indend * 10); + + var tempColor = GUI.color; + if (IsRunning) + { + var frame = Mathf.Abs (Mathf.Cos (Time.realtimeSinceStartup * 4)) * 0.6f + 0.4f; + GUI.color = new Color (1, 1, 1, frame); + } + + var isSelected = Selection.gameObjects.Contains (gameObject); + + var value = GetResult (); + var icon = GuiHelper.GetIconForResult (value); + + var label = new GUIContent (name, icon); + var labelRect = GUILayoutUtility.GetRect (label, EditorStyles.label, GUILayout.ExpandWidth (true), GUILayout.Height (18)); + + OnLeftMouseButtonClick (labelRect); + OnContextClick (labelRect); + DrawLine (labelRect, label, isSelected, options); + + if (IsRunning) GUI.color = tempColor; + EditorGUILayout.EndHorizontal (); + } + + protected void OnSelect () + { + if (!Event.current.control) Selection.objects = new UnityEngine.Object[0]; + + if (Event.current.control && Selection.gameObjects.Contains (test.gameObject)) + Selection.objects = Selection.gameObjects.Where (o => o != test.gameObject).ToArray (); + else + Selection.objects = Selection.gameObjects.Concat (new[] { test.gameObject }).ToArray (); + } + + protected void OnLeftMouseButtonClick ( Rect rect ) + { + if (rect.Contains (Event.current.mousePosition) && Event.current.type == EventType.mouseDown && Event.current.button == 0) + { + rect.width = 20; + if (rect.Contains (Event.current.mousePosition)) return; + Event.current.Use (); + OnSelect (); + } + } + + protected void OnContextClick ( Rect rect ) + { + if (rect.Contains (Event.current.mousePosition) && Event.current.type == EventType.ContextClick) + { + DrawContextMenu (test); + } + } + + public static void DrawContextMenu ( TestComponent testComponent ) + { + if (EditorApplication.isPlayingOrWillChangePlaymode) return; + + var selectedTests = Selection.gameObjects.Where (go => go.GetComponent (typeof (TestComponent))); + var manySelected = selectedTests.Count () > 1; + + var m = new GenericMenu (); + if (manySelected) + { + //var testsToRun + m.AddItem (guiRunSelected, false, data => RunTest (selectedTests.Select(o => o.GetComponent (typeof (TestComponent))).Cast ().ToList ()), null); + } + m.AddItem (guiRun, false, data => RunTest (new[] { testComponent }), null); + m.AddSeparator (""); + m.AddItem (manySelected ? guiDeleteSelected : guiDelete, false, data => RemoveTests (selectedTests.ToArray ()), null); + m.ShowAsContext (); + } + + private static void RemoveTests (GameObject[] testsToDelete) + { + foreach (var t in testsToDelete) + { +#if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 + Undo.RegisterSceneUndo ("Destroy Tests"); + GameObject.DestroyImmediate (t); +#else + Undo.DestroyObjectImmediate (t); +#endif + } + } + + protected internal bool IsRunning; + protected internal abstract void DrawLine ( Rect rect, GUIContent label, bool isSelected, RenderingOptions options ); + protected internal abstract TestResult.ResultType GetResult (); + protected internal abstract bool IsVisible (RenderingOptions options); + public abstract bool SetCurrentTest (TestComponent tc); + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs.meta new file mode 100644 index 0000000..1fb186e --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 604645a3b57179a4d873906b625ef8ec +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs new file mode 100644 index 0000000..2cc970a --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + [CanEditMultipleObjects] + [CustomEditor (typeof (TestComponent))] + public class TestComponentEditor : Editor + { + private SerializedProperty expectException; + private SerializedProperty expectedExceptionList; + private SerializedProperty ignored; + private SerializedProperty succeedAssertions; + private SerializedProperty succeedWhenExceptionIsThrown; + private SerializedProperty timeout; + + #region GUI Contens + + private readonly GUIContent guiExpectException = new GUIContent ("Expect exception", "Should the test expect an exception"); + private readonly GUIContent guiExpectExceptionList = new GUIContent ("Expected exception list", "A comma separated list of exception types which will not fail the test when thrown"); + private readonly GUIContent guiIgnore = new GUIContent ("Ignore", "Ignore the tests in runs"); + private readonly GUIContent guiIncludePlatforms = new GUIContent ("Included platforms", "Platform on which the test should run"); + private readonly GUIContent guiSuccedOnAssertions = new GUIContent ("Succeed on assertions", "Succeed after all assertions are executed"); + private readonly GUIContent guiSucceedWhenExceptionIsThrown = new GUIContent ("Succeed when exception is thrown", "Should the test succeed when an expected exception is thrown"); + private readonly GUIContent guiTestName = new GUIContent ("Test name", "Name of the test (is equal to the GameObject name)"); + private readonly GUIContent guiTimeout = new GUIContent ("Timeout", "Number of seconds after which the test will timeout"); + + #endregion + + public void OnEnable () + { + timeout = serializedObject.FindProperty ("timeout"); + ignored = serializedObject.FindProperty ("ignored"); + succeedAssertions = serializedObject.FindProperty ("succeedAfterAllAssertionsAreExecuted"); + expectException = serializedObject.FindProperty ("expectException"); + expectedExceptionList = serializedObject.FindProperty ("expectedExceptionList"); + succeedWhenExceptionIsThrown = serializedObject.FindProperty ("succeedWhenExceptionIsThrown"); + } + + public override void OnInspectorGUI () + { + var component = (TestComponent) target; + + if (component.dynamic && GUILayout.Button ("Reload dynamic tests")) + { + TestComponent.DestroyAllDynamicTests (); + Selection.objects = new UnityEngine.Object[0]; + IntegrationTestsRunnerWindow.selectedInHierarchy = false; + return; + } + + if (component.IsTestGroup ()) + { + EditorGUI.BeginChangeCheck (); + var newGroupName = EditorGUILayout.TextField (guiTestName, component.name); + if (EditorGUI.EndChangeCheck ()) component.name = newGroupName; + + serializedObject.ApplyModifiedProperties (); + return; + } + + serializedObject.Update (); + + EditorGUI.BeginDisabledGroup (serializedObject.isEditingMultipleObjects); + + EditorGUI.BeginChangeCheck (); + var newName = EditorGUILayout.TextField (guiTestName, component.name); + if (EditorGUI.EndChangeCheck ()) component.name = newName; + + if (component.platformsToIgnore == null) + { + component.platformsToIgnore = GetListOfIgnoredPlatforms (Enum.GetNames (typeof (TestComponent.IncludedPlatforms)), (int)component.includedPlatforms); + } + + var enumList = Enum.GetNames (typeof (RuntimePlatform)); + var flags = GetFlagList (enumList, component.platformsToIgnore); + flags = EditorGUILayout.MaskField (guiIncludePlatforms, flags, enumList, EditorStyles.popup); + var newList = GetListOfIgnoredPlatforms (enumList, flags); + if (!component.dynamic) + component.platformsToIgnore = newList; + EditorGUI.EndDisabledGroup (); + + EditorGUILayout.PropertyField (timeout, guiTimeout); + EditorGUILayout.PropertyField (ignored, guiIgnore); + EditorGUILayout.PropertyField (succeedAssertions, guiSuccedOnAssertions); + EditorGUILayout.PropertyField (expectException, guiExpectException); + + EditorGUI.BeginDisabledGroup (!expectException.boolValue); + EditorGUILayout.PropertyField (expectedExceptionList, guiExpectExceptionList); + EditorGUILayout.PropertyField (succeedWhenExceptionIsThrown, guiSucceedWhenExceptionIsThrown); + EditorGUI.EndDisabledGroup (); + + if (!component.dynamic) serializedObject.ApplyModifiedProperties (); + } + + private string[] GetListOfIgnoredPlatforms (string[] enumList, int flags) + { + var notSelectedPlatforms = new List (); + for (int i = 0; i < enumList.Length; i++) + { + var sel = (flags & (1 << i)) != 0; + if (!sel) notSelectedPlatforms.Add (enumList[i]); + } + return notSelectedPlatforms.ToArray (); + } + + private int GetFlagList ( string[] enumList, string[] platformsToIgnore ) + { + int flags = ~0; + for (int i = 0; i < enumList.Length; i++) + if (platformsToIgnore != null && platformsToIgnore.Any (s => s == enumList[i])) + flags &= ~(1 << i); + return flags; + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs.meta new file mode 100644 index 0000000..e3a1348 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 160889f21f4d5944b9f6fcaf9c33f684 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs new file mode 100644 index 0000000..a1f10b9 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace UnityTest.IntegrationTestRunner +{ + public interface ITestRunnerCallback + { + void RunStarted (string platform, List testsToRun); + void RunFinished (List testResults); + void TestStarted (TestResult test); + void TestFinished (TestResult test); + void TestRunInterrupted (List testsNotRun); + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs.meta new file mode 100644 index 0000000..3a1c54b --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 35af7d395e501a348ae1a0aa3c91dee4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs new file mode 100644 index 0000000..d06aaac --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs @@ -0,0 +1,141 @@ +using System; +using System.IO; +using System.Linq; +using UnityEngine; + +public static class IntegrationTest +{ + public const string passMessage = "IntegrationTest Pass"; + public const string failMessage = "IntegrationTest Fail"; + + public static void Pass (GameObject go) + { + go = FindTopGameObject (go); + LogResult (go, passMessage); + } + + public static void Fail (GameObject go, string reason) + { + Fail (go); + if(!string.IsNullOrEmpty (reason)) Debug.Log (reason); + } + + public static void Fail (GameObject go) + { + go = FindTopGameObject (go); + LogResult (go, failMessage); + } + + public static void Assert ( GameObject go, bool condition ) + { + Assert (go, condition, ""); + } + + public static void Assert ( GameObject go, bool condition, string message ) + { + if(condition) Pass (go); + else Fail (go, message); + } + + private static void LogResult (GameObject go, string message) + { + Debug.Log (message + " (" + FindTopGameObject (go).name + ")", + go); + } + + private static GameObject FindTopGameObject (GameObject go) + { + while (go.transform.parent != null) + go = go.transform.parent.gameObject; + return go; + } + + #region Dynamic test attributes + + [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] + public class ExcludePlatformAttribute : Attribute + { + public string[] platformsToExclude; + + public ExcludePlatformAttribute (params RuntimePlatform[] platformsToExclude) + { + this.platformsToExclude = platformsToExclude.Select (platform => platform.ToString ()).ToArray (); + } + } + + [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] + public class ExpectExceptions : Attribute + { + public string[] exceptionTypeNames; + public bool succeedOnException; + + public ExpectExceptions () : this (false) + { + } + + public ExpectExceptions (bool succeedOnException) : this (succeedOnException, new string[0]) + { + } + + public ExpectExceptions (bool succeedOnException, params string[] exceptionTypeNames) + { + this.succeedOnException = succeedOnException; + this.exceptionTypeNames = exceptionTypeNames; + } + + public ExpectExceptions (bool succeedOnException, params Type[] exceptionTypes) + : this (succeedOnException, exceptionTypes.Select (type => type.FullName).ToArray ()) + { + } + + public ExpectExceptions (params string[] exceptionTypeNames) : this (false, exceptionTypeNames) + { + } + + public ExpectExceptions (params Type[] exceptionTypes) : this (false, exceptionTypes) + { + } + } + + [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] + public class IgnoreAttribute : Attribute + { + } + + [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] + public class DynamicTestAttribute : Attribute + { + private string sceneName; + + public DynamicTestAttribute (string sceneName) + { + if (sceneName.EndsWith (".unity")) + sceneName = sceneName.Substring (0, sceneName.Length - ".unity".Length); + this.sceneName = sceneName; + } + + public bool IncludeOnScene (string sceneName) + { + var fileName = Path.GetFileNameWithoutExtension (sceneName); + return fileName == this.sceneName; + } + } + + [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] + public class SucceedWithAssertions : Attribute + { + } + + [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] + public class TimeoutAttribute : Attribute + { + public float timeout; + + public TimeoutAttribute (float seconds) + { + this.timeout = seconds; + } + } + + #endregion +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs.meta new file mode 100644 index 0000000..b6974b8 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eb367bbc76e489443a4ebc8b0a8642f4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs new file mode 100644 index 0000000..daccacd --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs @@ -0,0 +1,23 @@ +using System; +using System.IO; + +[AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] +public class IntegrationTestAttribute : Attribute +{ + private string path; + + public IntegrationTestAttribute (string path) + { + if (path.EndsWith (".unity")) + path = path.Substring (0, path.Length - ".unity".Length); + this.path = path; + } + + public bool IncludeOnScene ( string scenePath ) + { + if (scenePath == path) return true; + var fileName = Path.GetFileNameWithoutExtension (scenePath); + return fileName == path; + } + +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs.meta new file mode 100644 index 0000000..1c80721 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1a5c61a06ed66e41a6ee1b5f88b5afd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs new file mode 100644 index 0000000..db49efd --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace UnityTest.IntegrationTestRunner +{ + class IntegrationTestsProvider + { + internal Dictionary> testCollection = new Dictionary> (); + internal ITestComponent currentTestGroup; + internal IEnumerable testToRun; + + public IntegrationTestsProvider ( IEnumerable tests ) + { + testToRun = tests; + foreach (var test in tests.OrderBy (component => component)) + { + if (test.IsTestGroup ()) + { + throw new Exception (test.Name + " is test a group"); + } + AddTestToList (test); + } + if (currentTestGroup == null) + { + currentTestGroup = FindInnerTestGroup (TestComponent.NullTestComponent); + } + } + + private void AddTestToList (ITestComponent test) + { + var group = test.GetTestGroup (); + if (!testCollection.ContainsKey (group)) + testCollection.Add (group, new HashSet ()); + testCollection[group].Add (test); + if (group == TestComponent.NullTestComponent) return; + AddTestToList (group); + } + + public ITestComponent GetNextTest () + { + var test = testCollection[currentTestGroup].First (); + testCollection[currentTestGroup].Remove (test); + test.EnableTest(true); + return test; + } + + public void FinishTest (ITestComponent test) + { + try + { + test.EnableTest (false); + currentTestGroup = FindNextTestGroup (currentTestGroup); + } + catch (MissingReferenceException e) + { + Debug.LogException(e); + return; + } + } + + private ITestComponent FindNextTestGroup ( ITestComponent testGroup ) + { + if (testGroup != null) + { + if (testCollection[testGroup].Any ()) + { + testGroup.EnableTest (true); + return FindInnerTestGroup (testGroup); + } + testCollection.Remove (testGroup); + testGroup.EnableTest (false); + + var parentTestGroup = testGroup.GetTestGroup (); + if (parentTestGroup == null) return null; + + testCollection[parentTestGroup].Remove (testGroup); + return FindNextTestGroup(parentTestGroup); + } + throw new Exception ("No test left"); + } + + private ITestComponent FindInnerTestGroup ( ITestComponent group ) + { + var innerGroups = testCollection[group]; + foreach (var innerGroup in innerGroups) + { + if (!innerGroup.IsTestGroup()) continue; + innerGroup.EnableTest(true); + return FindInnerTestGroup (innerGroup); + } + return group; + } + + public bool AnyTestsLeft () + { + return testCollection.Count != 0; + } + + public List GetRemainingTests () + { + var remainingTests = new List (); + foreach (var test in testCollection) + { + remainingTests.AddRange (test.Value); + } + return remainingTests; + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs.meta new file mode 100644 index 0000000..d444629 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 21d32637b19ee51489062a66ad922193 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs new file mode 100644 index 0000000..b8c0dc0 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs @@ -0,0 +1,370 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace UnityTest +{ + public interface ITestComponent : IComparable + { + void EnableTest (bool enable); + bool IsTestGroup (); + GameObject gameObject { get; } + string Name { get; } + ITestComponent GetTestGroup (); + bool IsExceptionExpected (string exceptionType); + bool ShouldSucceedOnException (); + double GetTimeout (); + bool IsIgnored (); + bool ShouldSucceedOnAssertions (); + bool IsExludedOnThisPlatform (); + } + + public class TestComponent : MonoBehaviour, ITestComponent + { + public static ITestComponent NullTestComponent = new NullTestComponentImpl (); + + public float timeout = 5; + public bool ignored = false; + public bool succeedAfterAllAssertionsAreExecuted = false; + public bool expectException = false; + public string expectedExceptionList = ""; + public bool succeedWhenExceptionIsThrown = false; + public IncludedPlatforms includedPlatforms = (IncludedPlatforms) ~0L; + public string[] platformsToIgnore = null; + + public bool dynamic; + public string dynamicTypeName; + + public bool IsExludedOnThisPlatform () + { + return platformsToIgnore != null && platformsToIgnore.Any (platform => platform == Application.platform.ToString ()); + } + + static bool IsAssignableFrom(Type a, Type b) + { +#if !UNITY_METRO + return a.IsAssignableFrom(b); +#else + return false; +#endif + } + + public bool IsExceptionExpected (string exception) + { + if (!expectException) return false; + exception = exception.Trim (); + foreach (var expectedException in expectedExceptionList.Split (',').Select (e => e.Trim ())) + { + if (exception == expectedException) return true; + var exceptionType = Type.GetType (exception) ?? GetTypeByName (exception); + var expectedExceptionType = Type.GetType (expectedException) ?? GetTypeByName (expectedException); + if (exceptionType != null && expectedExceptionType != null && IsAssignableFrom(expectedExceptionType,exceptionType)) + return true; + } + return false; + } + + public bool ShouldSucceedOnException () + { + return succeedWhenExceptionIsThrown; + } + + public double GetTimeout () + { + return timeout; + } + + public bool IsIgnored () + { + return ignored; + } + + public bool ShouldSucceedOnAssertions () + { + return succeedAfterAllAssertionsAreExecuted; + } + + private static Type GetTypeByName (string className) + { +#if !UNITY_METRO + return AppDomain.CurrentDomain.GetAssemblies ().SelectMany (a => a.GetTypes ()).FirstOrDefault (type => type.Name == className); +#else + return null; +#endif + } + + public void OnValidate () + { + if (timeout < 0.01f) timeout = 0.01f; + } + + //Legacy + [Flags] + public enum IncludedPlatforms + { + WindowsEditor = 1 << 0, + OSXEditor = 1 << 1, + WindowsPlayer = 1 << 2, + OSXPlayer = 1 << 3, + LinuxPlayer = 1 << 4, + MetroPlayerX86 = 1 << 5, + MetroPlayerX64 = 1 << 6, + MetroPlayerARM = 1 << 7, + WindowsWebPlayer = 1 << 8, + OSXWebPlayer = 1 << 9, + Android = 1 << 10, + IPhonePlayer = 1 << 11, + TizenPlayer = 1 << 12, + WP8Player = 1 << 13, + BB10Player = 1 << 14, + NaCl = 1 << 15, + PS3 = 1 << 16, + XBOX360 = 1 << 17, + WiiPlayer = 1 << 18, + PSP2 = 1 << 19, + PS4 = 1 << 20, + PSMPlayer = 1 << 21, + XboxOne = 1 << 22, + } + + #region ITestComponent implementation + + public void EnableTest (bool enable) + { + if (enable && dynamic) + { + Type t = Type.GetType (dynamicTypeName); + var s = gameObject.GetComponent(t) as MonoBehaviour; + if(s!=null) + DestroyImmediate (s); + + gameObject.AddComponent (t); + } + + if(gameObject.activeSelf!=enable) gameObject.SetActive (enable); + } + + public int CompareTo (ITestComponent obj) + { + if (obj == NullTestComponent) + return 1; + var result = gameObject.name.CompareTo (obj.gameObject.name); + if (result == 0) + result = gameObject.GetInstanceID ().CompareTo (obj.gameObject.GetInstanceID ()); + return result; + } + + public bool IsTestGroup () + { + for (int i = 0; i < gameObject.transform.childCount; i++) + { + var childTC = gameObject.transform.GetChild (i).GetComponent (typeof (TestComponent)); + if (childTC != null) + return true; + } + return false; + } + + public string Name { get { return gameObject == null ? "" : gameObject.name; } } + + public ITestComponent GetTestGroup () + { + var parent = gameObject.transform.parent; + if (parent == null) + return NullTestComponent; + return parent.GetComponent (); + } + + public override bool Equals ( object o ) + { + if (o is TestComponent) + return this == (o as TestComponent); + return false; + } + + public override int GetHashCode () + { + return base.GetHashCode (); + } + + public static bool operator == ( TestComponent a, TestComponent b ) + { + if (ReferenceEquals (a, b)) + return true; + if (((object)a == null) || ((object)b == null)) + return false; + if(a.dynamic && b.dynamic) + return a.dynamicTypeName == b.dynamicTypeName; + if(a.dynamic || b.dynamic) + return false; + return a.gameObject == b.gameObject; + } + + public static bool operator != ( TestComponent a, TestComponent b ) + { + return !(a == b); + } + + #endregion + + #region Static helpers + + public static TestComponent CreateDynamicTest (Type type) + { + var go = CreateTest (type.Name); + go.hideFlags |= HideFlags.DontSave; + go.SetActive (false); + + var tc = go.GetComponent (); + tc.dynamic = true; + tc.dynamicTypeName = type.AssemblyQualifiedName; + + foreach (var typeAttribute in type.GetCustomAttributes (false)) + { + if (typeAttribute is IntegrationTest.TimeoutAttribute) + tc.timeout = (typeAttribute as IntegrationTest.TimeoutAttribute).timeout; + else if (typeAttribute is IntegrationTest.IgnoreAttribute) + tc.ignored = true; + else if (typeAttribute is IntegrationTest.SucceedWithAssertions) + tc.succeedAfterAllAssertionsAreExecuted = true; + else if (typeAttribute is IntegrationTest.ExcludePlatformAttribute) + tc.platformsToIgnore = (typeAttribute as IntegrationTest.ExcludePlatformAttribute).platformsToExclude; + else if (typeAttribute is IntegrationTest.ExpectExceptions) + { + var attribute = (typeAttribute as IntegrationTest.ExpectExceptions); + tc.expectException = true; + tc.expectedExceptionList = string.Join (",", attribute.exceptionTypeNames); + tc.succeedWhenExceptionIsThrown = attribute.succeedOnException; + } + } + + go.AddComponent (type); + + return tc; + } + + public static GameObject CreateTest () + { + return CreateTest ("New Test"); + } + + private static GameObject CreateTest (string name) + { + var go = new GameObject (name); + go.AddComponent (); + go.transform.hideFlags |= HideFlags.HideInInspector; + return go; + } + + public static List FindAllTestsOnScene () + { + return Resources.FindObjectsOfTypeAll (typeof (TestComponent)).Cast ().ToList (); + } + + public static List FindAllTopTestsOnScene () + { + return FindAllTestsOnScene ().Where (component => component.gameObject.transform.parent == null).ToList (); + } + + public static List FindAllDynamicTestsOnScene () + { + return FindAllTestsOnScene ().Where (t => t.dynamic).ToList (); + } + + public static void DestroyAllDynamicTests () + { + foreach (var dynamicTestComponent in FindAllDynamicTestsOnScene ()) + DestroyImmediate (dynamicTestComponent.gameObject); + } + + public static void DisableAllTests () + { + foreach (var t in FindAllTestsOnScene ()) t.EnableTest (false); + } + + public static bool AnyTestsOnScene () + { + return FindAllTestsOnScene().Any(); + } + + #endregion + + private sealed class NullTestComponentImpl : ITestComponent + { + public int CompareTo (ITestComponent other) + { + if (other == this) return 0; + return -1; + } + + public void EnableTest (bool enable) + { + } + + public ITestComponent GetParentTestComponent () + { + throw new NotImplementedException (); + } + + public bool IsTestGroup () + { + throw new NotImplementedException (); + } + + public GameObject gameObject { get; private set; } + public string Name { get { return ""; } } + + public ITestComponent GetTestGroup () + { + return null; + } + + public bool IsExceptionExpected (string exceptionType) + { + throw new NotImplementedException (); + } + + public bool ShouldSucceedOnException () + { + throw new NotImplementedException (); + } + + public double GetTimeout () + { + throw new NotImplementedException (); + } + + public bool IsIgnored () + { + throw new NotImplementedException (); + } + + public bool ShouldSucceedOnAssertions () + { + throw new NotImplementedException (); + } + + public bool IsExludedOnThisPlatform () + { + throw new NotImplementedException (); + } + } + + public static IEnumerable GetTypesWithHelpAttribute (string sceneName) + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies ()) + { + foreach (Type type in assembly.GetTypes ()) + { + var attributes = type.GetCustomAttributes (typeof (IntegrationTest.DynamicTestAttribute), true); + if (attributes.Length == 1) + { + var a = attributes.Single () as IntegrationTest.DynamicTestAttribute; + if (a.IncludeOnScene (sceneName)) yield return type; + } + } + } + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs.meta new file mode 100644 index 0000000..fd67c93 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b1dba0b27b0864740a8720e920aa88c0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs new file mode 100644 index 0000000..0b85607 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs @@ -0,0 +1,141 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + [Serializable] + public class TestResult : ITestResult, IComparable + { + private GameObject go; + private TestComponent testComponent; + private string name; + public ResultType resultType = ResultType.NotRun; + public double duration; + public string messages; + public string stacktrace; + public string id; + public bool dynamicTest; + + public TestComponent TestComponent; + + public GameObject GameObject + { + get { return go; } + } + + public TestResult ( TestComponent testComponent ) + { + this.TestComponent = testComponent; + this.go = testComponent.gameObject; + this.id = testComponent.gameObject.GetInstanceID ().ToString(); + this.dynamicTest = testComponent.dynamic; + + if (go != null) name = go.name; + + if (dynamicTest) + id = testComponent.dynamicTypeName; + } + + public void Update ( TestResult oldResult ) + { + resultType = oldResult.resultType; + duration = oldResult.duration; + messages = oldResult.messages; + stacktrace = oldResult.stacktrace; + } + + public enum ResultType + { + Success, + Failed, + Timeout, + NotRun, + FailedException, + Ignored + } + + public void Reset () + { + resultType = ResultType.NotRun; + duration = 0f; + messages = ""; + stacktrace = ""; + } + + #region ITestResult implementation + public TestResultState ResultState { get + { + switch (resultType) + { + case ResultType.Success: return TestResultState.Success; + case ResultType.Failed: return TestResultState.Failure; + case ResultType.FailedException: return TestResultState.Error; + case ResultType.Ignored: return TestResultState.Ignored; + case ResultType.NotRun: return TestResultState.Skipped; + case ResultType.Timeout: return TestResultState.Cancelled; + default: throw new Exception(); + } + }} + public string Message { get { return messages; } } + public bool Executed { get { return resultType != ResultType.NotRun; } } + public string Name { get { if (go != null) name = go.name; return name; } } + public string Id { get { return id; } } + public bool IsSuccess { get { return resultType == ResultType.Success; } } + public bool IsTimeout { get { return resultType == ResultType.Timeout; } } + public double Duration { get { return duration; } } + public string StackTrace { get { return stacktrace; } } + public string FullName { + get + { + var fullName = Name; + if (go != null) + { + var tempGO = go.transform.parent; + while (tempGO != null) + { + fullName = tempGO.name + "." + fullName; + tempGO = tempGO.transform.parent; + } + + } + return fullName; + } + } + + public bool IsIgnored { get { return resultType == ResultType.Ignored; } } + public bool IsFailure + { + get + { + return resultType == ResultType.Failed + || resultType == ResultType.FailedException + || resultType == ResultType.Timeout; + } + } + #endregion + + + #region IComparable, GetHashCode and Equals implementation + public override int GetHashCode () + { + return id.GetHashCode (); + } + + public int CompareTo ( TestResult other ) + { + var result = Name.CompareTo (other.Name); + if (result == 0) + result = go.GetInstanceID ().CompareTo (other.go.GetInstanceID ()); + return result; + } + + public override bool Equals ( object obj ) + { + if (obj is TestResult) + return GetHashCode () == obj.GetHashCode (); + return base.Equals (obj); + } + #endregion + + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs.meta new file mode 100644 index 0000000..c604bea --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 68740a702763aaa4594e8319a05ae0d3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs new file mode 100644 index 0000000..692a4ff --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +public class TestResultRenderer +{ + private static class Styles + { + public static GUIStyle succeedLabelStyle; + public static GUIStyle failedLabelStyle; + public static GUIStyle failedMessagesStyle; + + static Styles() + { + succeedLabelStyle = new GUIStyle ("label"); + succeedLabelStyle.normal.textColor = Color.green; + succeedLabelStyle.fontSize = 48; + + failedLabelStyle = new GUIStyle ("label"); + failedLabelStyle.normal.textColor = Color.red; + failedLabelStyle.fontSize = 32; + + failedMessagesStyle = new GUIStyle ("label"); + failedMessagesStyle.wordWrap = false; + failedMessagesStyle.richText = true; + } + } + private Dictionary> testCollection = new Dictionary> (); + + private bool showResults; + Vector2 scrollPosition; + + public void ShowResults () + { + showResults = true; + Screen.showCursor = true; + } + + public void AddResults ( string sceneName, ITestResult result ) + { + if(!testCollection.ContainsKey (sceneName)) + testCollection.Add (sceneName, new List ()); + testCollection[sceneName].Add (result); + } + + public void Draw () + { + if (!showResults) return; + if (testCollection.Count==0) + { + GUILayout.Label ("All test succeeded", Styles.succeedLabelStyle, GUILayout.Width (600)); + } + else + { + int count = 0; + foreach (var testGroup in testCollection) count += testGroup.Value.Count; + GUILayout.Label (count + " tests failed!", Styles.failedLabelStyle); + + scrollPosition = GUILayout.BeginScrollView (scrollPosition, GUILayout.ExpandWidth (true)); + var text = ""; + foreach (var testGroup in testCollection) + { + text += "" + testGroup.Key + "\n"; + text += string.Join ("\n", testGroup.Value + .Where (result => !result.IsSuccess) + .Select (result => result.Name + " " + result.ResultState + "\n" + result.Message) + .ToArray ()); + } + GUILayout.TextArea (text, Styles.failedMessagesStyle); + GUILayout.EndScrollView (); + } + if (GUILayout.Button ("Close")) + Application.Quit (); + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs.meta new file mode 100644 index 0000000..7d70150 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7ae9d3b4b57cae343b7ff360f9deb628 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs new file mode 100644 index 0000000..7f0d1bf --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs @@ -0,0 +1,446 @@ +//#define IMITATE_BATCH_MODE //uncomment if you want to imitate batch mode behaviour in non-batch mode mode run +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityTest.IntegrationTestRunner; + +namespace UnityTest +{ + [Serializable] + public class TestRunner : MonoBehaviour + { + static public string integrationTestsConfigFileName = "integrationtestsconfig.txt"; + static public string batchRunFileMarker = "batchrun.txt"; + static public string defaultResulFilePostfix = "TestResults.xml"; + static private TestResultRenderer resultRenderer = new TestResultRenderer (); + + public TestComponent currentTest; + private List resultList = new List (); + private List testComponents; + + public bool isInitializedByRunner + { + get + { +#if UNITY_EDITOR && !IMITATE_BATCH_MODE + if (!UnityEditorInternal.InternalEditorUtility.inBatchMode) return true; +#endif + return false; + } + } + + private double startTime; + private bool readyToRun; + + private AssertionComponent[] assertionsToCheck = null; + private string testMessages; + private string stacktrace; + private TestState testState = TestState.Running; + + public TestRunnerCallbackList TestRunnerCallback = new TestRunnerCallbackList(); + private IntegrationTestsProvider testsProvider; + + private const string startedMessage = "IntegrationTest started"; + private const string finishedMessage = "IntegrationTest finished"; + private const string timeoutMessage = "IntegrationTest timeout"; + private const string failedMessage = "IntegrationTest failed"; + private const string failedExceptionMessage = "IntegrationTest failed with exception"; + private const string ignoredMessage = "IntegrationTest ignored"; + private const string interruptedMessage = "IntegrationTest Run interrupted"; + + + public void Awake () + { +#if UNITY_EDITOR && !IMITATE_BATCH_MODE + if (!UnityEditorInternal.InternalEditorUtility.inBatchMode) return; +#endif + TestComponent.DisableAllTests (); + } + + + + public void Start() + { +#if UNITY_EDITOR && !IMITATE_BATCH_MODE + if (!UnityEditorInternal.InternalEditorUtility.inBatchMode) return; +#endif + TestComponent.DestroyAllDynamicTests (); + var dynamicTestTypes = TestComponent.GetTypesWithHelpAttribute (Application.loadedLevelName); + foreach (var dynamicTestType in dynamicTestTypes) + TestComponent.CreateDynamicTest (dynamicTestType); + + var tests = TestComponent.FindAllTestsOnScene (); + + InitRunner (tests, dynamicTestTypes.Select (type => type.AssemblyQualifiedName).ToList ()); + } + + public void InitRunner(List tests, List dynamicTestsToRun) + { + Application.RegisterLogCallback(LogHandler); + + //Init dynamic tests + foreach (var typeName in dynamicTestsToRun) + { + var t = Type.GetType (typeName); + if (t == null) continue; + var scriptComponents = Resources.FindObjectsOfTypeAll (t) as MonoBehaviour[]; + if (scriptComponents.Length == 0) + { + Debug.LogWarning (t + " not found. Skipping."); + continue; + } + if (scriptComponents.Length > 1) Debug.LogWarning ("Multiple GameObjects refer to " + typeName); + tests.Add (scriptComponents.First().GetComponent ()); + } + //create test structure + testComponents = ParseListForGroups (tests).ToList (); + //create results for tests + resultList = testComponents.Select (component => new TestResult (component)).ToList (); + //init test provider + testsProvider = new IntegrationTestsProvider (resultList.Select (result => result.TestComponent as ITestComponent)); + readyToRun = true; + } + + private static IEnumerable ParseListForGroups ( IEnumerable tests ) + { + var results = new HashSet (); + foreach (var testResult in tests) + { + if (testResult.IsTestGroup ()) + { + var childrenTestResult = testResult.gameObject.GetComponentsInChildren (typeof (TestComponent), true) + .Where (t=>t!=testResult) + .Cast () + .ToArray (); + foreach (var result in childrenTestResult) + { + if(!result.IsTestGroup()) + results.Add (result); + } + continue; + } + results.Add (testResult); + } + return results; + } + + public void Update () + { + if (readyToRun && Time.frameCount > 1) + { + readyToRun = false; + StartCoroutine ("StateMachine"); + } + } + + public void OnDestroy() + { + if (currentTest != null) + { + var testResult = resultList.Single (result => result.TestComponent == currentTest); + testResult.messages += "Test run interrupted (crash?)"; + LogMessage(interruptedMessage); + FinishTest(TestResult.ResultType.Failed); + } + if (currentTest != null || (testsProvider != null && testsProvider.AnyTestsLeft ())) + { + var remainingTests = testsProvider.GetRemainingTests (); + TestRunnerCallback.TestRunInterrupted( remainingTests.ToList () ); + } + Application.RegisterLogCallback(null); + } + + private void LogHandler (string condition, string stacktrace, LogType type) + { + testMessages += condition + "\n"; + if (type == LogType.Exception) + { + var exceptionType = condition.Substring (0, condition.IndexOf(':')); + if (currentTest.IsExceptionExpected (exceptionType)) + { + testMessages += exceptionType + " was expected\n"; + if (currentTest.ShouldSucceedOnException()) + { + testState = TestState.Success; + } + } + else + { + testState = TestState.Exception; + this.stacktrace = stacktrace; + } + } + else if (type == LogType.Log) + { + if (testState == TestState.Running && condition.StartsWith (IntegrationTest.passMessage)) + { + testState = TestState.Success; + } + if (condition.StartsWith(IntegrationTest.failMessage)) + { + testState = TestState.Failure; + } + } + } + + public IEnumerator StateMachine () + { + TestRunnerCallback.RunStarted (Application.platform.ToString (), testComponents); + while (true) + { + if (!testsProvider.AnyTestsLeft() && currentTest == null) + { + FinishTestRun (); + yield break; + } + if (currentTest == null) + { + StartNewTest (); + } + if (currentTest != null) + { + if (testState == TestState.Running) + { + if (assertionsToCheck != null && assertionsToCheck.All (a => a.checksPerformed > 0)) + { + IntegrationTest.Pass (currentTest.gameObject); + testState = TestState.Success; + } + if (currentTest != null && Time.time > startTime + currentTest.GetTimeout()) + { + testState = TestState.Timeout; + } + } + + switch (testState) + { + case TestState.Success: + LogMessage (finishedMessage); + FinishTest (TestResult.ResultType.Success); + break; + case TestState.Failure: + LogMessage (failedMessage); + FinishTest (TestResult.ResultType.Failed); + break; + case TestState.Exception: + LogMessage (failedExceptionMessage); + FinishTest (TestResult.ResultType.FailedException); + break; + case TestState.Timeout: + LogMessage(timeoutMessage); + FinishTest(TestResult.ResultType.Timeout); + break; + case TestState.Ignored: + LogMessage (ignoredMessage); + FinishTest(TestResult.ResultType.Ignored); + break; + } + } + yield return null; + } + } + + private void LogMessage(string message) + { + if (currentTest != null) + Debug.Log (message + " (" + currentTest.Name + ")", currentTest.gameObject); + else + Debug.Log (message); + } + + private void FinishTestRun () + { + if (IsBatchRun ()) + SaveResults (); + PrintResultToLog (); + TestRunnerCallback.RunFinished (resultList); + LoadNextLevelOrQuit (); + } + + private void PrintResultToLog () + { + var resultString = ""; + resultString += "Passed: " + resultList.Count (t => t.IsSuccess); + if (resultList.Any (result => result.IsFailure)) + { + resultString += " Failed: " + resultList.Count (t => t.IsFailure); + Debug.Log ("Failed tests: " + string.Join (", ", resultList.Where (t => t.IsFailure).Select (result => result.Name).ToArray ())); + } + if (resultList.Any (result => result.IsIgnored)) + { + resultString += " Ignored: " + resultList.Count (t => t.IsIgnored); + Debug.Log ("Ignored tests: " + string.Join (", ", + resultList.Where (t => t.IsIgnored).Select (result => result.Name).ToArray ())); + } + Debug.Log (resultString); + } + + private void LoadNextLevelOrQuit () + { + if (isInitializedByRunner) return; + + if (Application.loadedLevel < Application.levelCount - 1) + Application.LoadLevel (Application.loadedLevel + 1); + else + { +#if UNITY_EDITOR && !IMITATE_BATCH_MODE + UnityEditor.EditorApplication.Exit (0); +#else + resultRenderer.ShowResults (); + if(IsBatchRun()) + Application.Quit (); +#endif + } + } + + public void OnGUI () + { + resultRenderer.Draw (); + } + + private void SaveResults () + { + if (!IsFileSavingSupported ()) return; + var resultDestiantion = GetResultDestiantion (); + var resultFileName = Application.loadedLevelName; + if (resultFileName != "") + resultFileName += "-"; + resultFileName += defaultResulFilePostfix; + + var resultWriter = new XmlResultWriter (Application.loadedLevelName, resultList.ToArray ()); + +#if !UNITY_METRO + Uri uri; + if ( Uri.TryCreate (resultDestiantion, UriKind.Absolute, out uri) && uri.Scheme == Uri.UriSchemeFile) + { + resultWriter.WriteToFile (resultDestiantion, resultFileName); + } + else + { + Debug.LogError ("Provided path is invalid"); + } +#endif + } + + private bool IsFileSavingSupported () + { +#if UNITY_EDITOR || UNITY_STANDALONE + return true; +#else + return false; +#endif + } + + private string GetResultDestiantion () + { + var nameWithoutExtension = integrationTestsConfigFileName.Substring (0, integrationTestsConfigFileName.LastIndexOf ('.')); + var resultpathFile = Resources.Load (nameWithoutExtension) as TextAsset; + var resultDestiantion = Application.dataPath; + if (resultpathFile != null) + resultDestiantion = resultpathFile.text; +#if UNITY_EDITOR + var resultsFileDirectory = "-resultsFileDirectory="; + if (UnityEditorInternal.InternalEditorUtility.inBatchMode && Environment.GetCommandLineArgs ().Any (s => s.StartsWith (resultsFileDirectory))) + resultDestiantion = Environment.GetCommandLineArgs ().First (s => s.StartsWith (resultsFileDirectory)).Substring (resultsFileDirectory.Length); +#endif + return resultDestiantion; + } + + private bool IsBatchRun () + { +#if UNITY_EDITOR && !IMITATE_BATCH_MODE + if (UnityEditorInternal.InternalEditorUtility.inBatchMode) return true; +#endif + var nameWithoutExtension = batchRunFileMarker.Substring (0, batchRunFileMarker.LastIndexOf ('.')); + var resultpathFile = Resources.Load (nameWithoutExtension) as TextAsset; + return resultpathFile != null; + } + + private void StartNewTest () + { + this.testMessages = ""; + this.stacktrace = ""; + testState = TestState.Running; + assertionsToCheck = null; + + startTime = Time.time; + currentTest = testsProvider.GetNextTest () as TestComponent; + + var testResult = resultList.Single (result => result.TestComponent == currentTest); + + if (currentTest.ShouldSucceedOnAssertions ()) + { + var assertionList = currentTest.gameObject.GetComponentsInChildren ().Where (a => a.enabled); + if(assertionList.Any()) + assertionsToCheck = assertionList.ToArray(); + } + + if (currentTest.IsExludedOnThisPlatform ()) + { + testState = TestState.Ignored; + Debug.Log(currentTest.gameObject.name + " is excluded on this platform"); + } + + //don't ignore test if user initiated it from the runner and it's the only test that is being run + if (currentTest.IsIgnored () && !(isInitializedByRunner && resultList.Count == 1)) testState = TestState.Ignored; + + LogMessage(startedMessage); + TestRunnerCallback.TestStarted (testResult); + } + + private void FinishTest(TestResult.ResultType result) + { + testsProvider.FinishTest (currentTest); + var testResult = resultList.Single (t => t.GameObject == currentTest.gameObject); + testResult.resultType = result; + testResult.duration = Time.time - startTime; + testResult.messages = testMessages; + testResult.stacktrace = stacktrace; + TestRunnerCallback.TestFinished (testResult); + currentTest = null; + //currentTest2 = null; + if (!testResult.IsSuccess + && testResult.Executed + && !testResult.IsIgnored) resultRenderer.AddResults (Application.loadedLevelName, testResult); + } + + #region Test Runner Helpers + + public static TestRunner GetTestRunner () + { + TestRunner testRunnerComponent = null; + var testRunnerComponents = Resources.FindObjectsOfTypeAll(typeof(TestRunner)); + + if (testRunnerComponents.Count () > 1) + foreach (var t in testRunnerComponents) DestroyImmediate((t as TestRunner).gameObject); + else if (!testRunnerComponents.Any()) + testRunnerComponent = Create().GetComponent(); + else + testRunnerComponent = testRunnerComponents.Single() as TestRunner; + + return testRunnerComponent; + } + + private static GameObject Create() + { + var runner = new GameObject ("TestRunner"); + var component = runner.AddComponent (); + component.hideFlags = HideFlags.NotEditable; + Debug.Log ("Created Test Runner"); + return runner; + } + #endregion + + enum TestState + { + Running, + Success, + Failure, + Exception, + Timeout, + Ignored + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs.meta new file mode 100644 index 0000000..5ef068e --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5c3afc1c624179749bcdecf7b0224902 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs new file mode 100644 index 0000000..e7b6958 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; + +namespace UnityTest.IntegrationTestRunner +{ + public class TestRunnerCallbackList : ITestRunnerCallback + { + private List callbackList = new List (); + + public void Add (ITestRunnerCallback callback) + { + callbackList.Add (callback); + } + + public void Remove (ITestRunnerCallback callback) + { + callbackList.Remove (callback); + } + + public void RunStarted (string platform, List testsToRun) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.RunStarted(platform, testsToRun); + } + } + + public void RunFinished (List testResults) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.RunFinished(testResults); + } + } + + public void TestStarted (TestResult test) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.TestStarted(test); + } + } + + public void TestFinished (TestResult test) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.TestFinished(test); + } + } + + public void TestRunInterrupted (List testsNotRun) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.TestRunInterrupted(testsNotRun); + } + } + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs.meta new file mode 100644 index 0000000..c39656a --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7729da83f7c08d244b5788c870a93780 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets.meta new file mode 100644 index 0000000..433c295 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 1d1ccbd729921544dbd71f7e80c405b6 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs new file mode 100644 index 0000000..c45b795 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs @@ -0,0 +1,206 @@ +using UnityEngine; + +namespace UnityTest +{ + public class CallTesting : MonoBehaviour + { + public enum Functions + { + CallAfterSeconds, + CallAfterFrames, + Start, + Update, + FixedUpdate, + LateUpdate, + OnDestroy, + OnEnable, + OnDisable, + OnControllerColliderHit, + OnParticleCollision, + OnJointBreak, + OnBecameInvisible, + OnBecameVisible, + OnTriggerEnter, + OnTriggerExit, + OnTriggerStay, + OnCollisionEnter, + OnCollisionExit, + OnCollisionStay, +#if !UNITY_4_0 && !UNITY_4_0_1 && !UNITY_4_1 && !UNITY_4_2 + OnTriggerEnter2D, + OnTriggerExit2D, + OnTriggerStay2D, + OnCollisionEnter2D, + OnCollisionExit2D, + OnCollisionStay2D, +#endif + } + + public enum Method + { + Pass, + Fail + } + + public int afterFrames = 0; + public float afterSeconds = 0.0f; + public Functions callOnMethod = Functions.Start; + + public Method methodToCall; + private int startFrame = 0; + private float startTime; + + private void TryToCallTesting (Functions invokingMethod) + { + if (invokingMethod == callOnMethod) + { + if (methodToCall == Method.Pass) + IntegrationTest.Pass (gameObject); + else + IntegrationTest.Fail (gameObject); + + afterFrames = 0; + afterSeconds = 0.0f; + startTime = float.PositiveInfinity; + startFrame = int.MinValue; + } + } + + public void Start () + { + startTime = Time.time; + startFrame = afterFrames; + TryToCallTesting (Functions.Start); + } + + public void Update () + { + TryToCallTesting (Functions.Update); + CallAfterSeconds (); + CallAfterFrames (); + } + + private void CallAfterFrames () + { + if (afterFrames > 0 && (startFrame + afterFrames) <= Time.frameCount) + TryToCallTesting (Functions.CallAfterFrames); + } + + private void CallAfterSeconds () + { + if ((startTime + afterSeconds) <= Time.time) + TryToCallTesting (Functions.CallAfterSeconds); + } + + public void OnDisable () + { + TryToCallTesting (Functions.OnDisable); + } + + public void OnEnable () + { + TryToCallTesting (Functions.OnEnable); + } + + public void OnDestroy () + { + TryToCallTesting (Functions.OnDestroy); + } + + public void FixedUpdate () + { + TryToCallTesting (Functions.FixedUpdate); + } + + public void LateUpdate () + { + TryToCallTesting (Functions.LateUpdate); + } + + public void OnControllerColliderHit () + { + TryToCallTesting (Functions.OnControllerColliderHit); + } + + public void OnParticleCollision () + { + TryToCallTesting (Functions.OnParticleCollision); + } + + public void OnJointBreak () + { + TryToCallTesting (Functions.OnJointBreak); + } + + public void OnBecameInvisible () + { + TryToCallTesting (Functions.OnBecameInvisible); + } + + public void OnBecameVisible () + { + TryToCallTesting (Functions.OnBecameVisible); + } + + public void OnTriggerEnter () + { + TryToCallTesting (Functions.OnTriggerEnter); + } + + public void OnTriggerExit () + { + TryToCallTesting (Functions.OnTriggerExit); + } + + public void OnTriggerStay () + { + TryToCallTesting (Functions.OnTriggerStay); + } + public void OnCollisionEnter () + { + TryToCallTesting (Functions.OnCollisionEnter); + } + + public void OnCollisionExit () + { + TryToCallTesting (Functions.OnCollisionExit); + } + + public void OnCollisionStay () + { + TryToCallTesting (Functions.OnCollisionStay); + } + +#if !UNITY_4_0 && !UNITY_4_0_1 && !UNITY_4_1 && !UNITY_4_2 + public void OnTriggerEnter2D () + { + TryToCallTesting (Functions.OnTriggerEnter2D); + } + + public void OnTriggerExit2D () + { + TryToCallTesting (Functions.OnTriggerExit2D); + } + + public void OnTriggerStay2D () + { + TryToCallTesting (Functions.OnTriggerStay2D); + } + + public void OnCollisionEnter2D () + { + TryToCallTesting (Functions.OnCollisionEnter2D); + } + + public void OnCollisionExit2D () + { + TryToCallTesting (Functions.OnCollisionExit2D); + } + + public void OnCollisionStay2D () + { + TryToCallTesting (Functions.OnCollisionStay2D); + } +#endif + } +} diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs.meta new file mode 100644 index 0000000..91cbde1 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0d545b1288d5fc74d8e6c961fb67ab18 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionFailure.prefab b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionFailure.prefab new file mode 100644 index 0000000000000000000000000000000000000000..3425eb9bea87f970937b28061cc624ef75c610ad GIT binary patch literal 9336 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 PNQdE7R35Od6Eyzs)C<&k literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionSuccess.prefab.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionSuccess.prefab.meta new file mode 100644 index 0000000..73ed474 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionSuccess.prefab.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 1228dff762eab21488cfefd42792c37b +NativeFormatImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab new file mode 100644 index 0000000000000000000000000000000000000000..5469913913671d18206532912a4631130d6cee43 GIT binary patch literal 9336 zcmeHNOK%)S5N`7b36Jm&;k|Z1z$HXUByvE;4{WfAlf~;G#6!^D?ez{C&sZ~KV{=+A zhzk-wfP?P{aY8~|kT@g3nNzNaBL{An`l`EUs%K{%p@^s4*6d7AS9e!+SAA90W2L6v zRO*QxrPMK{rZ(xW&YwPW`b_^h_51$*{w-9e+x~Kzq;qDVx1)3`Q*$~u{2Jsa6Zjb_ zbvxazEG5Ocvufj=%WLnMZt-%|GmEia&(%%T$b|0hpWE#sdw!u86=}AxQh%Yi*sGq_AVDqtx{Vx=_%4g8oqN_&FD&*et!sQ{4z6DxMC{C0$z=14jq8P$V6* zWaqCqp*c*J=$N^<*>);>jpO1-jSkf&F0jxjBV4?sH;k1YoK!XD0_%Z-UbFN&jtkmb zE}jmRCN6HZWaW6MVm~j?)C-ATi%pN)ZWDA9v$j(1yWPrg-=P>NRy_O6iwwo;bhBu) zfOz(aMZ3ciaSuF>6YaR5!{{hYqTOkm0uJ&bi;{Jk_Yy5KEA(BGYUma=%k-|AD#2CU2CRt7AsRI)}&_D>$g&K}v0o&71DdBeT75G1m`)&T&UV>PwXR~Wz7*BVHa`r2gpn>up(3hR|7 zUmK+#WqHB+BF!8`C~W2>*V8IzjUBP^+L#;f2q>2}?uWgWjeELM1uyDdlQEal$eBg@ z8HECvISNZLY=#1uxnJ6GP|#%PArwdxw`(T&S=H+u3sbRQ_`^glp#|m zX%rMc5}tW0SIthbm6@|I03tMB9d$d`!@J;Q(=~nNIS4nr)1UhKK}) zSMq#_fV3LdgMh4jmE-w`qM=u}G@?KXQTwDR7gO@BD=8F=>;SkTVNxA!G2U2ry)%N4 zXh*T_yWAdxJwf{i+%BOo?EgNu%P_~czsA1fT*+`d%_C+Qa2sBF zMml~%+ut%Q;m^0%8S2m~8crT06oR_WO@Mz5+=P)$i)8WASZ*Zld2TA#I*8&PWgF~S zCH}#e!1n8&6`<$w5i|nyO3x|*&-)~cqaHw}ZBPhTE>W*GVBioX-uXeBP*j4Pr>jp+ z15+|Yt`Q7`XctHnFz`6hqFCuIE;cdHVyci1d$3}Xp2=v^k?@hn8Y%@vJ_Ju01^xHI z)A`r2nWR$|M>enXqBGFF^!=RmOa_;ZQaREU(>3ImpbfChNQdt4|@fEGZkC9{E{pHARe0Jq_I0h~y%^>a7D ziHtHmT`6v7YmK&r_B85J?u=+zVy_pgE;1n3x8dF-vV>bdt-~hH=MfJ|sP#0XP-|n+ zIbC!ID`{FZU~a%cut*{1(v(!17OBN8l~kxYJGqh@*8O&tuF)ES&q+b;!eAHYSN_Ra z4ELH%x&ul?;Vh+StLl_P-!ooTqb75)7P#;mkEMMb&~pLF5&NF|xfO zQ*`}*rgYSP6&lT3yoE!b|GZ=2PhHDtFX~5Kdze59B&!H#cnTUG`#LdHoE(pa80Eo~ z{c^^ejx-vDd(wTJr$!)y;_2|*gn{ALFHk8}#$l3g8;1opKD5Kv<1l;x^V32&!D5+9 zJ5(;|s0-~!x@odvSI%k^YAo3?kWleU1_61={3o?SXX_NpV`O;-4tl{s5Y9-40y>nY zMG72>CG*G3n~rIGhU7>!a4N&*6@n?3D>M`ESFTWC$8OH>TsO=}EQve(-q!J!{R|eQ zCBtTR{<^d8V1rWrio9a_bX<^h4eyjZ1v+S_q>Uf6Q!-8Qbfr44n2mJX^vW+7R;BA1 z3%b=+S{@J8*eo}!o}yqw0{J1_Aett2XTTRr+mjjgz7WhSS84?*^=eq8u! z^5eIEct@b>8;h=G`OFunjyBtL42c2Ld&wD7>LH&Ijw({!kmwq_DOWzbU)GE9V GG|(S4*UPa0 literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab.meta new file mode 100644 index 0000000..e04b231 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 616ddafe39e02da4081e56f7f763af3c +NativeFormatImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab new file mode 100644 index 0000000000000000000000000000000000000000..947a40f12e53d4f198d92b7fd045fe2b0608de9f GIT binary patch literal 9336 zcmeHNOK%)S5N-nr3E}++A-vX3A~=O8i9`;_@gq*K6eo+2Bgk#d&h&J3cU5=QS5-Y$ zYT^T>j&3NW_A529Mt61k_=)2ux^JpKwzsz*raIlW7m_%c(Y;_jO!}#s2{O&EL5?zp zpMg@3((TH8oS!&N#{0l9cN(@ zPg4J8s=L8*Ge~uuo3YeB>iPg(DCj;$f2gw$t^)AT!v z3))*Qjt-SNE*>#t#dxS}- z({L?^c;<;kd(04V4?K<%?Qube(NXF|d%`q%9AtSK#w#@MC0b-w=qDxBz%Fc>2AgV{ ze_;zx5si~$Y|7&-3vX&xzNh6l_PN~)Qq>9afO|hvLlMTg3c93a=Tl}RsjH;V>GqYR~Wz3*9u4!`dVlBYe8uB z71k?FzA{QTOtYNzMVdK?P}s~1t|wK-8arg;l`&VZ2`HB~?uNaajXSzR1uq7hI%O`U zku!_*GYkbVa}<_hP!9z#bGNjkprFpseJGG7Zq`ijvlOhf3`_xgJQE+m6s-GhOi9Cb zQ~FFDqES%XNO$dX68oFXDF9quh zI_s4?`qEC+tvtxXw(&}3B=WN8qSO@EmXjocP}y`l57#v_`HG-(!U5uz(jd;dNxC{B z8X^)HUcvJ&0@7;S3j(t8m5%3MiiY0l2Z#bGMD3EMTujKfE+$YgvIF3Xgh{op!FXfb z^~MlFq8-JwZ*sdA_IT|#xm`k`-~R@;%P_~azstVkRKajF$wForaP5I1O^C2rGVH;i z$BW*Cpyv=J-nl{RP*j4P zqpMC%15+|Yt`Q9QXy-}fG4LwUq8RB7F4i&7U@D&ud$6eEj!tRPq41H%8Yl%t-UUw? z1>OJPY5nWSOwuZgC7TVhywwXj$&HNlOa_;hQd!bP-PYu=CA9~nmK^$oRQ6)H(#uza zwRuv)4IW#Rb)V}Ys0-xWC^!!T8mAb&m$g`Q0r)h zq1MErGeO?&Ehb4`gSj3D-Xi&!OH)#*TcifJlv1H;?c_?PS@)Z1vP^3PKF0;M4TEi* zU-~C&G2Cl9Zuck=g|nEDUFlgYoyYhQLFbmHj`5>4bjDb4GDIQ5eC#ZjW1V9)^biNR z0cDS*{KmbwaY63p$NAl^d-;F47dAI+K5_%xSxfzhe6*HI_cCVBRqC`=#h6L!P4IZPl0l2wE=JOvGpeH|MpPL78| zjN)L*d^zJyM;eX7J?TEmQzMW;adddD!$AM*7pRmf;xNg#iNib_ADH2*aTq>;xoIJs zV6n)hEh-mu)P?pVS<`90DQ7haHI{5YNT|3agMhqb?vq*`q$?E5V`O;-4tl|X7tTnB z0y>nsMe-bqA#=yfYnEwzhU7@qb1H-S6@n=jD>UWtSFDg{$97KtT-VP?42eDbUJs(a z`3&ZzC4+i){=TzsZ-Wy4ioB@1bX*X(HSd%>1=?w+q>b;iQ!-6)bcH%E>eXajcZx3< zMy0D63%XTRS{@Ho*eo`znxbGsJo!1nfO^Wap~`5Ude$W?b?P}XVG-ZG`P;iiJn-Nj z4|yu+@o+Dx3QO;w^CDF$->?ddW1*;EC3aek38pIPP_0{yx*Vl&sAdH$o?u@)sA`=$ICny4`46hHD0;BMZobiv!+f*Rp?}oqM|mUF8U1?*vTya{ z+&AN&fB3_NTk%&1zgz$I6CS@D%RPY=I1`A80`bSqBZ~+zP#~JKQY;6=K!JED0HfLd zvbLd5tKTLrhz%(1l{gP59_oNj7Fq#bcKHtcpzgM&Y#W>{pYepcyUG@fDT^GB+P15G z91o2H4cV>oJUF}4xY(tiUNc>GqH}|eF_Gilmusi~t_@pxXY*?}9N(R8I2x}}RIsj? F|4*8G%i;h4 literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab.meta new file mode 100644 index 0000000..d16c91a --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: d940e636fd44be84e9b7e8da46f700ef +NativeFormatImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials.meta new file mode 100644 index 0000000..ea98c41 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 8d55f43641ba3c14eaa1156abc0edabd +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/green.mat b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/green.mat new file mode 100644 index 0000000000000000000000000000000000000000..ac8a70c46e15524e38ca537f26657a596e87c9d3 GIT binary patch literal 4212 zcmeHK$!-)e5Ovu1eP4&2up}V~s}PVt5)gun2;n+%W;~fjo$ko(pbQ7pf5MedfdAkV z_y8o1NQ8P--Gisq16K}HQje=$&sF8;vfZQ9)=;TEPARpOT56OU9~v1NY2H@9*4EYr z==~r)FSIi@(4m^tiBV)&0}`?xKdDlisF{Bjxv^2TRGVFRYwGT4&@j`XUQE;mGQt%E zZLU|V&fcGD1TMBytIkA85JwMaeASw!UZ`qoA}7Ao78F&$i0yH_k;O*9Nb*t0s^i_u0*pX%9P|#(%VIMO zBt9;2Hi#C9iI;jw_(o(1qf%)ntkrELzgQDm!psY`kA$x*ViLSJ%*{5!KqQ*z^_I4( zp`GU5?b6wWU{>Z@x?wC>5slf{;h~}SVq>R=Lu^PH8@t5R6@5MmT)S%HWn*1?u4Rlv z4*H#GWSxOYxF~mLgSk*rDb6LmOz78Ubt-x%C@FKH0Hup`id62Uz79o%@utmZ{N3$h>;XpR-|9=l65 zZwnpwa7Y7ERx~HX)HRtmbOOb8w24xw>(FrElO9m13NLFjjI~p%ygN=6?06M>o9(Ad z>|UVRW;3DU#9plwkeH$$=}f_nS3lC(61$Z0H1d^7KIel{SuXuhqJ$mo1nDY=}@|=4SKJ5F+^zNf$#7Ct6JUVU^;7FiI_-F~H znEV)F^5lCR9pj##a>8$xAehBhGm{hf!GUA=mIqX-!h1|s#C{Hj7n7%W(A+rulkswxfod|3%y z#hN5uv30tg)Zph2BOAVdd;V$o=XqANFaw07a_T(WLr*#n#{N~N-E|w-#`_2?i@IC z=NI?}{({i2d&ZHc#&G4}u9DSKKdDs;N@y?#SrKX!C*ky}rIa zKnWJL{8>XJ80M@j3<#P2Dm+&`-C1c1sx!VL|fwpmRv#eI3EkeIHYZK9`pd`(O0;Dd&DN=cW`Z^R5##>g0%7cV~ zPl>u1{L#z~ zTdzDgMm7jzL{;5+a6Iev5xf(^rAkaajv5NE6CM;Q4j`utLEVZq$eB##q&Zo@d+aVR zct_}zheH^UvZOgJrmn@z(+w2cu_jWbu0z9)hdiKC72ein7;C52_;j2p*wGYwo9$;y z?4F~UW;3DW#96HrkXWMc>0H5%rtj%|iCt2867fnV5Bs20HnW%v7YGCHP>}5&*PTqh z2pb7wL@i|UrL5PVu6d;MZOzc_FW-}it@Rrrj_&REtTc=iFZL&Uzw_J`b) zhg{*7*lTQm)YGon{Acs!D@CUsgg_ zu_lREY@J>w^;r*p`t|zj%WpsChiX5QFSsK6(r2L0K%ap=1APYm9|rI;S<~P*5dTf_ m7UGL`VOj?feZ}JqOuyr+D}5$~)J%ZI|K0_D?a`TIr2YdBGPa5U literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/red.mat.meta b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/red.mat.meta new file mode 100644 index 0000000..3914d56 --- /dev/null +++ b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/red.mat.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 0503fcccc592ba54ba2564beb42ce08b +NativeFormatImporter: + userData: diff --git a/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/green.png b/src/Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/green.png new file mode 100644 index 0000000000000000000000000000000000000000..f4dcca21896885fb30c3a4b531f1fce4aaa573bb GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1enP|?%HF~q_@`OYt&Z}!Zr4V+$+dEIy=Oc_{! eWCgQ?1cO^3)Abdn4$1))GkCiCxvX results; + + public TestRunnerEventListener ( string resultFilePath, List resultList ) + { + this.resultFilePath = resultFilePath; + this.results = resultList; + } + + public void TestFinished (ITestResult test) + { + results.Single( r=>r.Id == test.Id).Update(test, false); + } + + public void RunFinished () + { + var resultDestiantion = Application.dataPath; + if (!string.IsNullOrEmpty (resultFilePath)) + resultDestiantion = resultFilePath; + var fileName = Path.GetFileName (resultDestiantion); + if (!string.IsNullOrEmpty (fileName)) + resultDestiantion = resultDestiantion.Substring (0, resultDestiantion.Length - fileName.Length); + else + fileName = "UnitTestResults.xml"; +#if !UNITY_METRO + var resultWriter = new XmlResultWriter ("Unit Tests", results.ToArray ()); + resultWriter.WriteToFile (resultDestiantion, fileName); +#endif + } + + public void TestStarted (string fullName) + { + } + + public void RunStarted (string suiteName, int testCount) + { + } + + public void RunFinishedException (Exception exception) + { + throw exception; + } + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/Batch.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/Batch.cs.meta new file mode 100644 index 0000000..4595868 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/Batch.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5401885870ebec84f8e9c6ee18d79695 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute.meta new file mode 100644 index 0000000..9a7cadb --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 92b38897656771f409e9235955975754 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll b/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll new file mode 100644 index 0000000000000000000000000000000000000000..ee8b155d7fce38d44ebd8fcaedb8c52e194c7eb5 GIT binary patch literal 327680 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 Gb*L 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

>JutcluU}C9Q;`=N4(7=E;iM)N|S@ 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%0D|oKv`vX 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 SFbEg~3<3rLgTVg-f&Tzf%r6E2 literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll.meta new file mode 100644 index 0000000..38d55f5 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3c5e1afc6e0d68849ae6639aff58cfc7 +MonoAssemblyImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit.meta new file mode 100644 index 0000000..a94ee3e --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: a92d914a774b29f42906161a387d79f7 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs.meta new file mode 100644 index 0000000..96b0d0f --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: e22ba039de7077c4aa95758ef723b803 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.Mdb.dll b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.Mdb.dll new file mode 100644 index 0000000000000000000000000000000000000000..2ddd97685300a00101c45fd79c53ac449a317d8a GIT binary patch literal 39424 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 literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.Mdb.dll.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.Mdb.dll.meta new file mode 100644 index 0000000..36a8c4f --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.Mdb.dll.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 96c89cba541e8fa41acc13fcc8382878 +MonoAssemblyImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.dll b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/Mono.Cecil.dll new file mode 100644 index 0000000000000000000000000000000000000000..5e59e6469ce71529a12d351e662a3cedb5aa54c0 GIT binary patch literal 280576 zcmeFad7Kp9=^oadbLoagMPs*YNEljT^J<>Gq%b<27fcm9pa?;HPYfcKQbBU7x0TA$qM z;g%zx-0AqUS5}K_!r-iM`FX|DmakqNtSzoMqZnSWy0~(6@sMMVE1nmee#Rc{?de^N z=p~CR>&O<@O7`EfB#P~2%ibx|lCrFMNEL4U+d2li2x1viI;ym-=>{O_=iT}m{P90I zoIt)t-)ULXT4{$n750)0eMZ4zCvYECU16I69GW6uI6btcIt-OY*S6$Xd7!-{>CU z8RrIIlsw&I>D(c; z*!H_DD{Zfzj^BC?Kcy=aa&q%L1gqwOt+Snt3CrqJhVPp&PS6d%riWwKC?FT~;MZ2i z4J+%taFxznB4SGLl6SPRuZ5;HO}ALj#N8DBBhVAw`uY_1a&5mF;|+z+ZHSyty>u5}!8 zA>}N>BO4q|0=Dx33KZt05eIV{GVB529!TdaVy&JdG6BOh3G!ANLW)?F)3>(dwzibs zZsO0Gd?VJmC8WWzjzVPoi|l#FNkL9vm`GCI-;;M$faYjY?2t#%P(`;R}6o}|-git>B3{fmUHVdX)9ty1LbUfS#L%Y4Xh+P;)6s^>%hb4&eNsbG0deSg5VBlcN80CeeQ+dq(4 zt&HE?L6Yl1kn8N)5N_JsqVmxJMNp@wL}`kLoM(z!}5hp~%i4lR?tvr>87>fuDdef!V z_SBXd^yLQRqyyccI%pL&Sg)INYUnuKU?~GEw1Z=CcUI*C4A;}MOSJz08NnzbYbX5G zmgT{krUJ0tI)>h^=*F{ssLr!(|8(5yS>oNSurAX7sAqX-0P(**T>=~e$>|QO_!+da z`FwQ|oc^Ks$#k^%hv9x6hYhZ_jVMcuT3C-6S#4L>a?{?BQ~}Sv6rH_mUy2hU> zyrB%Z?e!Szr0WEY-6ClgiZ^TfqaYf=Yp{R!hLszkl9r4ou3R#w#0@L`w?T@XtZrb2 zFywJd_t`b(J9q;58KTv9p%xOUxe3b+k)}1l=fMq~xfWD_5eDLPT$&|f4PXNvyKt#X zn{ZD_z9_p()RXoGAQhZP)ml@dnXqqqa#R z>>5Q%p(d5Ho16;!s}R(#5y^nR2a*eIh7As?4C!;ND{#jcF&QQURXmxGRo4j{gnt+WbY*5 z*(@PY3?Q#p+Q-SGy|tZ+bLMy{w2K=MR?2MPsSeL_{lzG!K&+i@#mC^Are2GjdHNx9 zYtyPce~r*=oZN_}oheUl!p*MHQimYOD!z;#&DyJ=wn)(KID>_fFVh|h#bsO2@Q9Io z1x7MRBZ#?sMxjw=xrnJAI5kPM^A-z@m<8*Fol9`mnY6da0ZOgXt|_ccRThs#gr(x? zSM!(ZD^-s~rq@Zi{S9t3JXsWXGYc7}P)a8QZ_R?;?*~*!PH$>RQana!HJXC}YA%CP zXks~nmLb&2RVL_7Y_u>n_%}$7G{LNNk1}?zP^>W5QYfMYB{iimWDBV=p4O-qUYV_^ zU9{j{<*#LeV*w@i8lqQ=G`GFmWIr_u%^xk*R&tU#t6ZZO+NJ^~g*NTZ*i@0r5E`*& zWp9(_X~qDHT%>5^Y+JOvS0g|plL*nE5xhY+ag&n5G?mN-3%0IB&>nn*$-9t{6xrY$ zMxnG+-za-*38W?qP-Zu1tEl*|Q4zHj1r+n3&J@si+X7TTFE_uav9ZZ2w23(=S7F8* zMiY-xY0XbAmYq1BpNyC0M<%4&L0jBnu{h9#MsF&7XR%wM zFt)G7A}XwpN){=Tb(N+3NbZ9 zORLe(ug;l%ex2#~MT}d~XvP}eXBtgtaX4C{NT`R|zuLUiQ%6e|9UCSytEIj|37m(# zo2>=mc!ff?8x}i7WiHXQ%B^s?=BHchmT4NlhT_Z1cr_W+={KAx2vmticvd_0lQ_3$yG(n_)YZ425>%!VCtksm8So zE({H$;B2hp${UO9_CZL5iJ~uEc--QJs$XvA{Yk zA8AXAHcVUc9!V+N5}5$heqGqGFd2BU8C*GjJQ?^&6Oidq zfOaLlvbPdN+KCEp5=dR%+en{Qv34=_fHPP|8MP4) z0Yy!U>e!@l>#p!ctXBCZ{Mg0U2cmIOkpsGTCN_W2BE!m4!CXDj$O%jCJ=y zN-D`Q2~p-G0oXlpY|aGC^o0$c{)!@Ha51Qj-{xp{>}AoOn(m9XzX*bDPQ~$yNi=?s zkY7~5Xyl{g!{q|6z^~dt!rB>y@e#jH0#n`fUF!M4~~x8Mc2WT)_t!Z@jgW zcnwp$&5Pp`TE2K+fLurMvzwR@CS91Ou}x?mcMzJrNGx;?Evhsx4p#JrW-%6Nq`X2V z_$YEvm{F;-c~Y($R>Ga}Frzp5z~Gx)Z7HL9vCO?x_4`%YTMJVwg;&ShTT^3&zDlQ? z%DR=#!~|PzN0ixw@|9cR=*}jj69S`GXh(?ZtR&R=A*!=5r8O6KPR%B4{|xxVK<%6N zhNK<08%$;zSD7Qp8Kpv7sjyc`SI+=&p1%-x{uK^4r9QcHhCNz^wn|~zj=E=Im{x%S zQy#`k(r=o)bDY>eE~`9P#@3qpJz%;_IEd6?ol$B$(O_OHe)dUld?Ay541zMrLUDcq zQgI(E$*KieM=`}&$1tv^A3TUM=j#mWVW#e_aydqdP zj1QUtJQGl+{vr50Mwb*WO_O6C2p`n7Xf4eNC^zE_h~VBa;dPRp%u>c;)6Gh73m7Gf z7*xnYBSs9dg~r8pfHFwyZ}n0#&&Nt*A5w^wMl3tIr4_cUW$G%QtYl(Mac)bl)Yz0n zqm{1DB=6DDo};vIirp7s15%8$b)k^#Xx(|kf-jdsOV`@Yo3YHtDjl`wR8&12d$H|C ziJ}b@naUvR-J<7B$i06hGIo~OTtdcb=zpTInh7Riy`1Bt2)Sq;i$(e*SLUyGGdFQ zFgiYjArRKlE`t$|_pea4WhJjTLI8X&4^7G?^Y}mZ~X=jwt z%#x5g#5M-@mtBwPQ+f!siLkeBn9;fD61sXsw7M)5`$Nzs8LZ5HB=%j=&c z4;||yc|;<4{i<7)=gOE}?Tt2~skmXKj6UqV|9&LYq-?S!I(OPq*tT>u^QGo1qV_-A zcAoZcLU^{-uC)d^Z^qM&230G|d}$`S-!P`95!H5UgVTQ+{WRsQb=ytG7XM~RhNR=8 z6VlN;DILB4+jN}1<1`kgy^&|Pc)n2%*rH3jC+Y8p5}SJLpOpUo|CiFg{n9BE-zew) z8+q>aMxN!jq_f)^ws#H6oPUlq0t+}AiHx(nT5xOBvKH)2Tv(j`)0e67+D`Fxz~kyF zgAG9o-KQ772CBh>B961!2tUyscVYhl$6VO$I%nipeln@FtbBC*|y56S~=Ic=5*G(^~$bCM+yC#$`$a z(G;v>1OYV{l7|Ud(cQ#&eiV5tnL^BLpP@BN`bB>Q8o#tQzaBtOnq4f5ZZ`H2=RNIB zcoTA_2Rb+Xb6N&zP9@pBRQAqgpwQ;!Qn{q2KBc1ubWNDp=pMLZ9fo9}waRLybfi9P z1I(3lJ2mZ!PPn`)y;N#bGPTKY$O5m19Qk+jRe7Cb&P8zKIh(`yj5firG<2^puoQup zr{m#%gK!=egbLF(J_duXV<3$^SV`e}yGECDBR$aad>kTlbbdLJ($NX*q&e7;OjHtQ zj{6^^5|56Dag}dz96MivqFfw{lgOgzuNjSaW09sdfIUzdR^?>$2xJ!^#zV(*6Xc4w z=6^QiN}WNCp=3`oAPf@#Mp40FFP2M*7Tv4Z4aN*cj;C99Os$S(J^umb_Cvat7#F}) zZX>aRx@=p!LLMZ*UYM%FR7qAN!wguY|Cq^Sg`*fLh|O4e-H2SZ)L|~BbZmR8_Zg(2 zdOD1$j;ibO9GFiihjUELpzZFI>K^tc`@E3;Frzaw91QU>!*M+Sa{x;V z9bF@-xH_(v@r-Tlhp;-b&DJJdvB8}yruwH@JE=-So=_nE;lLeD2+1;;hfOIT= zHhs-JMTYPl_SWeKqMD@IJDgA=7q^zmA{7!bg1=WNEz}oPuIdkLWnaXTiTZI1@Nd+=#zpoX{cb`loRppf1HT zI18N8y{^(jo@c|2Eu)o$k6LP3dd5c4!jKP(#bT^X==?8{7E-q4YMWWIDbV#GUb024xSh?=ND|*Pe%NZI<#mGa#EJCfPE+Lr1)E(VO|y?ZzXHmA@!N*nA3CvL2_ z7vesr5m%9W>|0xqi-nR4N0V@z?F}-T!ctv*S*%$!DyT92qf|kmY_#VKwwTzZ{PpYL zk)4OC>bYMSr7pTM-}jLQ^dTE@Z_&DF2dj{iw$xApG0Uloq&JYSq*Gh&@|=;MqVCw! zyq`?S@O zGcDTkNUo`LJLP`^OwtB9BiAzDqIj>)mP_-Ru$F=obY$~yM>ct8j?st}>waq{xp4** z+?H#XBNeS!GHbU}t;yE0;5>vF=yY=jv6FUEbu=fiY1TeZ>zdljafpY1San!T*fU$I1 z3cxfJo}Xt6f|V|u+Ni0zl#=ym8T$>Gn1@)6WeQ8Geh^ror3|y0^1lVP);!i6 zld?*sxvL!t9x-a$|27z841Gw8#WUVnyBUeuk5+@gAri?=hK2uiiM_pbFpE&@QE}a& zQxV~eDr_s=>1JKoP|O9G#HQi+2R1Moj@{wNM?NT(HQkZpFgSW52Xw!t*ElvX28pJ% zBN3brp@X+0x@=+*jg1$3R9LB;>OBMZ^2PYk+&W&e`hBFg&Rmz5O~7}fx)%~Zd;bX%2;r<>3O=;vLZdxm@xsWh_3J^mZt8TstQ$Oq6lj~klzFww;Foo8 z%+lc1m?6;>Q;={N6MU&rBWqMaD(^pmkS4v%WU4!kP#vjWMf~r96I(fYCJ=+$@!Y{Q z#a`Whsc!%;7hailCwP#|4Hqhku1~qvovy|CLA>stXX2+Bi=xI%-HV?LqEaSk za5`d*xrIR!(Pm&4dwZ)W1g%78qTGjAMF-i$rcSRl>&2A!nuFwcovCbU5eiRCYZmS_ ztub6@;i}?7Fw;7eBit$pr*3eatl=b$$B;G}tl%!W0ndRkNi!9-%^kiy z@J-^*2AJt>6)FA7hZGe|8N%z2u*rB9e+qYDT8eXUY5)@+s~2~471+B0@f9Ib@HHH? z@Ls#Hb0ar*3P&8dmMkoHgh#Uk8=yTES{u1pDc}U?L_m>>)eIPV6euEVi*f>pHPK{U zB4A^07fO>YhYgSpB2j}eLddpC^OsH5Yp4Saw^zsL9c^Z^fyi8MX(gRaRx4Bs0{}54d+D*WbjGRw~(o(y|{vf}~ zDU6J-7|*TJ2VGVa=59oc_P|qJ(Wd+c_75c-|A?evoRY9cktTF%Sx08;9oE+A2-f12 zu(UA)M8-_knMj$x+0sp6#U_V-A1z8cS-k+i+sHiva`&d(!6~3H?`6jFW6~|io=?fv z-jCz6H2j%=Y@6cv`F|m+Z7GSq-AlISQW8(AY(-s&xS*_y80AuIO`%_>8%3Cg^3bQH z(G58)VZzW1VRVvddx~3!0@9_;@P-oUy+OT^H}OUaaF-%T;~^NQewDJlQ`xRIY}XjJ zcgfwWzZ-WQ^Py{zKLkYuU<}vsmZ)DZtZsdy+!OU1%Fo-;8@> zA>%8UFTMxBR9kL3s-BLBfZw7xZ-R3pPRF+xR9O2!|0ZzSFyoYZ20mVZ?kX)EV=gI3 zGKMTK-3|8JR5ov;9U9$x72-`d{T4=iEj5D6OTPnfyK?b1I-mjXP>8ok)@FrxQ&}sb zpe;4>Er*ky%eh}!N2BGIuqBf7(WiQ1ZOas-K^qcd3i5GZ)f(prLtIF~>*LU-xVE`- ztiB6a_NA>}P(+m(%){y2Pm&8il%Zkq{8$cSIalg`8~DSP7CaN+zk(E9j{>o6|F<9! zC`5C-#(y7D@1t!@mkyn(a*!p8LUqtjsp-+^<`MjpJcZAl-MCM-)6$AHJiYc8iygW?j~Gj z@Aa;%+l>PiS$9=(Rcdu*Nb-mZuY0e~;!VX3aEuS3@xuni;!SDCS)8vN zUtVt9-0?1Ku4En5lLTRC3GzmCO6 z#Sf%Ta2AOQP2gIL3(bV}R0|Z0Qau9KCvg1|SFdAPOK{za>$|u(k}V&JAE*2Dw9|tl zC5l0tz==>ivX6eVRgX!H>Bl-*&tza7^YuG4V^xX_qeXnHL)juxtt^&woJ#`Ps! z9GpCjtNc8EinzQ?xniP6qK+~oa<KN~Y`@ z5?Oi;3TI4RnerbEnaz~{-H^SRGL|ES0Xlrrki|^-QA6&WDSzIOvoqz78*)yje6Jz> zO!+oLmNMn*K$dU7kCTT2^Uz;z7)_4VnjfbA$~pWLaUruDL6bzbPGG1CL%k&fm~BEr zd3}aNilX|G$7TflUPUfAA8`^!LMUw%Yf8UT$%43E^6b~B``gs6k`BV6L zliWeqoE|X-l)yy{weHPBAuc|h!%!&H1q{X2j5mo3n#6jogn|HhT4xGFy}2f5XUac8 zT#OH;yv2|x+Q&hb(TF!S*{y}xGqDg69}T>S3kjyZm(k(JqDE~L{nG;2JI%sX_VEL2 zU5;B37nFUXA(09WzlfqVMsX`2jGs4A0LqX}dJz{Al*Uaqz~uN>(yRU&aB01CP3$wj z&t^jUhp8>n?a4VUuViPEjkfDZ$Y4fZZsC*$%`2{N;QA-7{ZO;c#q}VrKj0dnybwP| zT=xnLS)^-iOBErbWti=}khW+~$i88YW+bsVm6FH#lkR1uGP>v;iE(A|S;D4Y0|clgSP>>I8}WO10is_^bSe11gE9zG``=M0|_k^b;_M3#ox z?3Ve{RHD}dW%lCg!!-lfOkDlA3a$J}^C!cfHvY8pX9|C&@@E=>XxnD{Ac21OtzT;->9cMYdWS- zR-?L$#Dkg=C!1HSx!6_}?A6eWVWpse#uq~lj_Vogp00kFKOeyl9=hsi**YClfR<$N zZvY%GEMOM+6#CRY;pHLl^jbQPb-i#HetZBaeXP4gpFGF&fP<_h_6;lLNNpbHLS$-g z2OkHY!7$w&2g&K;d>0SSamKL>AfC(ahZpCT???=$1wV6qnq|B6b;sc!3wo$KNXtji zEfRJM=how^+|>xaDq)TxpEh!9KxYgx2#XK(gk_o*uU(<%sfCDa-2{f7)c4V~<6M zejdv+xEg*k@R(k*gKOa6h9>RGO9r1p_#ouT@Sovqyv&G`<^)85TALnu9)>f0a-RM> zN*t=GSN#kVM`%5N0@&sb@`S3ds+i4S4>A~`_52B7Y$i_+!2_?mkkixQI831WSs?2i z1ukg-lT-D#NIaSrulhNPC$yeF0gPq`se-9%s(c3fJcAKh&z}IzvPsp$Ox0qOsvRfd z?~$}!DeViCMrb{M0$5y>h)GuRk0@A)!5(2SLhJbxVECrNx}=WTve%8q9A&$nNBL2l zY+qg!2azl&!Aj=j6s{9q(_p}!WgznZ0{I$7kMaZ}{yPxwgx59L8)bQ8 z)1acpMc$mD%Y;Zzi=6WtWqvLwqvMmruYWLzi7?L%0Y!Sx{)6IpO{6%iwxAzy}aX!*sVZkuhW4yv5 zyzvlyyN#bb76Wl({5jkY7Mu7T5(gd9KJDtSU}x*R(w`l-*=oA>`hQ0CVJ_>#H<8f| zgaqd+$+S|gN1yK=tLw^#L);;fKWq#lf5B5UGv?6IsDgVTsw7MGUVt-Fco@XIYARWK z91)B#!Cj@KBaNci@h(8nj-sC3jj-v6->ZGA$&ZI!z6}>2RR1frKEA~?!k=*myAa+U zP<+{z;J@K7XDuV_%q`=JntFX5_zy*VPWa7+oof3%cos!9TJNLaGOc&pcB(=u)}%vO zmJ>eFkmnfBZEA@$_aBy8@=SxfbYc~mNN=E`mHG>)(kz@6y4`^~N!$?;_e8|K5piKe zToe&^Ma10^af=W*Aa)t@ghO6(Xt#)ZX5qAy8T5c zBdmgNMFO#_@H%fe%D6WT=yc?v?t+i6&Qp722Y8s+3xzqG@jw*XS+pE&E=mcbOdOPD zTeLSQ*cR%I^4*Vqy)W%u&zo66_F?yPu>>p(>T{o03fttDTl zSzrn0>4-rd<&QJaP_QKNG`A=u?jvTn> z^J5Xa@Us{u@Ef*OcJ(Q?3<)R=hb5!|Q9I_wSU+Uvx7wUVAUx|G^P_SYg8N8Y5Ztr^ zjl={;(57p`;ssBG!^5Fy+3RtFXW*3BO@+a!*Xlh;di94)i1+3RnV1d+U^<@NPC9&? zl0Z6y#S4BU>EOH6m@jz_1nRmIQDaWzW0geexMQJWTSrp2j_iGPFU?nkIY)D6FNDLy zr~^1~m6AuEy!@zi_w0XDh2ls`?(64cqy+c+gZAJ(Kf;QY>YrZ}bc*3B%$EvMm?H;P zQ-$4mkOh-(J^rZgm)S@w&^AWuAIl!`XR+UhH!hrjbouBc9$D9Dwp!z&~GRg2c_IEFUM(6(`^Oln5H&X2{p=C$qlny(F%U7Q+I9GiURb$K?qZ8aE1Q%9z}ci`IhzQ6hRBd{ z&G%~Sgva>071oJ_yaNEeWwwkoVj@k2C;XSeAN(9YX~)fBv;`{R;gOC+?w}V?p44F< z!d7u#BIWT5aEMy;*n?y|ZTH}%d;bofOj84Gq5x0x-=1v6YlvW!X_I=EMynK8tEOEF zFe!-14Q9IF*LT3$Si$N#O3To;cCzM=E4|Kk^kGrkiJl{Mbi34cHZ9}fi8u0Ay&Q<7 z&`!~h4S=-0O@lODEL?bFdTIm~o5R|S9uUDw9eXcyTu(zmnCMYIhoL$g3mH6dvKZ<| z>@!EDQDt(vN9Rx=lQ_glg`{ezQ>gxmKL$%EzWulb`^b7=_;c7ecg}Gd9*=2P{0b{g zucV|6$h1l-*DFa;+wZVa{!*~ie}y1Up{vrK>^ZFykI7{9uz&s6!0lG-{gcRLT?uQP zQhVgQG1j0?>r5b2LSm}_CJIF&mrX>W=ro}cmG&n8ZzFyZF@8F?$Nx&iPa?)o=l1x2 z7x9yb@zc3I{@+LZBx3w@PT)6M`VZh#1fF@r3sI$%s58PbozW?wrTTSxVXJMe$$Hg4 z0AJVDne_h%qBEIIdcmJSy|fp~xHBbdayYbQR^_s-vJ4kvbHO${n_7n^14e`sRtwOu z^Dl+#*Qm6A#KnrdD@WV-%fa4gti!l7aEHOs*zuhiRu}G!8{>l(+UHD!dOPc{vuVcv zwO#JLW4laqm5>JC(bA)KLo4iPsqvPBwRTiC-D#Y8II~S>x7hNgJ880QUe9Um9WAXY zLJT&AP-3vHYI*7s-FJ1ms%I{ls-9;fud`LnIO3*@pV@?}xyc14)QV0|3oogKm(;?` z%Ghqfe&o?LaOx4wx<%R4BX07?%~W1dd2k5x4phJreA(x(!@ZZf)&&5Za*fu-*l1+n z8}3Q$8&DCd_@=ZsV|Y)X-ppYZnU~YS-fp0wqP7Z3jDdvqPhmv*vP(xD7#o~SFvNDb zX*c%CZQLF0_J&sxLupmxXkLnA7AM%u#-bH8PY)3*^*jEf6fp~P`^O^U8xir%h0;70Q=6xhs=z9|u3YQpD9c$~Mq&xju~4^KoPq zbAQ*zJlKqLCd+PrOR}fDf$Z;4HZ%L(h`=#rMV^cZ?D{M6gNTr%Gn6E8h>t_AfS-RA z8Ro<3`ln5DpE1dO`Xu+6liX)ba<81^K6{cI2X80Df6gTLxs%-IO>(cE&qIp?kcdc0oXN~oD=*fY?80@Zu0+G>VbHBcjl63rcF>r`C zRiizL9_n=JX*%3GHqfMs(kZ6~g+QGZ4;~|oI2gLL)vl4j|8K^agznT`vTO9tjpP7@ z_oF-%xE{?~3s(`+C0!pCoy(#Z7>hs0&qj=j><#S*T_`Ax?LeGI#OaMryI`8YOPu-#v zVt9fDx*ymDSfXXRVpv22HhVxYqh~Dd0h=@1E+*W_?)MkWpF^x~hK4;ruw8v%sR+Z9 z4hUP?HHkR-j6AH?0h?R0iY-$kd4q!OHrD~>7(T4!fN%HR;uzN9fbFq6G28HARSwvm zd&DuU%KG>#o3*un*IY>8k8FN|Zy3UfqmGR8VXz78=%WNPbqk|XV8^OFjV5?RNX6))>!OmGFn6aTt1UvT}!Hf;9 z6YRWmVB3eI2ok3Hxrr*4KzdBORhP%Hn*@936@r;E-z3=8SH}5n7VMg< z;@Eoxd)GVT*e!y+`|7y7TLruJnmFHWf?fBnIQCw_u75YMwiZ)vw+puMTISa=*d2o1 za2>EjR7RTxyYYJRwHf`rPq3Rdk}tyU6l~KCaqKR^ZoV;&-7VOAZi-{?7wnczaqJ$! zZoN5<-7DB_?-9)C^ghAfdrO?}1A^Utt6-*XeNeDFZWGMZt@{Pr{9eI~4n8E<`)()J zZtUR0g57yX9Q%l1cWsVi|0dYo?~7v}73}?Y5}RV=eN3=>?jknTU>_Ik-n)rSGuQ)y z-S>WCS%ZB-un*h=tgX$|k53Br!F!2Ce4i5R{`-hU_2|=rJ@|pRZG1+shdvm`9u(}e z_s6k^1pC~F;@D>e`}~LF*yjX$_#<)b^MZZh-vl$|_OM`&d^C=IL9jO&tB?77dzv2O_W{O97>HwAm)^KtBP!Crhgj(tn8AAcc^ zeOs`fJi;+`G}Ox5yr^IJo?tJ3g;=EfCy8yf zzDg|8>GuU|`I@A~==2AI*<~|n3o)#?ejX3seMzv6AGk$#T2w|q6|D0qV2yJ7nP6R8;@HcAO@Es8 zH?CbtWD)qVZvFpapDZIk%_TYmvOZWTi~y8(F&^c z|1N~%%JP}ym+R=VW~i8(E^`&%uKfd?-e&CF39C6U@-2WPFLRd@tGZ1Ydq*;KSq^8j zCrcUIz7!gslZ+D3Xy$8W~BI;ngS#2VACrEoJ;t;)mGihu9dYo)hAR1Jh;% zZpJxp5nwoL

(VOJ#IvV4f3PfUp&WbtFV|RK;nAQ4;5Y+Q6AqHWjSG93$++My2^L zM2D5nzcPJIlun@kO%z5)CNVl800=v)mJk4hlRy+i)Js4JaEJy72m#==NT?997J3I# zJx1MJO1b`WEOz2!h(dFZ15bw0wzyLmUEDS%ja@pqA~!KCay0m85xfS>MgNE{?*fOH z*G#O1E%x28veJuJd3*i1dU18*%HxXcr444a6zQzO^0BmT`{=3h-t?iM1@77SLY5&+ z+Ls~i!Pj9~vo#J`EA|2#%y_uTFi*&5p>;SwqLPL5Fmslar>v8Osk%>fG1F_3yFW}* zqA#xn8p{J;ZN*%+=H|DOzp$H0RH}8e1d!uIDeRBEi27JQKzL?F36}y5Fs)&B4608p zX%y;JMj&KOGIFyWeiF@z$)|HEO+_DLcOgaL(iKxJ*{#yY?m|4!8g0sTRX@YFM(gh= z<>Jq*@n6F2`OiXs>rC)M+b|0{a%FV4G$zeaY0?_ymDjEOf=;)Nr`+QswO`Q*VZX&aE{yKD zFuIkigs5I=`g%+l-HNi0!ut%QuM*jCgN8SVB{^Vw>C2kj39bxcN#4fnnU*azPHXrBiD&d4(3kR5Z zYir>+9E^nV3q59emx1OOVF2c9E&EfuJrFP``v+x)=)n4xGj>C#KYxJ0}#O+A}0Ic#%G;wLN@HeUV8UxoHU;8zlWeFGexgaS$DBXmJxMY?&dckN@KI?0G;m1b%Q9a9vLZqzc*_{ewa$e# zFGqSDi3jf-l7U$!**7Z2;>ZXvdLw87>06gH?_jwRiToCrR^Y1QB8?>gxloW+4=yZg z%J`dpyncr;7#v$GaNi5}t8jf0^wYS?Sfj8~GVqp+n*-}k@E|mebS+0VD!o}8p3PVA zhPgzp)6*gq*i!imfW6pA4LvcW-p^5;=71AF035HWF7!+ z5;#Kvj<@`~2pq2fhgSaG1o(`RUBu5CWQ=`-?;=I=Mh{IEFyum7tkhcct9I};K4nAm zm#1#@p-NdVm=9LYf1RPd8AxiVEV0B$sSo+F0G5Q_RHmO^fK^kkg7@>w9CVcvwbj~8 z9>8WYSPT}71%i#d|H25Ab&#i!68Y>kj=r%?kadtzQ~@;TPJr*wbAG3U)DQhO6|6OC zL-4{g2rZ1x+YMo~IT_kXNVW$Uog$K@n&#foFMPRk`!OeI0J`^BKh^riH*`~ODJEWPX zu>^%x_wm~gTn%!Psm;ovUj;^+^a|S~c<~+8GJjw#KvY>gT%87z%xu3jqs2w%ggK6#RCd+a>vKgkg#3=cGhGW z-O7Il{7i;_4l09Jl_lk|d0A$}%k#0qD38OJQ94#G8EgPB*v(LyBAIW8^1kZ4@>Ir- z7b))or#x|+k3ZqNBMHJ2Nx;j}<}{;NiA+2GH2j)4R|$~CZ!DjVbvc5Z&3vZ4yguQ} z0l+j|(VaA}K69V!M||>yrqwEQnFg84j~y?aILL00)IZ1`klX6r;WNKcdJ0`*i;{3g z3E_S6C1WN=g52{kCnEs~3f9CrJOT=hcQzWE>JUn*vKO$v6{gS2gU9nbp_(D-D=_}2 zniw}8CBi9psT;O@LuMsp;Ter(;wNoDCK*)0k_;}uua7hDji=S62}lO@ZE&_3c{xCw zlvW`bTr!DA7l$Q*Be$S_DoZ5gvH>btj~vT7XhO&x&Y24+{O1$F^G98@sSTgc(`g zkcC%u#J?wGd;O6c@=@N&x8^6@8K^`W|r3Jdu{c>MyG<;rzkll28I{#>TDDr=*HODT~#?x z=A}6IU&F)Q@+MOAwDaufOIY}rwFYd}j!!x(QXL4n3fsXJDs}2g@-J+ZAkfjd)b1heHAU!-Us|=a5fY1BrYm zco<31gkaGhAvJ+$M_Gpyfr4FqaJBUP7_{11br8$SSrr2fi9XA%tlsK!(#!p;N5FS3 z%K{w@A_@M ztZInn^5)rEzeEoY9{P}>$t_kk+*%4#aV*5_NzW7UG0=8=A)7Mw`Hh))@esbiN}zSC zcM|-o*yQwrSMY-*v5ss;$TagIUuaA#vpQs`6#?&}R&^joarzjr%%gSoD3RbTXy!#d zbu8GREXjJQOe=qj@G_b;0`;a-&bi2+Y!|8y@BvgaeLesll1`i7IkCDGAHWU~1&6tUgFa*-!>U zcooQIM!cSrs~?Bv2HIsWwY9B$sDx%1W966(`nx01c!jo$CyPD}?oJP5+p~f74YM1- zW13md--9{k*eius@BbG{Kx0mhd;-lE7DM)xjI(_~b(#20%B=u~r{iaRJHmT6Vjg9m z&mVb{;d-q1Aq`hT+f5%@AII}Iw8&dVvrc@_DEm{G-B?}ly$yF-HtE^s`UKp6$CZSe z-8=nwJp=j=xEA6v3E!<0_-k!X)tBNJhr?cR_A?lS?aYN%=UHyy6P0w|Ijs ztW%gOcQ@W{HNrRPww7%FDg<7sfh)314~zmQK)MtVn_WsHEn#Kf0AZ+$>p8hJ;Uif$ z5a$dM_>H8OD19C2qlMPM{@yGNydB|c_%s|8>!X00K9OS{Kz|?OBaS`AAqI+jW%mbusdt%0cv}WJonUeVUR6;4Cw?{QX0!x+od%yGe>4= z_^{jSur3bnF-^9-)aLfqX5sT~V)EwatcytltptSGuv^9Qv0G)@aQ|#*!`~0-7Mm?Y zIhOjY#YnD??~A`-lMXLC!CZxf( zhH>v@8hZU~FjxyHiQ!uncNrEXgt?-=7m9D3|5C%>7_?2`Uk_i5 z->@cPdU%J8-CEYvogf$*V^Y%9>E4g zAaAL5P=l!gP42~j9Y?KJ3`4PKg9qLBcA(G@L@Ccvu9I zbbQ;7Ip90^y(y;LE-#|Urnu7nwi$y< z320g8(ax+zepLis?lT%`QUWndC z{9X8B&dbrI3?_Ycm7U2+-*xXu6~VU#Z{L7b;yo5zG?j@@M@ouZ3;VLkve*ZAwoa0j z$hHPtobF6_q+@|;Yg#8_sgZ8FGb+UBEAw79BXh;hwvM)#1PHLS)RQCKTiJ54-8vO0 z`YrTX944ksw}HlrPH!xbxxMrOnIt=rE=tk5&S!-eBBkb4Q?7q797)rkq`*gprrjp^ z?J|B7(DW&+e{3>Lzk+JO+Q_aZgMi7Le+b0MTxJi1o6c|(8xE%n3&P7u9Bm2OTM4(C#sML?kW-i@^>#+H2H{f& z7@p83&06K8=DjoFV2rIL;bF1)_lQNK$|4L}9U7GaaC5ah?IlJ|W}kw?25g~tXIs;ZIkf8U73c zHO4D4MvD+6ZKGXdS+4#X;(ODp1W zd*IZS+in&G6U95zQ94xJ{Rlw!va{(!ZSYPd@XqY>&TR9}-15#$;_jc$+NWd6LBw@2 z>X35*vo(ZXggBMbAMP#pLTk7{iFAme2{;RxaJdp~;rU9mhnFic zCETRM)bL&uOqC3PE1HF2} zqm<|k$Cc>A(_!K@BfL_Hnc=NU^oJi-q7Z&TiDLL&C3Xs5P-0g28zpuQ|Ek15=y)P< zc9>COPS~l0AL5z;ro?1Ec~<* zhlh_T@wV_;B^HOjQR0a3H6@M=GbxGvsBoqdM~AyBaZHFenlWKZLYzh?acp>o5^oPL zQR2ApIwg(|?^5D~@RLfM7=B%elfq||sD!^#Vl4cF5=+CsDsgi7FC|V16Ri^0sbQxQ z?+E*p7!P+I7O=t-l)i>^RcQ<$tZ2{^D(qx5wN@JzT3g;+|(HYX9^d{0rD2;KN6^<+Y9@15%F^;mrYm~;A z%nIM9G*|7yPb&Rh(vK;9JLzYY<~%=qMQO}Wtngn-WBh4_o$Zq5J4p{H&E=vHQzYhv z1H14jrQc6_xzhKLzCh`FNxxg^`$*rV^an^ksPqR(KcV#fq<^OLgQWkW^h2aGQzYKc zlHOVA&ygNhn(MmZaY{c-`W&S>{|v8G`VrFaQ~FWT4=Vi_>2E3hIO!LZev0((mEJ=7 zA4)$>Ix|($^9<=erGH3zSEZjNJ)-oFNS~nebEMBu`gzhdrC%U@ozgFozE|lVlm4{Q zKOy}srC%bA*HN)7eoFckrGG~HHKkuB-8xNp{zf{l^lPN&DE)WR2P*v!(uXO{SzCCL z(*GiTmeN~EU!*h#b>THibG#J3PidZz3O}Ya4%I`?N;{;#sI*J^38is97xh$W9EpVu zD9zR7@b^mNY^xQ%u5_AoCM)^E;a1dNrTIKVIG{8Z!mV&`rLq2vvQU~6)bI$Uag@~x zPgNQxTCEVDlB7O6NnfKhSGB|UDLtL^hn3Ee{=CvWD-~{0x|{S%O7jF+_y?u23u=Xb zRT}3)&?a<9TsRqmx~4Q1aA7~BH*k;|dnT+(CkBe=^3FlJ5CG1L03iUZjsPJ51Q8$v zfHe^y1c37+KnMU~1PB2@qGz-b;o~@($61G~Zz9@9-z^mU3OinIQ!^5uUZvrW&Z+IqhJs|&1dTvn0_mRE~v?B+E5cDo0 zm(!Q?cbo5Y2l~aNjLpv1=5cN%}b~yA1V%$(*0T@fpK1;rxv4)fu^$<4dra z{s9Dm31o4u#V#xhu-PInys{~&WMi@#%mL*1??Gg=0^f&I<_nIz4^Lsk*d>e1JIP4m=I9?+iILg$u68K;OsKE^fLk25{uc^$ZxS2)>vERn5r)Nit`LZzuW2# znqqx`xWdUA2Tu15lGC``U=At&CfY+U^p+ar1hkQ$D7mw3|Gi+*w-AqfjpiJsnd@J! zwE>~lvpz-n5Q>TUD zSrx3@c^)1oq#pTESowNut7kSPlVT4nX4GZa!yb)>Su`s)aja_}D|_vZjdvllB?J;R z*!X${+dxdYT9eyBTV-(>ZIdVzr!S@{13vd{YZPO^dqAEREY{=?UmTDN4^;^ za9|Lw_oo6JX~EHP6FgE^E7H#svnizCk#BZQXWX*+G@+9~$-)QQV$VUKUHu+5j)Ogs z1=a7!FChc(DXg&rly?N`i|T_P@RLHA0i!A!Pb|!O{)dnjDGS>gh19Dg&MoE}F}nc4 zt`*jTcnlX$8{pF#{M8Seuwtj8560{bo{^^zw|@;Lr6+X7u6HaBIJ0kGfOz;9&o9%JNBh-*gEfP*;7~G{2m97c zsB+Fg|0w0v_$G=g=e#hN#5-LnrK_aR+QK&S{zs7s^VBKr!?kV)2j-e6Bb+he@mE$Z z&&ef()hW!?$6EEZ@#g(GZ6iNOARIqo8?1i)mNvZU}0p0QB#y)V9L_F=d z*nGtQSX)rpu#Y}-cqiP;9MwC8k}9aod4^M%ZCrl?gT3}+_(AJ%8X_BHyiRxo1~Zy@ zIUDE{PSybVHW_(1(bLFkOu-6-9Qh4xws5MEe78t`5|Yv0vEAu(8&YscURug*LLY8! zh~q(_;HxN6J_90(#*M9%jHq}RUV62LpseTQb7CY79}_=bX^clraOMJ^g@C+~O%oCa z9ayE(Pqi$y9mI~Yj5a0Kpok2G$3h8OK~wN^#KLnWj?{IBr1`x4yHF8v)bHK6aU4&l z%vOW|ARZjp3xV&z@IEu|Z$&ZTvHi&H_?TJZgYpa>F?CO3>W(wXMC2>b4?fX@DG4cj zZ5}6JBpFwjySN#<5co<=l!3;~VnE(8FNk&jrTUZh$y6#rL78Yg_?!JYeneub);`L z&L3l55_LF@ZzP=nS(tiYe^`Y41N`RD5=p7+==$ViT6~TMqbYXapMpgF09B03JP`9~ z_{lc~b1XCFkxlc2y1=ot9(2Q*_*a-yEEtG&7U2`O$VVsI;2li^a_hH1HQP72Un1!{ zG&v}hAw{V|gbIiPMR%$;tv;xTWRlu9#P-kjnPu7Fdh@*fmU;UO&VaBU+0KOa8wZ&~Mn@NflhdD)R&fVu|`aEBNDMrX{$_)hp0@$o}lAtFy9c+3BfZ| z7{wN{5~$DttuU=LJZ+2KxNiTB_J4)l)ukrw)Gx$g9Wna8ShoWsC61GGa+k6w^=bnV zVf@_TWK4`CVqiDhkRUx?IWrbdA4m-J?QI#PJMo9;NO`f2N?Ypqt_X8{2X`m92g%X}OQq|r z2(I5)ScWi|yCeP&f(h}<;5PUWL$E3K|HKKAH^_bki;_tMbb|Zn+XV#emN)`DN{%V2 z416(+2p$JRfLCncGt1*Yo0nDzu%keEAL#}pVn^I27lDV}0R z*!yDM#1wUc-41@(M4xS1$Hhk}$8c>%U+BlPeH)j26=%?Qf#RMHT6@~u`sjbz9PCR;zwDid|KUbGk6pCWQ=O<<}3mp6f|0GBm^ z4g!9g{I=uQ*ugmDVLub)^cv1ns)p>~pL`k$!;Lb0G2GZs*9)FTFv&+Mcm|{-D;4~( zi9Q>lW+;L)i|LUsasA>QcJQZ&&kkOV_=rCNn=;z@Hb{}GddHZQ&srdD(KmS4XnMYg zwgKxGxA75C>NOSI4$`D&BT<%9D!2h;Q-i5s6WqD^8sg?=2%Hs&w-HS+r-`;SP${RB zBq0@W0E@}%8IfhT24_W<-5Q+JM9*!Y@w6YvGFa9~`xp{*sHFWlh-KR6YuZ1hIz?j| z=>pF&MLI5Qiz{IZEN+#q})|isPsF%bhe# zaG{WG8n-u|=-_%sITX+{lz2YoYN9eXqGsPqedyDC2lG&?C#P1; z=}~h!SU>!RR-k}P@oR+=-nNR{4NucGAsl6`e`!f(l>28xE zD2eaY`9G|k2b^71wf}Fa!dF-``sMoO|xfgjYWQ`F!S{z1LoQ?X}z5 zYqz!SHjUhdXefT6M%NtY3FP5FcB-?)yh`VxY79B$B6T4*F z^j>VZSF4VZ-3~`?Yar?rfMwGv>Lo39l?>>;44G9;e@Hg8-TG6$DN9_TtYWp#%FD^m zSbGCWQ_@auBc5n{(z2+$T?(34!a^@U-4s;Um~60;&WfelL;DqQrDed7yp+xCmB0#! z)U}Lrc|b-6%*f6h{~v^0%KUJ`^VOAliPK^LR|)@m}NcIn)~E zu8+!H?RR7#8gHcg$fd*Ms@L^eg4gnCBWiPwkZTB2j4BmEe@5s8&V4p1&q8TGMOB44 z6W!)K0V=-w-BH!liTLpTh?AS>7G@Gf30cl~=}&atO395hhntHVonzrSdnf+kW`y@R zyy+T9ceSWF%!7e`2bf(i3>$F^;&>3Ox|0pdtz^}|BnMupvIzGL#wX)+EkwM+#}#++ z0xt?L2ycez2@qpG076w=#`@|7d|zd>)XT3tLOpvWKTYrUiCwiG#A+A9u(~DYey5E_ z3mf%&uWP{Bz1OX|=)y*Q8IJKqaxIr@*+mzQR2%gbo5?*FIht5b@BwD-Z~G*|GmhTs z5|L^zTZg-KF+P()Ydyr=`zl0y$GRt6dA0aX4VQunqM5eR#-TQ@>Rx8P?{|xpS&=F# z1xxQ-2NW~uS@!z`{Vwy?>KrB4zKIsX1t&3DAA}F;0?S(W-snkd9*Hj^*>sxNw^;gg z1zUf!G2j4DUZb>EUtkLi8dW7+=KC)e1_)P~?alXAD>Gx$%1qV=9zdalo=INq_=>fS z^T5AtclgpB;`XVk+?ZJH({Sky>Im>!l+<689z_nU6ukjciki`QNyHiFgJlpwd|gJA z*Y?U&)fUQge80ZpYoAUcU4@78Y@Z>({s6*M1IeN#O^SVQQXdN6g;ArP9tOZww+;8e z2g`U~0RHKSDob?}OgXcI;myGe_z%M4a&i-t|4n?V(9R@fn|P01%ecdFlIpGcVw!={ z7~5<>`VF4+EKuce4Bvl7J+8b?wAlEtzU#x1cY&t2eXdoj*>h_)X>X;Gy7Xnq;>R>z zTVBKxfZDaKDCX{06~)uYQe~uJh87wTL%n2SdL%zt2E7K$8V|wKy@BCZo(=N62v6t_ zYL8qHP7ha%4=Dz1FgA2JIc#eq#L1P&QC#Ak)QOVwTXewGi@J*0V6P4gOx87!oFZQ6^7K{ZkEfCcNhW`&Mz9-KN{ z2C*PYaJML@&e=FF$=Z~peCOcHF2_@jnr#L; znd1g5r=apuUwLCu_8p~`_mw^S`^pyRAZmnRqUJy=kE>`p8XqNT86Ul$j3hiQZPpCV z6-(#wQ%IiAs;?YM<9HVNwd=MfhxUOQ6N5ha8)y4c=`1{{EwkJcr$-ZqIr*$M9-DB} z#+Q{CQa#Uu0lap`vUfn_+HX*aU16Bqk4)|(L`nA;XqPBF|I#L%|2So`mL5kK6E`gz zR`ob))8*@0LStV67K`;(y|*nIr;lOaG}gnJ1*sr!BlpFP@Ew3mr#|0(pz>xU#Pzm@Z2_PfxZY z%ihIju-5C*Cf#cjL|$2{fEsTEMC~_$YqD@D!7NtL9!~@0wIhl6U`o-;uv)nk92)by zIIgojLWQ7F^a31Qz%+@?V5+f9gXzu*%Jqr*ap|o?O~t4xdy*mHjMaTJGh}slHnHES zbiJP)(CcTY#hUe@sN~%6bFmw=~FT;w)Jj4C*~n*_I>}tbI`_@6igNlD#%KPEr)httbMt zzBxS;cCtt1L^J;v{5 z_$rMpp`JR(|7wEyy+@Pnps>Z+j}da|Im%MqmIrGgB-D$=$sR)tP7z^V_iQk;7m{V^ zAp^Gd1wUb}r)ugx^E9#Oi#4%5#f>r82QzY36Q2jvMq_)7TQs7|&q01KG)Cc58!i|{ z+H#CETPdX|3WahixBjIg>VHM}&)u5XsL=HNpZ?Fr-=Dbpx3%W6=9Hw>vZgIOtY}Uh zfp1OI?1iKkQzlKncf5_|iYWWOY;CC|QRG+J=16AC=QSeLZTY;ZrNYp*{oeQctn91@ zsHF3;cy)jOlA6j`EQ~_!4`XnZ>*CUPMh0qjtmmsq{r3=uO&jop& zwsFwxwy_j>YkXOVw*b}G9KIEv^Sx+ZzJ>9B3!Orpbult-0$Pg8*ARqkpT^^h$Cm_k+s1@meLSkKKDecM zpY`z}%kMmKygvR#^$}_}I~-btRDZncroTSM{#W&Jk?P~J`>K!2DV5vj)`t!5GCQvE zoed8OUrqSeTu@pW!y3{=uxB?j*ieD)?_3=g1lF9Y)iRsmRr&g1)W=KzjO3M8v zUKRQlL;Td>T==&I|2>gr;ol?px61Ix8l8v1|J29l!p|0**$=1Gue4;Pl7=2Oy$Eb~g;#DGt>LsP|cZ08yS>$q&?eYlR(Fq*>~c~WT)be{=)+KEvr`QJHrz1e?(n2(dElIq9cH_r0C)CU47 z_EN8WE$pRNke<&77ZX@VL_CIM+8w}MA%q=1+v>D^LWYY~Yw~Vqa`cfzq=ll_YQ1EZ zUV9~kdZSYp-(a+=EcB$%E`b8e9j4{hH`mf9!b0DW^IZy}R%o8Akme;{(mYqW=6N@y zy24<5uWBv7@(Flr|AvCeH-@^eCz!QK4O!VA2*};PbGI$9>Zq9sxuhiIs)_XrpDZys zNx6#1(puv7J8MbW#_#Qe>lRRBnZ=ZR1c6>TqbXMxGKooNgx9e3XX8_1=96k$Yxa!F z%6>C!rHED5!1T#y%Juc?=CSQzXXn!*+@Q6cXGD_OK}PlS39#ycYO>iE%)V|ty^%eE zXu}w-Wq;MrTYx8ikG@(hkBI6+N~TYDuV(LoefS>GUA4-m#COULNLd%l*MMkSwg$AF zn(tc{>sUzkufWy$ckm5sSVvMwK%NG~_ApCxWx!7dOzt#SZZGCAiTZh>a~73Pix2Oc zqMi56RsCbmGl)pv6h?iJ+g^x)Uf*2fU2-5w_aZx3d1p_{G}0PYEhS+mz)pOEzYM3q zKLw)xJ6vl&Q!GD=AJ!(6(tnbx^_t)_jw)$RArhv1DxJv&whu zHJ7xXBi6l~YOU=^>*~;AT?^Qo?2U1KNRqjlJr^uEu8wUQ!_TFm#n{49Yvu;1K2tO- z!1eUE)YxIF5f+V9dxzC=*H9a;hQi_)3Pu?UQ+o=lpGlul_(tjO>>7R8gE&D$@Tv(e1(mMd({_aEtDu~zEE-;40!!B z#D{gH9ew3>!fwjzGVnhqe$#pIt-PK`z1o`6HEKw``OaR%oVBK8OS|Wi6+KbWTUgQ@ zBGg=l%@$i&Qd^b$`+TpgI9^bc)$)1DO5v2%5yT2}m&s_guYZ;nFq6`3ioXQzem?>4_>+&br*J#i?wP5iQpZ*dMQaL41#EIa8gWHzQoaoL}og%{E3? z7Z)ucY+CQG;0F5CEhbv81fG3i&N|0U87%!loCIJY5oi1W*2d125c^HFfYG!@G|y9s`y zX;p%|tJ4oJ+{v^we}^}xA5pkhPOmH6>!#1bJ#`*GVOwW#>U8&L>2+}GDEFLXo{?P{D_@4k@_uieVQol@-HK`Z z4bO&<>%a#9f}_x%t?M@dl&I-7xhinFV#Rfotvc3!!cB!Anv-7qUP-+t{e#bF462; zcjOLpv(z4|?J5m@D5=)7cR(#~V;U~LVtKy~XkI!8&C2_=gi-DqauUBvF@)2xlkEOr zD}&NSUk?1MmOl&~tR-5m53Mu_Fl$kk(>GE$dTm!tCvUr&b-Fv5o+#WaT`^e$fKFRa zxg(T#r!wyg%xePiWKF3WirFj`8gJLBZ%Zovhxm+r2PIc;2ak4o9SZk27uBz@L3+dm+>$mo&-C&RVdkp09+wm-*bsO~`=?3ALJ*X91C z^L3?@ODy#wo#IemkJz=bc~C!#w|hl&T0OyBnlg+xea=8PkGeuZr%iNEv+@n4lX|^t zza?OzqT0TVE(j0WUAkKKSY}^s-2@w|8^nGbuV$Bs?KZRJHMv$PEtJZ#ibUw&Vx2qB z+P7h^Rg&PAvVNg8d}>AQ$LF8l6ko369^A_kduV-o7&{T0=(xf#9rqw5W|N1zn1GHI zO0GIlZ~plLVrAFm5?AVt%|ES8?1aMIRwgebPKkrqrqF1z*Avm#%6~__BZzImRV+A) z-di$F{|3Hvz&)nbWoqM#gPDj`-gq?xAo);QUj&{V2ufc>k_J-LJcOHtCf}-dSAT(c zW8X6wyI^cn6&l#W#-IoIy0y+oW#_v}bD3(`hu{GP5&Bf%_mEzp232(kRrL*^lvGtA zS)VTJ_2|U8jG#1*q~GsOufGxYzGY=OH%`#&vGmZJ1^N=*Ta|}gmw$=M5H-)nmSsVC zkH(wk>d8rVQ>}_+2fWdK3_N8oC8nwBTLZ1jHh!R_+hCZEj?L96D|yKS-l2ovZ;Ri! za{@WfH*l^}A-fbkOyVTYE+I0PjO}#xLe&A6w{;Xcdmm+!WS{4EJrz~qs;DCKbe;R^ z@s+2lom_buzu5;sqaXTNn0u72H>C#4y`Jw}RhF+PCr1DS$7lEbKtb-1DD4w`WNsoCB>b8L2NB zX)La}p24Ba31aVKE86a!oYtuVcker`MY^fA{OF0s*OJ?jhCO#xgMuayEXttAH%IE) z6VihSn4WHrF;I>S4G%RkEDa~aLmVc&pF8T=ggHhAhX*H!uy5V3ioTbnsTwAy{|#E! zUXl$h+KJ6gf`~lR1X5X|0nSE@*+nkfrXdRXC_KX#}E=C1~p?CN~s)?5G{!Nt@ z)lAKG3ssW^-ijR02L+DT z_?Qs7r6G!*7O#w+X$6y^^9H>dtS?1X>t^W=Y8JZ(ND8i3q;DZHj*6&rbzd!z&$qg- z!Yw<&LhH5l))j;sNGeq4Co zKUTVaKP$;}ziQBGWscpLc!Qn@^myc{@)O0gGHJ%yUzLt5!TV$@nqTr}3RS4kY+~D=eq~&d*?NEc>dBjAdvmw2m_=i&pz{{Az30 zr%EA6_Nj8T^B8e*w;B}gcdAUvBtx_x(0b>C|JvZ*CVznhYejk2eVb7l^Cp+NFMWox zG`wrU!g3N4e`ckMvzBU$spi@Zd&HCWXxT(Q>hf~%48Z7{!O1T6447N9tsMU3l6zap zeYv^g^kd@9=ia}hbboIBO1#O+|Fb}flVZm^dz$+E*A(_7c##+EC5(rdsw_%Eo%Xj^bJGcZ7v;b~W_8l+6G}!*yRzLF?@HAn5Qw+-Sc9 zaj|y9Eq8G7rRon;+B2T&%{3ExC|6z`3)CUrM9;~e9NOBrY~yz%prplr)QiCM_!Hrm z7E2+s8qM9Ez(LY}GqJnugzCtfG8K2^iP#r<8;E8MBYnRr;w>PCb8p{J3Qv!-d#SJR zw1^oQN^e(+r2Jt^S^aJ$Bx%>$gSB$34x}F>&~{qmjlU8h4!jAXyU&b+zD7dU^MESffe&T{mREww<}4z;9b|lV(_EW zxt0A^a=5m6Mi@_Hz1ym_M&$8x)NYccn>1i!p-d`U%OB{Bx4(^80dnuPpH`DW2&r2l zrfrtn*eNKTRHgDXxqVd=*{^l+xaP6dR%5%nMIvnN&0n~2Y)8w+S8W;vi!P>eGRoJ8 zGA9oCjnj`P)5a!#(LJ5-ugQx?Zz5bqO{vpd+$Kd5WnSE^cxEs3)|rF&Ntd%aYo-#S z^b^oj<$lt>i8n8e+vrDTYXRBHfj3pNC?3GS)J8Qb=7^PJ_&u%)eb zK-|v&wQ^`}IYy#HZ9sp2=U;h$s(sf?zrem@(;wqI#XZnU`zMq#8~R!ralO`wb$>4b z+y@pf-9O9^{;&DLe+0}-<}akdbg)PRo$<4z*Zmv8jaK{b1nU}vg{$^7v{-8Y=#kCg z%4zrSz=yHyu>d85!Mqd`kHy?2jDc4Bx1!CkClM|kk(uKksR}i$Ww0(SS$!J|ge{YyFIujXOa`$MR6x7&n7@s+GgDmx(hpQ;<1#rQ1cI)7$m5kdLW zKRyv*z0ueXGYwn7ZKYp;(Q@>%JJ~$8!__7{MJs5o(n#`HgWfIB| zW@eY7?KBf7{A&?@w+IVl@Qm)g4hu!1gP^oM@WOj@)S+eO{L7iWhuFry6HlvjeV?=K zLz2HYo`kq|y+%=bd%zn254s9UuvKTAxq@R(Gjb9yKt7;kZk=TlLn^Z=#_+%Gq zLizjSd}h^$X|jrco3;Yn+!X0cex1(u5b>3MnMU9p#R|;)c|}??Xo5P!4C@KjduAS@ zHKz0q3e8P&{E52Ldf6S&!L*P!=wSB;qj_dd3;REAbWX?AIaOwjX!&T$IOhfn)s~iX zxIG5YwT6`=jm<*hPS0GVWwVgD_|!vUPg)dLq$q|7_P>G`(?UgJ0cA};%9=7t;Aec1 z&-5p4+5FPl zjl$NN_2J1}W$fA@A-iEVPUI1#clF{aXm&iolGaRNiiyQi8Jg6RCw9{Q$OrS0ZgM{E zTHsjsPlCd&E-u@csvDTRoJ5llRh9X!44tCf`w_-sH_$ zGM9hG2?*wt>k&0QwHn*Qu$?{V0JbZj!nB-VdY~6ZKF;?XIi#Nx=>{HPa?BOl1}`%-QIGnH4i8y1aPwNkM~w>WzO^qDqn-<#sM*3bmd z{-9ceKnBkkGO%!UtdCnuS}Zqae}pXU+u}#mn;T_aA7w+tpZMoLD-{MPz=NWXG)pjR zvh3Q&v1--*5X3_O^?f@&#yh`DM^!Q&eHf6g$15mQ*hdt{0vN^xU)$v9m>fxbtEdJ- zWK;cme-%NA*0OUg=|F-4^(5@hGrQFC!6EE^RIW3l&d2zUMxBrI;k{3FhMBl(yo~x; z&MHq@afsX6$Wq1pq+-4{ylqJP{}g^LRbnJJyPnF)L;UeW#rU*hIKLW;m3QXhCy8~& zOahag%+OYLUP@(;4`zpnR$su&2=FBOz&GY#KQP_-ETlHRUUPX8{hTGLGPw5q;J|=MfeLSvHX-3~)RzDyt+4&Ul{X?8NgC+2f<_G^+U@;iV>L>V%vid2W zysVDzrFn>#)z1h`cCzrivh!lv=d!%|OYoNf_vRAFe;I(il2G&(wOf?4JU=Ho?OAEP;Oocr0h71ZSv-#6pf?a`lP?*M|o$6@%`-!dwD;3-n=i%6P%TI4#~`wA0{Yf=l*rdy>TMB11I{V zzYCoFUSF44$Mty8Oo7H(s!P@J@;u2BTyvQY= zkAx;Wcc>ozgfp*)68O)6SLCde;C~T%DffTHU#bU1gB5+!zwx7b_`AOIw}*calpyUo)OY31cT zSAH)fG}+0r>B`O?IP*M}zBvZ61ddlhw&Hkdoi9o&AIx>2%*W&=PAu4q7nwR z5_l^< zeF-j+=kUOcNqm!eBx}w5KHGR{@at>ip@ZCK+)}~!#a*sUd*6C;FRv){>K`izOm?#T zy|S|sXI}0l@G8J-@~oENtA!rgKnc7C@OWSU9|vMjG`QFoJ?cZBbb_Bk;J}dbcUIt$ zGiOY)s@+MZ3Fxi!j{*Om!_tprv(NtG=*qnTclO~YB;$bl3E=J10a%;t2XNfJ zAF%IiKq`O>Yp1cF0II<}*_HraypFLh2dKdI#}n%GCvY2N-dAu^rw0(2?1aOWodXpq z^raH`p!vb9M9qi&fce1(3mgWV672^H>^UiOa)`j8xs>4?a=gz+(yfB*6X5oD5{+^?{j^9`}FN)qSiES?%fSyH(^) zfq~E`=H~xY0+XHe?UkL=aOQoY1U`L!@EL%|hjRH>!aq~^Dwx3GS@?_mmvoZ2g`{$qJ!k&4L|6Or7Y2`>vA3(&$9FYd5$p8iu6Ev zjx^7z^dNbTGS8ay{_-4c9*#;rK)z$#*GvzV?^yQ@ri@1Gy2rV1C_O~JlW@~H7 z)EMu5c2tFNb|O_pP-hJzJaXF1{&rN4Jb>y!X-sV7vjxTN9gt2h(_-I=QTjx_o`{T7 zhrOMcHv4C_+0k?ZQMvIQIM%t#^zmwsS~Cm4FOUsR_h^wVN@t9oW$zB)0eX24Y8Lbz zmp2_q+i=a=zC)kfgWlbvaD|}hmHgHYV{?pWf6PdJO^Mdh*9qzpWI;EUW}cKSJ#8VU(fjZ&0>TD}PaWIJ3$y8{>MUY*40?H&RB}RLnRO4;R>L zO0sik0CxuW=8}6$$$hT7xiP~^a>gBxB+bNiEyGTg7c=h3+}%D8{I2wJs% zZoI<-EO9sN*loIvq(%}u!I+J)B9ATGb7(muwc2Qoq86g_&B{*u5hRjbz|W)~L^i%R zZrA9RpEsb>bKU?c*|hfJXO5zdgxxIb!jh?jm2bl4-+Fnp#{;ABeYC`G*?XI3@BXw= zvS%f0U0@J6=T#|DJKE|&BQiPMtF+*@N(*kQwBWW%Yh+ewtod7oHA)rM=v5e{ad=*- z?F&^3kK_lVFcYw`&+ves)V`EVhJtwj{BAs21p|WW@*KXLe#qOM&O=j;E7BuFJ`ulG zjh4>|JS%GDD#$J(Jx}Fwws=A+uTv`aRIa7*1ET$-mxkWDAdNIVDx~p#PvcRLTDZ76 z+Q>eN3?P*c=b~UVeKcW>?Bf8`Y>uI*?d*nH)Uo_eJ({1zw4ZHXm4tXIjiM{XY3fXa zk6U?668ta)KSgck#}ZMrhomdz$R4&_Tpe#Tw!IIO>&kf-*0*O?wcMR%2#?fT~UYr7t#<{5#Gr5;g>RA!N`om-C^_W0LNBdkyPS6~RlqVM*6f|6rnnO_On` z+L0M|W_#gp#n~D@h#A>+!ODwWZSdQnE9|~mT?qvXjZ%sovy~UAT@_(Kt~5HD6%1E> z5~0}wreh{laVo=2dxA2-|D>*w7}Kr%LP?`zlLlR?5}{DF*9QUo4cKF}G6Tt7C~+9g zexJ{8uD5H%2f!$dLx2#?|a`V6}c6 zo0etdXxx9Ldt1@R{xD5M4UcTMbGytuLAPvb?`X#Vc_ovZrT&-&jBPN^ND+r zJJYXf#7xp>DXMgT6kWR?V)Tq(mXX!Gy5ij$et-haOp)f%hHs_z}T(Ss(UvRuDwc-fb^e2GU*m) zcM{p$?Z>MKd16i2v7zb&h>2eBYqRpXAnItYP|YqQqKl%wd@2j%Gb1$5=l`UyUIUNw z_tko3NV0&xsH2HVYzEkOmmlDlk(2Zp&>OYvc-OF-qTYhd*?s~HW>4g2lGjC4l%fA# zOT;*P5;Sti3k>qa6689AlzaUP4N~s)FEPl|O0iyP5PK3Sq;-oyo>jt;rW{0rdE2$Su^maA9@E%=l?#b^!(b+>CCBm|(u?TF;jm%gUm?L=mm5b0>KuKzgR>=f^8FHD zK6moLYR+>Yp|`w?_SfE~vcH@k?xqY(K%#|Zub)84`a7t15z`-T$AV6}69NFgDxh^^ z?nS7e^3kNW@u?=+B^OT;LngDn0(!G#)lQ1>{RrhvH3sAlBkD?xr2QnZ^kjZ=z2YO1 zg)-ysdbjinr~70oXExpa2#q?L0sk+Ee_q7Jv-G^0>S27(^ms~^lN8wusoWWx5z$f} z+D{RiPZgUcL#lRax^DTk@gu?lK1&^@CTm}ZoPLOmV9-9b9@glYD=w3rlY1L4KWw>o zS*3BRVd>;=VdX=u#+Q^aGVi`Nh}cl8HuhrT=`ZSN9U;zc;5ceu-$nSno5&_}+gB)i z9c3@h?13z)ZFW8eG=^OY=2{5kJ@dr|d3g!q{l^~W(rMf%4)$(uGfaDEEA+jafrK)Y z9B*3ruTD?2@{c-NRdF7&qfz$eFRT!MU*Zp1{6#74&+1Q4f9)<(KIS0T^0Bp~x@as- zUkZ2SaW9l-U3Nt6FY0J1CeHp*i~=343B?(kss6(3Xq^3?K;%BZvy1#a(6=IwI$EJ> zU#Wucs^BT;msw$bBOgbBxKP};RM0mX&RGB7$XlR=B>m)EU% zGAFtd6X^vBn)t|7yF~Y1oUgP2{ z$(G`?5j4rhG+n<2-gueDZuz#it2qBv#Yqz}S^EgSds-TLdyOgB^7ItZB?s%312<4u z>Yb}YLOdr19b2+k?Nb7c*f#p+qUvb?Hojlk`E`_KXu>|%HldWo2$J<{NFvG>$~j_A zj^HJBG&{-$aoTgX@Ht>NFQgZ9XiYI=&Qu#k=?(3tE9GbKGg+O0OdVBEt;f`6IfB~! zb(~eB>m9Xf(z=={Q9m+C@QnCWx2zgpIcDgV#*4~s5oH#QFHF&U)UTF%sn8^EC#nmL zp709&Q99DFm9;EgGNhdXL#56bbv6JfiTqOUn^Nz46|_U|W4E-JI7ps-1lo(mQ%5U~ zarX3iI@kLO)}E;XdzK2!bi^?VOi5dT$x)tX*pqZDv^7Y97Z7Uct&oYct4Sb-jup^r z)Xj1UcP*au)rNhQ;Gwg5hrF(g`90d66}pW(l3S=&I_qYwVnvMNX5vRl+hTpywEd0W z3w_1)&k-xz9bUFtqU|eNt#Qv^wshTQ`Wi@wvYqZL+kwg_i?TggM6>NQkv_o{XH{aC zhwZCWz|SrUcnJlp^sRv9=qunI(94T*O;MCjcW6_^K0Z-^pIHVkD!^9(E(-qHctXKH zNAOa?d%qv3+#j+_D6atyYEl!?__FjgZ^{F`&R$(*&00@pHMI(d*cibm(&5BiYGwT^ zqBePD<+WrV`wGXAGbDyo_A%G)W#s7tDjO~QwyzeQ=LI^E)_*FaqO)FWH^n2qx{Pzo zUO?22^mo?(@}C_6`#U0h_1O^q%dnhoj;8Upj3?Y0w|o!dYpX_uIraDD5`#A^H40k+ zw8+8u9?bNnrFr}t85ShkcAI3JZWIQzGJ=MBWJ*-o!IyP^?hhcax!<{b%Q1@p4e+n2 zlRBSjQAMKl3ymV`8&a$_IIZHJfx)g(tqtG3`A$vnv#hnUwW77WwW_tcwWc-RXpJ{p z6+8+mEd_^W3 zR$85WSBgzSg#-f*+kQn`=DhRUK$ac0>;-BUN%lGXHEkQ6NcyoYHLw~&I`7KUac`mC z**x(W2(ME9jb1ZZZR8kRUIb6sOCe2jPz#qWqR-Gov**#-vd<_nUPeOF2+^jFML$wU zSY4vIDyR8lvSLyFzM(o-886O01z8W1Y+R%KU;c1qH%#sln-8>#YvnfMtEI|PFgT+2 zb`^2Qd+D#?GVwDt(y0(@;}aL&g=V#c8|BXza1VfS_5%h#_6y!l28ZZmDpICL%05M* zkL7k@VSjjJsoJ&aul~ zFC|+06V$Kg`5xl1-p06R3~VIeiuiIgakVu`_QbE$*|r}K8URQ?3_+}PX=v?V8ecHI z6@>Z(KarWgG-q{Mg4LYK^l`bfIlVb|E}4En?i`y|RU7U~GazKn*7V{Wy3Wl9X_2DF zN~2weGi67fuaR#0X1LQe-#6&%vVv0%ODxAezR{B^`zX)l)t6?q?BkWWO&ShkTdx_a z+Gk!68C<_|1&jDinASjtXE@(;=;QCJiQ0lB*5i2 zQ8K7?D~VaNSH$i0Z8u+Ii(csTjNn7{QOgu&DU8llqN6Swo7D)D3yz8LabuSVY7~sK z#%9AmarPWyrs~?ceTu^D#K4q#u37Hr$qYlyt;sZe1@2T138?Ji>?6<#tF6jE7dR?w zXSZ21Wng!w_uO)fnhRau{`uISr18)AKheE&e&1b!2$u@5e~cR-6ioTL3Q!FbE8F=_ zv2<98w_QwDu-l$~0v7AuN*YV8m4q!^FA;m$A>Q^yu-Qf)UuyW2LG~5NUX|eZ@RWq= z_+k%InDn&t)5^P*EqeqS+otXUEjCS#JJX)BmJSVDB|e4p2I0+03uSs`NGnM-s+e_z z*xu$DVI7Vg>dyG{fgSHtR_Z4mWs(cF>6pVSMQ2FmN*fOMl_wg-%`L(Qw@`EnttudzhIb z#lB(7*yfvuxgw?qZ5tb3O|qdsjgIW;+jT_U^9IZB@Sfo9IlO1xj6JbtskSjXvMAs+ zh8NwCz6{XtBJdUsFKW0^DD|5M!Na~LH)KePa{LG~rdN((V=%1yswMeIv+<`=VQ-|~ z)W{=NJHE%aSE~TNFMwj8OSw(3BPH8HpEPZO(>mT($8_fA#ng$*IG1Z&p-jK(@vCN= zEj2#>g+`SxW<4G^abz3P7q)zjD#>0!ftSojvRb6Vj>3YMEuzphZvrd5gCs0d9?PGa zzdG1Q(ICwr@78OG!u~a@ZW7wsSJJq#AAIc@r4NUT%WvlVA1h&|d@W6HkbE|Q zEu{m&oinbEsWmJ+W5XLpX2Ru(pC%b2?)+ds%M6>Vo|KOMcFR{`w`E_j0ynpb;GziM zdGNMq0R{RsSTC{=#Q`z>igKiMB+gnY=R$UlP9F-au;U^|TyNqgsfK~lIOW!1>ggw; zX3x9KvGgMCA*%WaeUGrLpeWM+kcR~{m9r|n*Z-pmXY_3D*{6^AEVh`8DykH{$MVm) znaV!=OMgF`|EKbQHUDqo|3m!0oc}NJKXo@hQGDBGdb16cK5mcRWuw>>f?1)+{RIyA zpaV`3;5zElp2z`XivTYafbm#S&K2N#0iNrC6u>2p@??idf~0B`Q;ZghvrYiD7k@M& zzK!LM1?f!!Xm$(6sRF!2fCoC@JON%T0BWo-P8Wa{m{_;1!iL=i7pV2l57|OINm|4wied%<}+ABd6*srw>}LFA`uE-eJS1di*eYoJBb;EdEafT0-OX@#Djfr!&@8Y+2?Dr&>R z;%7vK=1Mv3rgxmsnjY^~WVi217uFsj)ZO2@9H zuONh(bez7P39F@Ua^o5@d7!1&`5iN)^t;52&B<2!EXy^VKVgG&wW&g zinslogof&!zX5VXZ0=6)RYAtvenIfUMn}eKLUi|7^hQUX zEZyLGll$_dQ9L7=s~hOZHjP=SNnb@%uqoE?z?FiguLfXtILyw5*ETW!tT3y3Jb#f# z-9xlwz{abkH5tV&%1W*)kgrG3O%b_l-DxUv7V0z$xP`qJ`OWTwIT)9Z0-gOC=%?(~ zH8oUYs<{tz?##WKNOlxu<|_-Z>vao!x0<7^U>Jn^^IJXG&DfjRPnk>G77BAQi4IJ9 z&SvhR#@u+poczX|ISS@}KbN^4=-ip#8FPwqAIvHEzL@)Qw6x1870#i%O^KODFD(o} z#A{7`owSPTepQ&&F2k+agpk+xHU~xnM2Tgsjv=7w6qwosGE8%TVKLUb2_Gz`L@KDa zMB9JQFx)*C{X;bys5tZ$~gWj$M zqq`QgPK@1NhJh@J)d(Ur!YWziN4QWnz^ zy$63DF@iZDIZNhrO318=hPf@HXRxUw?6vDPW0g&v5;DgzWLQVxi5`M^xKhyEX$(F} zcx+d?o+Fx^=4U@jsPocf+fg(XE<+KqxwMF=QXK1{BW`N8ar~gpbD5H$_qtMBED3qR1Cp3sVno6$# zl~KvbW5mJx;Xn@X^sytf^sDp$bvAqKw|lXI1LGR=2P&wHw)PWs6z0cnZ5G|5vEJ0a z^iaq&qc!$iuo2R{VhzT>6mgVC#+bkrp4T9T-D3sTpYBTZ1XRWf2g2zGs-3~wM7*O? znH~UYN8-}gLZIo+e={c`Y}g|;l(+14z!u)4(aj%4uA7CHZ#P;CXl+{2T6~0WlQ9&S z?#W!U!hvqmQ!V?>pE+A?ikOWhZw}c<$;D*UQ4KFiZzUBo5|+$7ImRZs1tv4qC578D z&5mLoTE-kLW2!azPJa`=XIKV&f}LoNItrODI&TPuM0pm6;y>&JB6_j%w$=vewCn`z z#Rv9P#KH@}X!+#RLoli+&w7gKMh zCU7~~YaYdl$4mlqPSyOb{>{$N63>vy0m+>Qs!hkK%tptS=jzxd8Yrqmwf$yFy~}w~ zUCdr)iOIv$s!QKM$~Cjn?b9baWWmy)6W82F^}u8n;a2^krHhBa__4yk6c3 zc!+$k*I{R-4lxFrx57QwG}DZ)TBlI0b(#af3v+-uOa@*7C63ror%G>p*Cv}$b(HA% zuAp$HS3uAww@aO^rN$Kp2>!xkHQN3Lu+2o+XF+Vgo2IZsAcJS;=y-|V26~U0h~)~; zd*x9ot>1alqh_5R>mtBLHwG0meS)%Ntc@OSYla@at4dv~2YoIC@@Tp`j;Obya;%N6 zS}VX*>!ns8hDTga%;Op}d0Y?hxN?``8lIKi8KkK{Ea89>6mL0gvDfWzs_6RcaB`N* z%j&}_tGBAG1lq2jjNUu19ZsX~Y|2R%jjky!c_nb*$_al&gx@B@0&Uk%2CK5esmLt$ zv>$;KF1)ky@-lEjUgXSfN7nBqFSihG_5RT!F9L1X&#b&$NI7v)gLY>0Juh<3o0r$* zgg++2Z&zLf+OD7MOwWrVlb5J{s%OUiTX%2#^KPE1B~HkjoOYP3lsBEQiR?O!JwZCU zD{jdss?Mv3e;NV&8x7}Q&UyL2l>jT4kBfhW;#VzVwdtm47!|nE#a2rCyVwX(02XI(_UEACoe|d^CIWGdHJ`T@TWxh z-<21Ew(BQDMN!*VWXsDXo)`D`=jA4FLSE#Q?SS3o<#mKxUOrvqMWF5anI|ul3VAX5 zo)DSCBcBWQs%HVX-} zxO0(~%|c?yVJ_10SxC$0Ls~HliIs`Dlvd6{S~(xms#!>@=0jRN3u$#3X@i%`__9z? z=Z1m;FfZB~C)Pt_&7{ZtkvTP1O|0A>QIL~u-yUL~?8NM3C;F1j=}mCsy`LVCGQDFx z;fWozklspyR2~C`l>}3Pa@77s2SXKTUexLwsue)2Q0sFu z3usa;3ex6$Nwpvjd}=#&M#Qg>N6T;|lwD_UAG3o$>kNtUnk;M{{Zu zIW>FgCYqImDW9X#KT*~Xj?%kP&9^bZj-*_s-@?~o9ZwdlPhpS99H-`vLvzQ2b4Qjt z&d43-<&KBvjtg_gBXh?lIo=X2v8iojPq215>B>c5{my(dVq)?;Y3JiBeFk^1hh%pE z)H%EdLchivh6j}puPtVCj&GwTGHZ7 zkS_nEKLyxIwtWnQ;NilRn3v5Ev%|44*@nK%mf7gYz|;eX+~D|<3~^{V$t-Mej)x=u ziLdE2z!=U67iYxWhK62#w51t8ZKXWLm5oF=ia6|P((L^uHjv*x4_Fr&-1l7$@2&ABhMErW7*x7XZ@zVJfCDi zk_X&j=GWJ|A5=hX4a|cqQ#GFcl)&)YbLns9FT4+_@E#i~No`L3dMSC2!kbu_%%BTT zE8C+jujR28D>Yi*WJ&971lq|YPLmgI=h~zA6#`p09?RRomBiIwxWVB^Ff6AYC(6E0 zV|D}bcGS=h9H#87qnKwuP-n2^gY1VrJdUw&=t;jRoB6`CLm!Kkj-7?_6H)1ZDsT+V zHM08NJKw>wO9m(D0k_*kdAZC{s$Ji3F)0uvtm$YF-ed_|g`r|zn6m>t!64E43 zy<(z;QB3+x|DfzeZZW}&={5`0Z~9vcG|?Lb@MEZIRQueb+1n(8b+T+MWn({-Q&PDZ z9(GVp=rurXwVu6RcKgE}Zx-7)fWUs|O_1Y6EbTAqh!&ld2^7|Lk!i6k(=^+khi&cw zrV9YsI2)&&c?dU0!T%UYEX^r-drjPTCSsYdX=Zm3InF+T)6PiX{v__S1}$ycd&sa# zEc=v@5}Yv)ZArx;_|t-UFc)_EgLyIJv%u^OiG~sV#o6bCHi8q*K99Saau_0M+rxu# z_J#RF&s15&*%uY6ZG*nJarPzP?F${pvZ66W3znSFP`ocI9{OGd5a&GvI-GL#Ye&{D zP9SiT#zjA;dKjVP?heJ%YGmxsgVut1oPW~n85L9(Z9`4MJ2`g}A-oQ%_U87Cj({!< zquDg8qgD;g#2z%{f`$rvsAkRFjWwCx)J?6_m_kWk!Qqi$vh z=A<4PbtZdONrqw~0~zY4r<3M0B}c5$TevQ0?GKpy66|U=hvJN3yIIe)!BTn{S0i7w ze#ThKMQX;5q`!(=U2?`KZE?WPTVf_qbz)t^3YbnNkCmY}m2?267A#l-O+I)>csXy`W=_%tqjmfzgq~Ec9TAO;5z$C>3NDwe|vv%Ac)7@JoTzF6Kt*PkFUa z$5p#W_G24|{;s}C)6q^7m$`0qS=!d?Sv^Z2F*Lpl4fPkxsP`9%v~qtLus7|GQTiAp*o`4hHN<#}SI=L5>ck%)9#RhBxmc9l{ zbq!^-!Dbv@7$tv6W>GQ)!x*zCV3!M#+1=qtA96vHhh|bt9`=Jdjg(W8G7O`dJfsW78lI2g z@wtJl2|Bp_L-Kb;Pp2QKyp)*7Ssz8%>_OB*qm-q<*sRx?uu;#PRGZK?F>W;9#AHj2 z9<2>sJ8!XG?708=m)Z_7QiBc8<7tpXh||#x8p9l6v_1+%CPSK>BbUf3387p_{f}jo zq|^UeMpf-D@bOl*)_(nYX`L$P@Ii$`a)tDz6 z85$nq4$8|wH4PWy;eOE`(eNH6Ms!)kpG#f@Tx#*i@bDscEFK*hvD*^Ei=*M;;Sp1; zLti%qV}yi8hKZ1Ugyz5TKafAei&}2uwQA3$my{j{_zQJEBc1H)5+t~Eyy)k&ig;hxwHj4qaNQ1!^1u-99rQape#*(@V&bmaC#?UZ;qV@RIubPWd z=?~}#1#dN%xjryz>S}6OK0oE&uBNFzf*c6fjagUf@+>-;(l{B$6V_NXMcw!b>a=EK zWCoR!ioAQpo(#$raky)p*!Asdx|q_)$Fsx+vcB<5BFV?IIqfMQ%e*;BXSH)rvC^%a zOxoj%+qYA>&7`LwjLFa@fX%tauq*(W5xNSoJOEC~0V@IkP8?%p0I-zefK>s&Sv&`< z4uHuVuqFW3NcL=Mx0WugMrxlQ)06~KdI12-0?*g(%fG}4KIHLi= zNreE(bA53E$+OK^7H~qYc1U?IJq7p<>GIX?JM|gpzDt2?qK=?;^1vJb6m9@>0QmPD zV2&%I&U*m((Rp*4k<3=q$tfz>2$%x`@67?`0PyY{U=DW0M7g{x=Kip{Z^`CJrCl*Y z%6G;3kV?B^hLrD$^&ypZ#SAIm73)JP?TQ&vzAM&;RN56Yq^(W=Q$2SRYbp zSIm&|T`@!2;N{e}E2eX;;kA@?9}QV;9Sz8L6*EMZ;Psu@fqdxgs1%^E`O=4~wWC?60?mtBor?-+UerZ%Q31`1Ix!a&P#Kkd z1j_@^@~&79RxVRExQYPily}AY;r9`#yen3YRP2fgsQri#Sl$&YK;;}1s4R)hE^R>b zqW0~I1**la*enJn=1{Fn^ilP71+Ag#FUT1UBks)3VZfQWkWCF2QYqG@n#dgqEzt%HNL*_j$Y`zYvhHvf!E4!AvHJ)e z;nH`KGQGMwkjCiM3|QX;DVm_fmz2&G5=n5YDRXR(I^O~i&VI_t>g;tCx5Ew5 zpdfy`hbU)(Xdba)4iN9@A<9`Gnn#G{xIOB8M~HjEqdQB-x10rqr>HLe{I9hsRtUqn zEsN}JSI#1pIq>!jEuN;P06V2}cQ08vcXRs1+weZ5_j_x@LY;k1C7gdzknNJHOeZSL z*m@U83Q)KeV#SWoaJb|yf-GUJqy#FX(mJG^_qL<8T&8_$@i$<5;#V7gswR6z+iS{q zE4(g{`WzOvoy2C6V)83o{p6_UcZp@kp020T+do2C+#!&`Gc>++leXRcIPFezyJ>G) zrM0SwF*jFaC$qPzacZ@4ZqN!_7Lep%>d>U_e-Cw5VX7(fhQfa)Z}%vmyM>>)YWK&q zb{SWuVIB5|=Rv48xo@Dh^HZs~H?o9f@q7=X^C{`)b}f8f;-Wp3(_Z4~`n@&GO3x;| zWq!hY^Pb5~5>34wia#lLYj{mrUp4g{@aG(04lw?b1Iz*7uQ|XR0REN(%<=TF3o_dM zJMbudI|+CHA?Ij!moSN;5KGk@02FQja{w?*@s&qm_1!VdvGtBZAGV#5>}M2hiaj%X zGMCbpiKz~=Pmf~`0IVZAz#IUg9AFLraSkxY8=~~twBo3}50l*P0AbN+Xis`+AllA( z?rIkSTV-w)+Z|o1igm9KNHWFUs$#?)>aW^Gipq^#sCJQ{a<7*g`6)O1+12hMchi=t zUB(E#ak8{kDHj8`>d|!BeQ{$fM%1hS_FmNy6E^FgFG~upnplIxX<< z!gNT&M+;+aMZuiq-}%D^3i&r8&YzrlFF=(ECVSpD`$2w$R%cJh#(oWsWH2r88Rib9hJZtSSbd6Ed~TKc=~V{&~}rK zJyEZouQM!PmY(NJ&e{1|lapN~vcC~ofwt=>WnoYGQat7Bx1KNeULAFo0uNb{vot8C zej3!<*cy29@laT6?TvKZF-^lzC}`698qXQ_=*d|+c5Y2&kD_Rn71gM`Qu>uMEw4tv z^D5`;ys}L0MYvjdWgV%xL!j;YNgv^PRXp+FSvj*yiC(I=QX|{9 z;I3B}+zz9S84c%8&e{A;0JDL0jrjYW_!DTmeo}VMRTqk$LV)9j*+HxicNeU zN*>#r*;HUNyvutY)uh_xwU27j(Qo==31aK?wy?$tgecjSYysa|v$bJ{Mc;9+rr$H_ zs$bTBDi0Iwa|7)Or@fca)^C}%_7w)S)i_}E&l7#Lp=L@KT(@@cj9L(-T)a}NvSqjJ zC`e3jqV4D^UNRFZnLnyz1TuJf5d?H!s~7E0AsTv&N83x${;X&MZP!owC`HqL#r@&T z^b%t?9zQ6<8VpNsqZ^p?u}_o!L|Kl~Z}QoOF2efcX6UtETuqlToR$O1_u;GA7GXVq zcUKq_h_~6-Ze9`eKb7a%lxJLANj%7}Bx2@c^v3juB#(hSG*V8PjSbnx9XlR3+9|Dt zjS$cnEDY&<*H$!{g?x#aar!gOLJHq6`+PcY#onx6t9)v4ow)#^;D!5_1&A%)9JDoZ z8$VHodXvP{rJS7|r@tWeDE*>%STdUZSt;3E=yyO$u6H{o>d>!y5vto>NqJYxmTH{B znQ{8d9@>(uS`hnVzw7CaI3HP$1c$#WQ5wy(OX+<5wciDY!kmv(KZi!)YR``!`inNH z+F}}!mqVuIc28tizw7<;MVl{4CqXJIhux$yT+oix6s_3JMJjWn&6|pmAQk0&H>qeD z+-WC8D&``UxzXlL#YkXbrTs&6l(a4~F2DAo*v^rRd3ca9dm~m%fSfM@@)x>v`e=1z z@T50w;=39As3V2Y-nwlD_f4pygH$9+m46U7NezM z-%lHx25=>*RMRf3atTG#F@thQ({|>G84MfNu zLU=vt(%-P^BZ+9^!psg9rAFJj<(Q%B+H)@CrD`^aINL#eNR9SIs$P+#zaeW#Hzv#q z&VGTntJ1?vhYDnSFtBhv)C&U(rSL^))0%zL2y15M1-6W*bG=~ca+Z<%~tJtkjk$rm>ThvQ|- zM?GH=n|?x=n=kc^+4=fZY?+9&f99EpXJ?{n4NuDfHEr*%;c$U6!gv4hJs^A!4BrQa z?``3`U-+IFzSr9~7$Low9w%iaGA$%Kmaw1!7|g5Ogz2F`B?_`< ziKec9-%rh^Y7bf!SS~}T|H=iF6?nsHoe_wRT`GbX2-IH&Hw)BX2yYQ+RXO60!zuY({yvAccA@q6R|4f6 zkO@dXM(@JXpM9G-gX8^vI?Y9>Ju_u@IZDv&BE4RkV|qWDws|8v?v1hVn2HN}$KnN@ zDn2{p8Q~dF#eP-2WrQPfPgV;2@r)$oyvLd|OTgnLtsYd)tY**ydQdsDxh)q~2J?P0iw^`LTQdm5BV$$5}7q&D4y%4z(zUL21d&8|`;8Cb%e^;ZnaKi6&qDx?Z|RH8QKr7w@)xnq(|adjZtQecZ261W=DDxf z`^}0ie-Ya}_Z7P}E4KVaZ1c>HeUZ1;Qh8LfMHD?VF>AZLXg4hHT)b>C@JR)zHTMyC zG()opSU@#o4e)6sxu-d;|t+1UI6 z8B2O_00A}H5&`qhM_^V!AaH8bQR{RY-PLTlQtN|dD=Z;k>PfTldaxdz`qpf`9xUKd zrfUE57M%t3if$HOC^`tJ!_P~=0(t~y;q}U1eJvhKPn8&?B+WbOUe}eMNT=lTxa>nd z|I)E7gHu|t;pu=a%g)=(F|->OdJk`OZeU^APIxyuFTy!ejTcw#Wjr1qu3!y@s1rDH zD1n&Qsct^nLs^1XcW<8%k}hdo!J{3NJA?L7;6?V{c6$|&?$P+!`l_a@OX2-ILwz4(9;~WK%qHH~}PF%T2<54DuKy9d-J`WE z45WKSbHpsd3s1DX)u{y zOKl;-_+Cx;QMMLk30EySW-e=?5ss2BX)z@>b3AeP81Y!`9?M5d+Vbjaez0u$BkmsO zSjUG@d4*;Enc~LB366D=KBL_eg>-fiXwWf-_M((<;o{^#S5RA_HwPCa^|d2uN;M~Z zIaSMZP6VZoVS=c8HsoDpv^U>JS)1tLtTh`dlTmw;f?#b;@pL~ub(B*@hPi~1$!Yvj z9*?q9DnSEMefXTk4!5!H+g6cnKOMNOLOuy^dtb_9hd>6;E~X5~ny7_7HlVxz z_UC2qo0XPO(9WE0v@3bC2r`LiW{-u;WaRaI4`;-%ZD>^$SX1d|%pOqAREPm8XVx;P ziX}khbf`C~d&G;`V#5+*W$odW)82~ecPPD18P0Chd|{F<$H9msLNKQ5L^19%scG6~ zCbOEtF9E~srfHI<-@#d;gA^h;v!J5w0Y+Ea0}Tv0<8mZ@0G`2`AtGiD#<%{*Wij*d zl9(yv%>CBoawaOQ^zXS~*XSpN%=JH-wV2&xigRCp70Jv`3$e2&FR%(V#O1agbEQ2i zOUnMIlSMWVl3?BQb<2vWcD4JTl$iRIeJKkE>oxRj}kt zT2>9ZJ?ea~ z&rc}8`mff%PqLcG3%Ok0I&I79mgQn!s|Gpk{%BYZGrtbtYHy`Ewky(+n^6o$l}aRt zEtSb=`T`0nC#f4`PJPVbZ5=GIb+V%gLJb`@2-k&*bH7Bk1HWARRf_Qz-aW9ZGzm|p zzYU08g3$v8jk;OvPh|A#QH;lS}h+Raa2I_qB5K6oiuS&KxNe3o;1^m}yRk~K75PstW&3P2DGfBB94@zkMFY7ZqHt0J<8l63uIe|)@wB8@K@ z-# z)dC(QaeEA`G99UXiVax! zC2o3Y82O*%erKmGOI=-sJ5*=O6w5V{6@F_+{cA7sausPvEGLB=&{_{{k26@ z-5*4}OBAp3TVT8s6J03>NAFJ}(zYK^r%B4hfCn^d=_!ELf0G*W^EZ=xB&0YnvJq%1AeKl@YG__uAm#uo#3>&$cRCdA7rIgVe>%LW^Vu>$` zA~XuI$2$(BQ(WyYow_*_zO%FVNg1k}Txw;Jfwuy{wg-qJ_W6{}wWGCLW)X=qRx=Y{ zBSU!&H;Li<>*b`hH2bZ7z-}peeIKT4t?s1Vf3h5R=46^noc@W_+7E^2E2P&{D>o5g zD`l}PusX91v|HAW&1~0~$D$qv?%>pB&}!M)xQ7zEulo=HyoRR7zCAO%!#zkTq(|_h z>xt?2l`q5=Z|fuj>0R(LQoBb@EPr@L7yaHxW# z9azOROEp_36MpH}ulFXNmPmyPwnMw67)4v)B^9#TnlC8b0>jz4{PbKy+kZtHI}A}s zgH5qjTS`|jkUB&Yp+$f)Jm>wM<;2DN2~>ebS4NYJ5;QLVALFt2Ru10e@5Lr(0eozBv zb}72-wa_Ph=xQA|(&^JJj@gy0nHwW2MUYohe!7w>(S^cz6P|wY3N^BRM+R>T&*qbH_?G|d zn>>UScgt*B5$afJPWkgc<5f}hZGbo$#OU{bcpKg5n(r?4WHmcHK}|D;+1MX^*}$XO z8QvuvILiS(Uva*Js7>j^7qqNFV;3iK7~GY%qqM}WM@P#!a;EmY#7%>ooYcNokB@Sa z!Srz^<3~u{C|{HKj4~Tc`FdK%wL#QoJg(*8Z>8*M{I`^K*h5Kdp2N|6!SfbnKv$k= zwn{mnQV!1Zj3Le>>7&!sCAo6++Oo;m4Lt79NQkN${nV`LiYr$B%JLf83AjS4RBr(V z(SId=%V!AHS6xHU7cOXP=>iQy(_l$EC)6SPQ>vU{p!d3Yv?Dw3ga6m3xvd{}=1+6e z`H{~%*Z|{_1VJMfBYyE19^N6F=2}B6j#RX9-!6|wDtbJ`vY$3tA4=cQDmA7rNAZ4a zOtqOw+y1X}Dt#H6d?dbBK9mnwPwCAbW)E+)* zdpw9{xubd0{3&t7(5uudZA$|jPnXT3_%CkjS-&r4jpNruUynQVA94JS>Fa)H{v(bb zzkl5iD`(aMG2^uY&ueYfqsJ+Vfj+>1c_nW!HjJLPw{6&VUKF8ExbULLQr>diQjt0` zU0&de6aVt})km=#77h@gh|jGN2pHERt*HU|pFVmSSuG>!$TPZ?!O7@W7G4-MzI|kQ z!gCsXqx;ZNlxPemw~yy5YMX(NE#n)qbkX5zUzTz7s8DfGyHTeL+!bt%HMuXX4t69t*br5GrjaALBvvw>FJ?Myl7>Wt?fM zM5~dU3*H7&`-$C#x@Ez{_y;+)OSvh0EnA#19@oUH26H_}6okB+-HM@ayG)$-G%~bt4_<#D&E<3*7XVrIh*@XLj+#TtSVx9IX zttuG(wX(ak(6xdCh9#bg!^z_{Cwim!-%gcYbD}qj|Lx@YniIWI{BI|(*PQ5$;(t4N zzve`56#v`F=QSsKqxfG=_CFNFTgxB3rNyn1O+X(6qP4K%cH;MS|Lv6gnp3j96RqQ6 z0LY_`Q@l85i?VlZY8^ai*i<`+KOYNUss?{Pwsputj9*0%_>?pv`$ zYOGY3vj4e3x|xa9U^(VjYX9)wx}_V}4kxdn!zoCopHckhQ{zihxQO5{P9EUpRLq%z zORPH@^DLgU=JB-%9?zpsUQ!mN=pB+JRETjcAn{o%_|W932kahr0MD>%!kh9K%IDME z3)E`#T%d7AMLit`kKszudEF#}$q)IAIz+jL)a0oVy_1w}Ja&kz>Ey{aULP>w`q1z{ z41caG`{M~ut2>)i{(L=Y_#Y|ZkLN!vJ*gg)J)8dJ|62)vJRNHFXVbs@kCyPqv!hmj zHvP;0_Y(eivefF&rhoY#E8&mlPObiI`j`Ll68?B9)#}ftfBBy%;g4rlt^RCM{>A(2 zB>b)W%Xp&Int*M_{wnrARl?tR+|}yOw%7enm+&{9g|+&#?REb%CH##CWv%{fd)@zR z34h}$TB|?XUiUv&!ryp!*6Po;*Zt3z@Hd{UwfeK|b^i+`{EbI=tsR2XqiUP))Ch1>>1(J~T&}N$59eL+Ow4!`GuY z8qfV(Mp9NfnBN!cLU|0Ohqy}(9?TcgJZ&1igs|E zXZ$LgBfY7RIhZcX9X_SFGEP_#&_{8tFrwC|MBYw#R!Seml{8{`X5ys2YDw#7{A=~N zUu(g(;+>aqYJ4$^mE=4O*Y%fZL)5&AgS32tO*>3O;p<=2bb9@E4DJ~?g_Iq`DV_iI zMNJ()M_1MvH*oM%bI!VDEY$%&;pS}oj$z0lAKnCN0pt6h&d7{fl=H+VKaHR27Qo_mo+XEVxDSSlNiN`ihq`h=YLpereBa{ zi*<6ZkG)BRN!Ttfv@y?>I12In8+j3ie}Rr1i+^rvD!HpT{KORhz7*%|u6|$2D8*vu zrhZ?F4Y-SM{Js?Y=v?Dqd$vX&#T)us-RVl3mI|#i$6MrpO7FH+nxn?D7?tKMxJvxj zy{>U~L!54zftniz^c*;$O78r6?R83`dLjpDhH0c=FxJbBU(jSWys=aSUs@`{zTo*f z0`#!MJe0?K?0-J&z(#)9VGg;f=cqW!?qLUb%%l%8a5l73Qv9$3$EcMWJnTSo*eevJ z=CB<6Kdrm4}CdVvd#=jIN42% z;bff{mvFM17{kdrF}8QIpFVKBZTe8c$-j8c3n#it#%!R3ligK3oUB*zaB5_OWom|COttsQ+{|{o9qI{?nBz`&wNEMcKR3CH#NS6x4-1 z-ODvD?CAzMug6%L&`3uI>22C@eku-si!az8sA&A)(8X|=zf)rio1__&KB~(UoH=UM!KJ`ZPQ*T7yM-xYs5=yt_V=B9!8pqV_vBw z_{&MG0n68X9;2&|Z}>0mBmQeVlT%k8^$#Vpf1HQe{&5~=!;2?rC7;Imkuu_^19&dj zLkNDaNZpS!3MoxDSWnS;ulP}?;vX?_L=EgLtF1q8V*GrCaobKk4n%(fX!KG~1-(A= zb1`Oqjnr?X?xLH1xGhI(AI5K_7RQvB9cJ5Rhk`HgOk*_uV;)0a%*X!WSac8sXos;K z5eQHOJh`nAplLpP+WjgxP#q-5ga%Un>tnZ^VXzu)OE}pLq;Rqhq$Ql}#z;6>$H)>+ zcEcZ>tizwZ6Mgkt@Tr8CMmgRu*}mc(j7Wb$C-T=;-PpM}-hM+$CZYkWc&W}V5e71> z@1Z&+6UqOPh~ocuNj$D$35yp6?MlMn_P?jB%hBK7(YC?S+_ZE}`+7C3@&7v!4eTuu)?Dlec<0XC=j5lRQ_u`$Alp6Iw$c3Ii48^kEKcp^@S~(74dav zHpL9bbqjq--+JZ8L7Ib@=+9ujr>5?hAVMEYAH_GWKily%t2d&!!PZQQNR1iG@2ato$GA+_a(dP@SS92V+yPAVziEqg8 zdJ0_~(!7LSi?6{9Pjx-VCge=No?*?IgLZfR41apA3hN5?_x;%M^?cQRKQ^g#2wwN; zz-=nki}j|##*6h$sljl)X#D0BKZBs&#NJB-r+QuhXMpSrwg}_ZXA|DC_e|z%_Uymd zxQ9ByNLu0IxAn1T#y=p$Z^Yw7Q;uRSt++h8p^8Tg4Wi!UQo_XVpBpBchiHPo34nU3 zEbU$-w|n`!jmp?~G5k%YnrhF{dvuhe9pXiC>a_GcE?(HCmnNtY4)t$!GrIHj1&cOC z*4%I*aa-5L;=+Py;+5}@7yWN%UI`rUdHG5HyT>cP{AtzN_;a}bWY$U0xs%!FB*Isr|3E#auunB;Q)t0xj_HZ;i7D5oI0%oa z91}j3%SuFeoFB(bLCjg`O~e-=ZSxP=+5>f1fbg;pIiE#jEhQqRad^eF&C_UGprxmC zxXE-*)nWR;=?-EtbOCf7bSG&k;W2}KIu`aVbP&0PT%SDXPl!2P$ksA5xdj@}aWa|!u4@1vE??S~#?EkAT=Na-5Yb3M=GzHey&}q;-Z0YCF_0VsjBYnA@>&#-k zKa00_>})PKX%6emIh^xjcy>hlOhLF1x)OToWA>Z@>!c#y7U#Jf6PU;~427)z zUwSxt@)EA?V(3QbF6d?Wln-G4cAv8LgXVwA{&Nui4EhyxH{#>gakj`S=mQq9WY47oFhXcVb;#x`oH&-Kt7t>- zygB2UFc%Vl-@viPGo`eKh2dZ6(NGEJj84 z5?$2%`B_1-9f2)I(J4@@SPR=FP?A^&x zR1<@$fbyuMJgRjpQ5uDg($@0t3?*t8wTa?)6gD*bxE1Cd9zGh|C6dW5#VM7DJCQqb=_knK;R1vC!R3J%drqF`ax>VwMY2Bm1+ z5*~_DsU2KIAkhNyq!R_Ds}6F|=$rXO4Tu&CM=f2;BWka6>5f_(P@djPXUYV9q)!8N z(YPx_O zdXUbo^oS@;Jk=W$(OJ*L+wf9v11bj+(x4EKNl^mG733mX5Tyw>Wy^rgOLjpn-9f>M z27)3KjQ}MRal5=vl&f_n;ypc`C{6U1?;w}?@O)cl6S;_WunkbOlW3dBkrQY#<06il zxQFCO`hqFZ70@s_U6(}kV<*(hN60nEvfPLA8WIiHCd>Uu*B0q!$jh+xgl!fR)p{t=EPb}Tg*@|!(!^|e zSLfql2B=8VM~BFBA<<}Uo}_P?5N%LY5wwpeSj?03IR&yE2Yn(}N#1|gi7slN$^)Rs zpyePJx~itFl|Lw3MWTz^&+;ziLW|;{(?pz04bVA7Z9$iac-wmr3Go0n7m-JlMs%Oj z(I^ahET1BmWk~m2N)xx>S46|L0Q&9&@7o>l3^X~Kc-wyg1<{ARm`)Sz(Sl4apgW*o z`aS{MUJ-54LQR!SyzONi6SeI`KA=iOyNG;2Aw+wL{6Voq2Z;hfb%>4;1%uLv&Jl%z z+7hi0p(YFHZ6eMy95jsR8c|iyM4|^oQJ}d*e-XukRuVlUiU)m1{)EiXV*`Pk4FrqZF^)pE-FOjb3(?lE7PT11P7EH9; z#67Yrkq~d1E}FOx4kDVRziGM*ngD8Rx&zN5c(ybBO*Wbl5M9*TnO>O|Q!YQkmPy39 z94ESQ}6RS;hyNP^ErMcFtO|)iAwRR^;qY?Hm zIZ^ARw9OTH`*PZC1R>w?VrzKl1(M*v- z#Cv5L(xsX^fR=$8o8NL=LVJ2Q5%pJdSIULXM?`5vy=V$a=OZEq+1flDHmz);RwUb) z^FeMzv-A$;Pf@ys=%Uuqyb@F$)KyU+r4pryUy1k#Pk)2v=JJwxIH;SVQBGW5 zHhBth*_=nYxQGcvL$u50Dai99qQAA<<~^{jCE7`}4<+m)N)vyY_k+$74cG3QFVKP% zT?xSUzWy&!W?C z5Y3{c$}*r2i0F}Whw`A=M13^rkO*1?n{=o}M0GC2bUx!RknNOJf9Xf!ff&v{nf$lA4 zTaZI%`dr%4a%F`Sr|9;qCeA~H+9UG5DgNtZh^w67&~n6=)A=K73|C7ehCa28bPAOK8o=!+SX?*T+Hl@R!Af1)2cO@|s35jlEZp zHuqjj+SYp`X*Z!=(Xa`7t(GHPT(S9fO z(@s(ymU^G%7W2MH+R5i8wNH1S-J~Nb?iQ{h=ff07ZVeM{UB}9INV`M(L9?Nwp!v`# z(3#Nr&?V5d&~Kqf%Wyus5dIZ<26_Yf2&((CPid$d)C(F4jfK{NHiKqByF&Xy-+_*V zPJqsaE{3jx?u7mdO)AYL9!2;n^gi?z)YZNy(2>wF&^+h_=r}*lvjE}A&>7Hq z(8bV*3hc8K;dRih(C?t%Lw|rCfF6aOgkFN)gg%76fSLn1&$}kpG6BK>=Ysg$emFH9zF zSlFF(dEuH;0b*`IH057BGE1>MxR$1gHNkUeB-u(@a-5kPP@nv#hoorRtf$o9+0zC#j54{1s4}Aue7Org>Xho?+6dYV+8Wvp+5y@VIuJS(Is!Tl`W|!&bQW|WbQyFlbTf1-bT@QA^dR&I z^ceIM^c?gm^fvS%^chsE!dvPDb%lCCgP>KR@zA=^#?V&KOlUV~e`qdrEOZid26Qg; zQ>asUE^#HoYoQyU-$1uRcR_!G{sKJ&JqkSmJp;WAy$-zveF%LHmEl}gX=nwgH#7(u z0gZ#!geF59L0drELpwwJKnFo{pd+FA&`Ho~&^geB(9fXjp*x|6py#1?pf90iBDl8R z&??YGXf0?1XcK5Uv;(v!bP#knbUbt_bPn_r=$Ft9(CyG4p@*TTp;w`Ip?^bVRj$<= zP)}$uG!j}9+6dYP+8NppIt)4@PJT@T#?-39##dK7vddL8-z`V4BW#CpDjj?nJVKG1CFaOgPbd(bJ+nb0EW66i|kCg^tPZs^a@ zx>`V6X7;VpH7xAp%5W~L zG_(TL8yW;7p`D?9po5?}(2>x5=p^Vg=p5)m=x5ON(4Ejj(DTqc z(3j9M5nNkuXccH8v=+1hveU%m?`o=7$nR{-` zCc2(~FJ=o}R|mv8iXgRS5)u17j3Bo=y+1=EYc(KH`;@hNv$!h{ZCL#U?OWMsWsjs@hrteK&wGx zph?iW&=hDIG#%O&+6mf~v^cj*lv}UFOH{+biOZ>mLlfzSfEW&)1f2n0oJeaaYHg=Z z(sfGZ9md+o!rBlq>Ckr24$#ifLE+bJCH6|XP5wim!=PiKlc3W`t)&zt-6zlG&<)V7 z&^^$@&@<3$&^yqlP;(7VTOR5I4THu&Ye8E$z=9=hXU#>b3y-8FVG7Ccdi0$JAEnZs;NCY3Lu& z$F;hWkEqT5#@w?Z&5;8{?K;av09FMxtP1kV17G<}h8`fLRlB;&No75%iEyC@Fdc+@ zy|bh~^-T2ObYwluWU1F_VmXDa`z1TMl%A0{0y>`5C|47S^>{V%N&RvZqc?CPeWL-- zpgo`=4Ls>?by5Rgo%1P0HEHc1M){OWVf7}}M3ofY7TyX?tgYXb#suD$V65x~V}>4t zaF7a*s2D?eevnE}F^aEi*3tto4g}CRz-z6a@(1PB@nUJcmP(9?LHj^+p%b7ppr1g$g6@L;0zCo!1Nsy?&!6)w)rQp#S{Yg{g=2ydj({dX)1Yrc zyF&Xxz2QF+;R4bCF{4c?wN+xhQq)Rw+BBu`r)}QUdBx+y@;n}{EpKh%%56JQS>e!X z&^TywZ;r2ta3g3sG!xnbIv6?{`T?{E`WdOU-8Q!EM)~|eYK>{qx;MpigPv&H+qSPS zwCzvvH=uW+e?gx^9on(g73v3#gw};Nhh{>1K!-r{Nj2e?!TlsCV+i$uaMB>rn7+7g ztmn`FrJ{DU0kEe1wLi<4bLkB_Mf#yKpg^q-df#yLc zK=)*DKKr2up}#>RDscP>gfBv`LH~q4g39*nQwHh|tqcu>R)r=)lc8zQR?v>nZqRpR_^?`Ra?DX<<#ciV5#f`minBx*grD-k5zGI{jy z$(&04txD$iT7XDIxKZW;is7R;KxAaDB>%5#enZ+Ta~o;D%$=k;nR`j|GJhs5%sfOo zKl68L|7DpGbab!J zt|#k7=vC-V=zZuj=z2f)G52at+c>hJu`QfKnO?0azB2SgTMkDfJkpoLwGmE%c5BTs zEfH=9?Fj7w9S9u@eIGgl>ehx+l}lk=hM4tGZ^Vp*br;1@i}lJNy$P+``z>3W4C>8C z@$lZgr4;XxYT~2bi>aL#_vUN1mA!eC`?`03ir?KkhcqZ-4C&9k3rNE=rjr_b!{rH6yCqazUDI^uSHa)+Ws|wYreMr7TO{{ zi*Y~UeNk`V_moc)Xj^Cx=wRqr=w#>u=$FvV(7n)O(Cg5rP}3mJvjQ{-S_j&Jl*{FF zTx-%xhh{{+NyhYoA;`Xb)|vamL|xraO{@c$MZD z^a}LBpd4!XUuVqsv~KBpgMXs3D)(YN(UvtD;gP-^u8nXCv|DSAX^HS`q*?@B1}&Gu z)@87IBfQ>^W1jV7-AFzGI5w?E;*P-wDSkgG^*88+!M{=X!Qd05u0uA__F9JUdEw!Z z6{JsxtR)riY$Ub!D4~h|@0_6)yCiPXar$N%zUp{c`XI$r%HBlnP%Zlcg*h$V zv&gn@7$auq!mwIH3iD4%roqAy8*TXdGR^(Ud;u442j zJ-i)6tsLteKq>0y&~s~|aZVU%Mou--w{ohJ_R6V2IxMFi>G+%`q_cC z{-Y@)Zv%86^mphz(g5K+g72GG7;%8YLle7F+g2TsM9RlqfQTJ&+GL#ft!MluBbHF> zwH?9ZYSxGgRATWJ0^bSpq8GxQNBlwU`9^~~r1pLL$q4S-`bbvp)yA05srpl@tPxFd zRm0a086#Jac7S$=_9M0S!<>;D$vOf$j?@}IapZQ2p8}mrnjlt;{Ehm|L;6X3_A$o% z(&mi3N~2l*pdN`F4n?>sG@jJxX&SA3y3i9*y)yaCQgieP9Q8&%9+awF3adBtSx*j| zdwEdW@W>_b;0@~Q(soQZ#djJLWu|ZXVuhh$;YJ_6S9peW z?qXAASMlBAP|}NwJ5;vr)7Jh;RNFz&9B3YN0yKC$Tf?9iGdNro;gRh*9FK5KXai_d zXdk3)gK!4419U%fI7rH+^S`MdS}?KXxr6&EuhOTF(WtNfFp+z#aZSZn zQ+$-oqqg-goL4zO@OdXjY#52>VMactE@3fO-D!Xq0d(f&138UDs|K74dr`^hr82G*!A)uH|{KePe)&-`E% z#q`W>OfkhhhvyV#U+a;(?}K#Or@uolKyN~yLf@Fo)=+3FX$9@qDK#A`XnUsiAwBlt zPR9yb`m}>i6|^kqkZHeBcm%@Jr=6g15yDHL6_%W!AA2XpFEj?_MLNw7vwS9H58FbP4&vKrW=T=3XU6{5jS_j&x=!8pU zvK>++T?6UJ3#JQsAuc*cx>{&up{k;RuAW3uiq^YUC5kghyX6{9G*wZV^6~VZ+AKve zAO-sCG(^s0Ol`uP5GMM)J} z(Kl%}DwvG~JMbBIYo6Ctm6ot6vnq7oX5SMpNb1J{ZTwaV)^k(@r z<_co6qA}$+n%%@=MW2_?HCGfb6g{Szd5EsTMlJ^^T_v$rQ3P$fr#Po5xWe0JPw@y; zAkJ54lL}X#nZ~|M$m4}*DZzU1*ky0Q$hNK2~#MSK7snuTyvQ41YLBl_P(FIAMfiib@Aji__BFK8 zTyqsM1a#4vdt|s63Yz0I&+Q%Ga4{9MTktl7i;qBi1h-3sn5T%hwwhR?h+CNEmcDUd2tt&j}?RK{P;$Gm8EG&wSlC8dIY@@$@Q$#mK z=g706n5gJF<(Vox`BgZ|<-U87L#n`+@rk4d+ny?$hsPsxsz|ABcm{feIHrn;iefxU z`=yG#phA)2;pW#woL1D4C{5f})ZfF)uc-)*GjhqL5}J#AMH4*2{F;l!iasP;OL0ii ze9(}1Bi&k1W!i;Y>pdP_99oJ_ihhI52k!vqiz}eoitd2I`E$ymK>Q8r3Cb6yN_G5N zidi*{JY6dlQJzN?g;ugqU4r??AE~^$pbtR>qD`gdly1JFY@}PIJo75$`L-0B70n`Q zB_1hSN0cs_*EaGzK-5}%jlRoA&N~im#Ptd3GZ@V33our>E#9uG(zzL{Du*y;GFo z&+p@m*Vv)Eh&M=#qI&ianTohBJw+cy5uQ~Xdx;Mf#d*H%*Gm*Bs_Pj~wnK`Vc!oIk z7G>+A1o5WltIEAaB}H#}7CH15BNg@Ww20nfqM~fiA%4BZaz$f2dy?lmMU#-urJj-J z0;Ee)w9a!3rF&n|R?qU3?t~)Vo4rMRvXO4D=ZAi8i)2N-Z~KUCig@4l75fzNzU?Q* z);H4ezU?pGSH$~vfLPx^**yIn2a0Wq&Uh9$3=*wU4BG?G6fsx~P{h4ph&W-R6!DIz z+R*U4;g;u{E!HV=^qT26RGd*%!Ruqc9O0D8p7|KBb43G?am6xBGzVSN{JfU>4HJtM zg?erD8!nF9d5#db4HA32e)1b3$}}=c-{W=2Z$-<|Jv3;6Pu>Ta1 zs>s8qivLuRsVKoG+JBlTQdHlkp8s@lL(%z)ss1y>*)-&WaiUP@O^t2%#eJmjOc7|K z0*8-8oTA=7@nV*Eq-cmwH~(3pRx?glDDr&<5OoFRi|IZ&{&U0?MW6Y!b@^D-Zf=yY ziKs}tujru9XotDN(!#Kv_L=5CPs~tsi^`iX?kV~kw63M$=}>u^|9m0R4f3oUPw(Ge z2NjC2%HR1f5Du*k8@J#m!c7sk;9?Q1D2~!C5eM3_=N!?Z@^SwqA|`{0````#PeqzR zPS0HK`F}1t86I3?b)(I)|CL?45kS_Kq2oD;(owGUVpa867#Nc0M@h;w49 zqJi+71==e@>2z~WEKuapMN^0_3Jb{Cf0u>c zkv)z5ep$GH_J}nBTLZ3%S)e&$lIQV&>ms-l@)UOh&IkM<4s|u?pMd)Tx5TPm22~8y z1OF7G-!`anpjY5su?Ix`GcYpno(St>*lGr*1U?k_!7S>7H3ORkJ`&B9tw~@;;A7EV zQAS{=z$fBuMLh$11U?h|6N21#hX?ixd?_Z`(q#u~+Du!z;ek?HYD+gR&_P>cOIHx+ zto@{DYT&fMvYO~?t?Tn(3;H5z^ z+ABqI!5e~Nwc3M>Tp9*{9~7_6P}Dm3SWu$2L(yBoH-lb zP+jd~kkMO{wbh_PacjCqaI*HbBHtMS!40(U6*Zm_6WmbSr|8`owSpUIhZTJ_qgikh z?UbT(Guj0=)h;V?D(n^9T)V9(s&H^{OYO0u!opF(=~_IF9OGDNqct~3^zz#p&`w(i z+N1H2lc7}_!rQ=}?*+Hl-UjV;njh>bva|u9e8FeDENzzIDfR}>4(^~GR&*@*)8LNU z9UFZS{FYYg9pou41s6DU(L5F1A?m8}??h60;%V@j;BHzbC|~fX-$R?OY+A^s;GWuI zMdd=`>6b@M*_@89LqM5|s)Cj(N(!MXIeKWv@T?zF#j&^6R#8jPL{Nd~9#Y`YTl39f zPu});`dv(mL1IA2@4;_tE$nQ4v`l3iPPRVUE3`GAEmG(=A03TtcbZOZM!$N9e|yVv z3-;4;>~iU+O$S{=>-N(Yt32~UP6zkX&Vlx5mx3pl`)g0_(hblm<#MLRUKyZSKm}rU z$c5kmT5nLkxD%Y`J5U>C*sw)|w27cSv>zsz2Wi2>IF~u%(~#T2gS9kJp;#UAA~;*? zs_45Ab4aeXP0_&+?~r%3jqh^0LUA%ADP*K}4>U*o5#r`IR+~E9ussfG9WqW^spy}O z%#eKTfTB{NT|y>kE+Y)ja-qFLCTin5E(m#F^RZFykPoy^LB>%v zMOzEvRgR@0Q?&h{0;kTQD?_GgM+_2ghkiwL%0^p4KGZJTXm7}L?Y51MgcNFzZFDZ= zBkh%qZidX(9LI9a3MkJr_lM@k2WeFx==f0BcISuw39Xp4PByL zvQc#CXWA_r)eik!dt{@u(B;}o8?_7lQgaw*)MZd;x6qYZMH}^@XZ1pClpVT8i?`9} z&~;j>jS527Ywc__BXpzI%SJ_^Uu(HGS{%Ard(TE+gl^Gh+h|?rHtlm8Z4TY8ZL-mh z&>h+jHrf}uOZ(kMM?&{#S8a4Qbg%ZJjH443q=W0>0~j3=$OsE#j#*^<&;XqqjcQmKHJ5T3+;D zVNbQ6KyzrU6P9P%Z5ugTo@+^S*^_M*EibkHHVUx(qph@2HH)U-vQZ6-)P3h!)1_F< zdOI7nusG^dZPec4tgp9GH%n>#gpK-J%Ig2vDA!U>51DVxbDYIh?`fkcmI`{2jfyN4 z^(!`7YVpvc7jQb`Z11Tj8RWE)+S5}{R{8cC@V&*5^hJOt5nq+qArDEc8q(K zNPU5#4KXXqMe3GCT(>!5cT9YhD18v9P@IkVvQ(75SlRB!Bv*;nuYruQl|H77e|yd6 zD>fpVl}g7h4T-g*XO`+Va*b_WCC-jIR!PuHf5IubPxP*mq&GB3)Q=rlrH1|)s8Fs-e?5HZW^c$djF(kHfSZ#g8V$P*dOpcvVrH;N7lrQF!t)5bTWGSLuINJS^U(VGzNLok&)9=i8tCOeH|S;T>EIN-8mLgXRR6t7 zLp@&E0;->>lBy3;RK2>VXr%8@lv+KWsOvH#mp7|B(s!TFg9=4X^^ow!x>(LO+J@@! z;c0qXMf0ntg}2a8*r-={x?brEtLL!rH}y`6)>a=D-cE1$rD5AyeOh>X{iveDL|J<9 z3by5oOH`MRIz8?~{|d$5)fa|$)bA@Q6Sp?JlODX%@brlLHoUVwL{Sx@F8T#Um#Xgx z@2cmmGCXUo;X_!)?Gn!#E)?S5rg$$P=PoR7alQ0Z>#7RD*YY(3nQJl9#=ggTR)@d1l47z zzI3gz?GHiC*BM)@#iv9J)$>64qFj8u$k7{qWq4MK-xrpn&rlQ;KQJOk58q&<>+dlx zB3Eyss9|tH#4tTWQS0CjBi_|}DvFAq6){}T0p*KY@e3nH=ruPQB{YjaU>T{Wg9=5n z`0Wv+^rOnwf$B0w_t|84_6BuQ^e$+rqJsF-5o7e`UmKna;!lU?=|3vsy^^nA0~LsG zyH%ej=vo-UcdK^k?vT$Q`PtM&6}AD#f|uCRX@-#fbzxP@inSW(M?+oPltpa zRj27g6uA@4(7#X=K{QjpqNr}du&T54h1-mDZ_l=fBK>nk?}2uMctrWAYLR}#Ag2!# zEMl&HO40m;6r#(Dz9ic`{g$F{$u>`ar06HI&DUQj`kid^b@O*zdV$kLvMtcdD!NOy z1-iSUmkIN#F4TP$l}h}GD9j+L*#z?ak~Hi|YSF0Q&*@1SUV z;xeM1ihfL7U3G~*K+(y>4Mf8f-Ade2^;3PUqNj;Fh~8IZPWrLxXZj39m6CoTnx`lt zsf)u>{ZmD8NsWnCf%qEiu=#U+;&x-(`3ioyzCn>wEsI#LA5i34tBT`t{iq^O&>2Mm zwO&8#dEnn(C`#~UQerjp?{=oJY)D$pAX{o&wr|Zsqa=ag=nRI4`iJ2R_oC}p)S-C z&ec}y^$c<@u~Kmz6Vq&TGgpiZM*LCGuMSF%jJ8$g`$o`JM~OOz3U`a z+pUiV<%{e(kIX;lmz8aFo!%}#=uegH{W|etuio$g=SkNZb?R2zs}EJQs!kK4HK0P_ zRK7*EAN4EBwy92LwV!migGRa?b$Stfq39Tuw_lI@m2Goq8%9;zuXhE}_*rL4wFCMr zMSs^>SnZ(R^$>d&3Ul3s)eh;KL32c4-Jhx*(O)QAbloG>e%FT|HawH-{u6jY->N9H z?%ir9_1lX2)_q>>w4QXt@El&ZV&qwUv7!&^R*k%%-viAN^Xeu4bww`s2ZA>3T-qw5AXldjfJ;xv? z9+&RxqZO^H_sD!-pQvb4y$M7gg7!Lft+y!hf%O`*Ecdfw;(k_4wf9Zc3TZ=W1r}|?>T$iW% zD@6_J6-NH8JE$#cUGHNeZWW%t^A=wW5#7ofdPlTtiIS-Dct$0^}qW#xKBN6GevoPqvg)bkBlWTOe@ zH{=G;UX0h}jADC!AY1ZcN2w|sfo2sA<5sQ<`ZUgjE}I3tvoo3MR+ zcc61rc~#Fn=8qf3)Ax(d7&h@~!?&Z{~Kd^gHn=70*tZw<#s zRgxDJeM~kl>2!fT3&r_{i=upF9T2zt+9+Sy7_>)ld494FXb#b)C_fo@QP96a@u1bMv0tvf*VTU0b41 z$shFQ61t{3MTf~giUyO-BKIg7OH@TVT{S#=`Mn(!E=z&(MaGPws?w+*k=qUSED*7chDO(tQx&B(3J$9! zuPDlFG?i@c|6%0Wv(b8|T5=DlKn!cND!R6$kMSXwDUCcuZP`cB{6@c#E$5bz?#o6p zrncMxDiE6+RgS46BW@eE!;KdH=v{vfI+hl2{JFU7|s%SXy48q+F=9P%fpD->Rh z+mme-sDOTTqi0Ngc}7ue;~_B(WWzf~2@NP+irlU!vvD`S6nPs|DEc;@8IvlL?i!vi z8m^6LA|ENrYrHciO;)*Q*ycChAJbIEDOyR?OeQPZ*7$Htb9oO`Aoe%D5z|Tzxo@O9 zNu{UDo1g-5x3N!bx_qkWpT=urTFbBphNo+jwJ~jEJw?Gy;>DYC2&jOrkV0bLl(&`b zMxFTBcGBmek*-dY_}C12K~bwF>9Or)<|DQhh+a)P$7af?Ozzl?NgsheUu%LSl(aiPiK z*e>#xqMMYitMqxop84WAmEKi02NekCv_E3I$sNk(p7vL4cWHXco`oVZ?PY9F`2v(L z>ZQetUb4^MY%36NQo3GpBPd_=AX{(g|IDzBOzRobTeej+Hr2oS+wu`8UrbD^UA>P? zdd{BtVj89EE0-wxByE38U%3ucAl6bY{p1xzgHyAr_m>l280o%C%dI{@I=wV#Kjkt| zzN6?oImn!33Tm;7Z+-oC7+`(sAPr?zxq zaU*3fdXs}~1F3{ja+acTO;h4V$=dWb1lzi%c8D7zPbiw)bV%Gd`3O`X7Bw9nmoG<4 z!*dPgGG6+am`K=~rNSv-BUK8(KM%Qb7!Y<2AWvI(d_^lcUtKUvauh*A2mX5sNuX0sxu%iD^0b!&zk;B4f%xml0+LfNO3L3^4V zj-4rsK>6Z0(MR&AvR!UAE`F9Yl{U(ILNr?@D>5~o8b3$QQsmuyVf@GPkfQ3%zlxtL z{mU5X8WGKt`xJF({&W0%`BYJM^YihGWLJ7Phqq`t*%r$pMPD|L7oW*}paQX{`K$QP zWY;$g&l9kn0Tqbb&Fdz7CWq5oGu$KpZr(a!say)m7iC(sPxxH!P!!lAUM!c7Kn0>s zi_QtlrNxEQ6^OXhUI|~wgNjWRo>0`c#l(aaGTqfEy?}CADffd4#KIP95?0C^ zidMDQl(0(HD{pviBhS?`2UH+VxA-ApwfsVncj|$JHL`I9qx6SV-ddTis9eii3G3tm z5cQXqdg52Ilbhk$tfgn-2HCTsQNmj-(_=Tt6N<81wo2S6+q<)^P<+_(?VwGv6NsK! z|2Qh_YdKL-H_$3Yb3undd3zRP=x2l!& zgRE59@LbudVbWfi45BvzT4g2uB-eoo#hq4Tl75y)m90|x+@u4tiLX(!y6Lr&evyk6 zWu>o4Iw)T#8j&8B^sBs0UkBoCn3{e!@sPaXZ_vVY*RaE~Pk>Q+ohD3qpnS1|aycwF zD%*+lZAnMuJw>Zp>?0Z(WaM%u{W{TjMK9C;B$}$IZ0kqnBeGJkQG!ovPjN)X8btf= zDS0N_=%1wD$K_^a>(DSW>bTqiqP1VzhU4;A zMGxA9haHz!70EX}#R>UHQH3|d!%oOjVaC=5k?o}PRFp`zlQK$CGqRnMbrkg@+bP*b z(FbHZExRgOOSaQ8SJCfeJ0mA5`kQQLdr?_aNwe6bMxG2{ec~URX!!FA0pliB69}Yl0iKC>`L?&h)0e7HLl5_207(sWY@SZM=8q7=ub3J z(Uc5NaYHUp^m)ec8aL#AkkMam$Qy=DY|H54a6{It!ga}~c8RBSLqUb2R?$>Sm#=J1 zi$1P#Q%(W#EYdmbwp;}&aGKuUHSCVusAyq(o#;D|F-N~E&w%ELmF+*PaaX!TaCwE| z+x9zaJdkOMTw{N(@kn-5)T8J`jVH1vh|7x?f7|xMkL@i)17M@l>6td0&0IS6N{wPV z(mq~1lcVf%c_t@-t~qfo&t!o?!ti{*gy(`1o=ZUm;zIk4=4bLAh~Gen7tf`oDsRzV zCC1*b~Xpo0Xv(6DIvNzouerkWTbO6tx$Bm{qq`5rX6;krA+(mJWHA4VmOz* z)Pm(|mNqp78QWgg)K=NJ&B~gV+dKnmzG3>#&eO%T&(71u6dP;JGp44isR_u)vw|sI z**MP%rY$zl#x>nchwMDvO(*O;-AxhIt$7C2^f1*28F_k|nkyUU>1i5kXY(?>Z)fu| zowc)hn{L?IyiIN5irdr2)Cpv?r;q6?J6mPbHalBoQ%HPqI$u*X$VlgFny-lZXH7rT zS9YEOrfqhf0VYdAaV~+TXpoUhpsBl^Ey%=Q)Z;zITN`9rWM>ODePL${Hbo>Fp4ZzC zt{Gyg4>H;;%+y@jIG3>hkGyvQtE%eu|L5L&&9(O4fLujMR8SODR8&w@5Rj`%rDl0U zMJ2D4nwmE(2_#cWN%D${N~J}mg=L0?MW#umMP)^)NnQ%mijvo;eq)R|Htb$c@9F)W zbN;{cJb$0Z@0_1G#=NXK*P3gt%U)>DHhBgP2+@u>d3M#RoIJZ~_eD0hvzwMhq}tL= zo72D97OE{KQnpa-oRh7)R_A2vuB{xzq7$YhF>!rS#GKiBu_lv^h?;aBZ=ZEnGX8)nmJEthS#j6*7nRb_T2 zij7kgPIQe4@BTz<@QOLr9tXBTnrpnG(L{5ZW)r0+DBI$3o&yJI#CKL;ADr7+b4#cQQZw(&lm z30g`Ddgh7tz+rKc)e_4tbe@6--5orip*HJ@9R?FXPS+Hj^nfW~SEnOdazc#hMqF||%> zA2nVpyiMf`1WMDYnYsf_(5$yBTNLD*sKqiRr?m~9q*;e6+X$d^t&nLF&}6NF>0Y2I z+LRIKSs<3B&4`++6%%EPb!l^=GPKZ6-wdsS=}_9^Q8TstJCx_q zwBo2)S_RXm;F+oUk5aaCX|G1zqg`YAHmxG+UM=)aW&0)Vqo{e>0wVZ@+l2E`^R*Rs zp$+MmsD+yAXyxfO!4iGHwwS5&gx1lEw9`z3CUlQpta*%4p2H{fjb5S+W|}%7K6{HOp9Kw)i4!Lm>>P1W*)0bDVy+M^a{D>t{fl`R_#JLGU0omGJ zObrt@Mn9z8&Ez$4S9FfHfb#`U+#8*%9b<}~csP2cc8%%wiB-{gn(H`K-;{|TM?b8k zFfE>VF?y9&!}RDxG3XJkfoa!7+o09j;_)iqD-&-Sl&_UDeKfJ-phvaHG-dl~;($Sq zX=8~Bgv+G(L2I>4BDlXhEOpR2?am44sb>8GEuH9s>Eh`0K?T~eCfl?w>$TI0M98G2 zg9^1;rv8(1FleI|K$IsIO)>{>(i+p1ZS|xV2W{5I zOi}rEO}a8@i?*2vt|=#pn5|j`)2EYcG266S_WTa&+pb+_`eV`{u|pG6RVlvdxqXYZ z`9yF(GQC60PHhv@p|Wi4`+YRmhRpNn}#8_e|8Tt!2V1({gPW zQMR@H6r@+#hEMg%wQ?qWs#mVP#nd*zPaM{c5~*w0!`eBb3d{J-p23H;%S5VWhc)YL z+&k>M)#fk_ zn9?=)sP+)k&?%wf9c?Sq=qZDMN{F&Wcu<5mroGQLyaRGfYh=PZAjh<@d(;?ZKn=&V z;Y^FB9E&`rfuA8b{cb}#jrwFlU$G(VwC(OP zw8nYpxj~%H@Q$s~O6RLm-su+>`=wUK^jW{YK!=Hr+VIVsue7(B@QuN*wD*bB^Zqm1 zCrtRf|BQAGY6m5TGP|`JS)zh=d=JKHTRs;x-;R3ozudZ@Xp@X zS{xJJ+51{cVZ!@^=e0YTaMn1lO<}^VJ+I9nQZvzcEsJe_K@Y$iN5Yqg8C?Ktn6gTK*!S3NqOdA&atu}_KBiO#xCNuS( z<|n?>vWe7hRKC*=DjT)>JMCl>rN!21p$pX>GGyB9*zdKuOk<{ni0`#^Op~F^@3m?o z^*+k?+NVsoMc->*G2tv&>a(1JP0IdD!-=+GZl$_LZ?$wRfB7 zvDhEAFBQS;y(RV+?Hi^MF~vaNGhLeI8GK#)h3RMbv$fYXv54vu=IIflLCYh`vwBST z1A2?8!}Q$KjBRlf|M9uE}7G!aUmRTHWEm^ZYmY}-YiAxl-h{nIPKvychzzTVKPm~Py88f=lvl;>f} zw~6V*^g6IPsLOn6`Th8DaW^QpV_H#Gcu9TJ|a zZfFk@9kt>){D!uN3D46vv`>lhte;R@E-+n~4sWq(jZFB4+pn6-1FB{ChTE@NAk#09 zuTcwQvd!ok+^8in`OokZziD?eg@NriZ8lQ^*nZcRGK~h?@7g-1Sz!A^+rji8*#6KC zFcpGL$V#Rc!6xMAOeeu+l9!pTfXyWTV6xAIH{7KAgK8Vv%!D`GWM`&OuvuhZrg*Sf zkz8xs9m^Y`T1&sT6FwJjzrKHbb6fIsrCA{=oD( z*sRjBLbdZE*sRi@=z;{?u}r2}U4!lNKBgA4{Dh0lWeNnF zi`>Q(4mMZ0k0}9cuJT=`QDAeE=a{C0%}xHnv=nSDq;Ixr=W4LEkl{>Qz~(NKnD&9q zT}~ppV8b^zJ>)zld~?%7u4d1pkk3;VF?|C0JmmqV3t;n-HAHI8@{;inVeLn)^fsDI zBD!G1_dmVl9ZdNCr5DlB##d*saOaWU$;#$giOo?0C#kG=4ndWSX zjPsK@OdGbO#I=$6Os{Sk6W3Ng!Sn^>YcIDmiLEo@0_D?89k#ZM>nQgz4codnu9JL~ zY2MaVal!IUBAh=XL>Kuz(FJ;Qvy1$d3E$l8B5gUi?H6qL=4Myv%Y<)kc9lU)_~vFe z*^3F^-0UV}nDEWbP?^evZ*GRlu}t`OW~iLagl}ht$_JS6?ac0S4Ut+2beEf$a3#=P z?qI@|Ko9v86Rre$$mf{w+}~3kV#0MnPg%tj4%Z|-w=yVItBjWFOfIKIa6_5n3JtEuD27t6xT<_Qz_W;lGLvWn z)b}n>>`JV?K)BAn78fb=iO|*#qE&-$lT}Uh z_~7Ak>?4kRMT1Am%qDtj@F@8y5pHe2u)E|1MPlUaeS=5K`X+j9@L0KhwJK%8?Bj#e zQPwc6nO!qDUDgu8n=4StWSP50<=Z#=>%miH4NE$0&Di7uI4xtAaT~<5xR=4AsexjMqW%~4AEr)HQGGR0i zB&?P*6j|~3dsNP4!sG8zxr7PVb&ttxCOmE*ldG9jy}k3uL_98QnLO@^2fD(9>yY)bkqOr!>!sIb z+CD3;LkeXe6RtxFWj`idhdd#Zm~b8PgiK??b;t%en+ew;8)P;Uu0uA;bxgPp*(jf4 z!ga_dd4LJmA)Dk0CR~SXmY*}>I%KoF#)RvTE%Fa0T!(CtEw`v`z;(!0*@+3)AzNh> z6RtywWGWM`LyF{7CR~SXlM9$|9kNa4GvPX9yDVbDb;x%45)-aNcF0O5T!-wCHB7h; zDVEyQ%p5)-aNo|H$Ka2@ibJj;aZkf-EzCR~R+C0iD$cH%nZX&K6d>yW4AP$pc5 z?2&0qxDMGP7c${GWUqXf3D+TeWib=3L!OZ@GT}Pp8F_-K{XKr-S@|VX&wIKCKPwxU z@a$A7$8N)xscW@TIhhD&T3ckPoT~`FckyM+b8;~go^PL%E12+n`<%=t%CWAwcUkcB z@(|PJdru@hFW(|k$Jh(WnI-E+jd4z}O}vVtg&uESrE$Cz-IdPSaM!tah8l%Fv@HN`XdpghNP5bog~ zl;0AmUV2sj$b`N0s{EBmjnN^;+zM-kWxLWS(02(EpVcec6B8bq&Lv--|U0CHz)KW|v# zS=oxI+q@A#0ZjeoO%6CGLzq(LjY&Kwdoke_eJ%Sl;TC-@2NM;DvGXP+o|hApjoNZv z-p!u4wddtMOt`h@<^4>X=G~oGD<5FmKW{eB!%Xka^Aq35wM<{k>l*xx+{9Ej@4mzf zvY5$y-y)#BL~4JzD65<3g`O8>-xAdm+4sTQXflBbd+Cx)Wx`&%B=2OxUb-wNFkvrU zmeZK9m%f$vGGQ-$D;F^hj#-}goqUjKL`)9QDyIDV>Sdi=$F%#t)roa-6I1DZYk_tW zsXIznWR;&%rvH-?wcQWMZU>opO5u5GIf|=3bu@=RK9*>t7b}>{}I>*JdHLrhg^~AOgM*J zk*kUFtankq3Z|*^_r+e3!FyDh_mC}}>7n_4(9UB_h4X`gugI=@mFMpHZGrkI5--mG zBJq2f&_rhwugY~yZ_Teu{6Q8s(a(uL$s0`gdy-#duV<)CdfWULIfKb{wl(P&S<*!A zN!R7OLg5A5EY2Q z@CC=;<-<(h%%9%z54nZu8j#SRV``i~D9NNBBgzv&BU6$r`d3XfJW10pHPQGaUH_3N z8$72aS@nQYwS7S&=Ox+oh$dQ^5uUQh0)Cp6K~s?VkOJbke4-$Xwq$Lr}$^ha`{{y0&AsM}^uN!GV8 z*|)b&8KUoE>byN9Wtjd9({0;(r`)Q)$TWZZ;FR0-LrjI+Z%Y}WzsYoX`^1zx^mmye zcg#w;Q~!`@@{Xk`qxBvyQaj=NFuDC$eNYp@*KYI_q5_e*@Or>_z3e5`XW0w?=m54d zwSD*(Cerj12NdD&&eHTBm^Lr;@tmOBURE~zZP`SDh(t zqbBPsnebOIQ}kzTDfj8m zG8KX60=<&yrTed^EYv?@I(q*fDU0+vrW){EqRWG-oj-!-Qr(BiwCInNEWJCE_aYz9 z2lOPSPK)eA9@NJ%#Vu-x%+~K^ny{$lkcae#m=-UxMCa-onAR@}7_w4-hUvvct)m~- zUuQbCsN0ZL`ln3S7JZ+xTED>Ly13tveEkomZi@#Ec~o!xs%mxI;_p+|>cLE-7Pk#9 z&|{fqEqrnhAdc&`kK&|FimWDiix`C6sxgsrE;QJf}A{ zQQ?s1b-!{NBkR;9!9DlsflTw4JUV2b-jzuG9$~-Uk8L?i{KS4ehUsylF-*@d**0Xq zp2zvH)%*1#CT!<^{aq&9hW+|kCT#V7y~SZ{i&{PH*Sj#`-R1pyBvBsy%3!~~he-X( zV81^6b<9^Fe&4YlYM)31_Z5rFhrFcEAi|#T@jRd}YN9rtFY6Bz;og%a59;fPYT;@k zOCHiUGvVK6Dc5%~;ooL?T`y(Ay{AIg-cb8XyCsKYg+7j`0QR0q{zvp8BD@OuXvmxT zF-36Q_|=fN^^;5^VrqeEnDDy}NA>UuH7fXY;HW;Bh_CVVOeVU<)3>sx+tQ%mcl6ho z+AM7gRLRr@Y{&FkrhZ^Mre9&gYs%w#z!6m+UQ-^|XE5PYh2#1gL`SXoRN=VZNK_ya zmwq?oxSskZ=2Q0>PUsm-c%R{fzK99$GgRs8nD9PBmA;usy_xf#{yN+6I`uvMBokhz zzNcSi!t2!c^S;dP<*6grjK={z!j-NPV-TTF)c8V8c7Q)%pe|yrWyK zmk}Mc;

x+>?IB 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 FoldMarkers; + + protected static GUIContent guiExpandAll = new GUIContent ("Expand all"); + protected static GUIContent guiCollapseAll = new GUIContent ("Collapse all"); + private List children = new List (); + + public GroupLine (TestSuite suite) + : base (suite) + { + if (suite is NamespaceSuite) renderedName = fullName; + } + + private bool Folded + { + get { return FoldMarkers.Contains (fullName); } + + set + { + if (value) + FoldMarkers.Add (fullName); + else + FoldMarkers.RemoveAll (s => s == fullName); + } + } + + public void AddChildren (UnitTestRendererLine[] children) + { + this.children.AddRange (children); + } + + protected internal override void Render (int indend, RenderingOptions options) + { + if (!AnyVisibleChildren (options)) return; + base.Render (indend, options); + if (!Folded) + foreach (var child in children) + child.Render (indend + 1, options); + } + + private bool AnyVisibleChildren (RenderingOptions options) + { + return children.Any (l => l.IsVisible (options) == true); + } + + protected internal override bool IsVisible (RenderingOptions options) + { + return AnyVisibleChildren (options); + } + + protected override void DrawLine (bool isSelected, RenderingOptions options) + { + var resultIcon = GetResult ().HasValue ? GuiHelper.GetIconForResult (GetResult ().Value) : Icons.unknownImg; + + var guiContent = new GUIContent (renderedName, resultIcon, fullName); + + var rect = GUILayoutUtility.GetRect (guiContent, Styles.foldout, GUILayout.MaxHeight (16)); + + OnLeftMouseButtonClick (rect); + OnContextClick (rect); + + EditorGUI.BeginChangeCheck (); + var expanded = !EditorGUI.Foldout (rect, !Folded, guiContent, false, isSelected ? Styles.selectedFoldout : Styles.foldout); + if (EditorGUI.EndChangeCheck ()) Folded = expanded; + } + + protected internal override TestResultState? GetResult () + { + TestResultState? tempResult = null; + + foreach (var child in children) + { + var childResultState = child.GetResult (); + + if (childResultState == TestResultState.Failure || childResultState == TestResultState.Error) + { + tempResult = TestResultState.Failure; + break; + } + if (childResultState == TestResultState.Success) + tempResult = TestResultState.Success; + else if (childResultState == TestResultState.Ignored) + tempResult = TestResultState.Ignored; + } + if (tempResult.HasValue) return tempResult.Value; + + return null; + } + + private void OnLeftMouseButtonClick (Rect rect) + { + if (rect.Contains (Event.current.mousePosition) && Event.current.type == EventType.mouseDown && Event.current.button == 0) + { + OnSelect (); + } + } + + private void OnContextClick (Rect rect) + { + if (rect.Contains (Event.current.mousePosition) && Event.current.type == EventType.ContextClick) + { + PrintGroupContextMenu (); + } + } + + private void PrintGroupContextMenu () + { + var multilineSelection = SelectedLines.Count () > 1; + var m = new GenericMenu (); + if (multilineSelection) + { + m.AddItem (guiRunSelected, + false, + data => RunTests (SelectedLines.Select (line => line.test.TestName).ToArray ()), + ""); + } + if (!string.IsNullOrEmpty (fullName)) + { + m.AddItem (guiRun, + false, + data => RunTests (new[] { test.TestName }), + ""); + } + if (!multilineSelection) + { + m.AddSeparator (""); + + m.AddItem (Folded ? guiExpandAll : guiCollapseAll, + false, + data => ExpandOrCollapseAll (Folded), + ""); + } + m.ShowAsContext (); + } + + private void ExpandOrCollapseAll (bool expand) + { + Folded = !expand; + foreach (var child in children) + { + if (child is GroupLine) (child as GroupLine).ExpandOrCollapseAll (expand); + } + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/GroupLine.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/GroupLine.cs.meta new file mode 100644 index 0000000..9195f33 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/GroupLine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4fcef1ec40255f14d827da8b0d742334 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs new file mode 100644 index 0000000..49c6ada --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs @@ -0,0 +1,12 @@ +namespace UnityTest +{ + public class RenderingOptions + { + public string nameFilter; + public bool showSucceeded; + public bool showFailed; + public bool showIgnored; + public bool showNotRunned; + public string[] categories; + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs.meta new file mode 100644 index 0000000..6ecfc38 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/RenderingOptions.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5c0aec4b4a6d1b047a98e8cc213e1a36 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs new file mode 100644 index 0000000..2703ab4 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Core; +using UnityEditor; +using UnityEngine; +using Event = UnityEngine.Event; + +namespace UnityTest +{ + public class TestLine : UnitTestRendererLine, IComparable + { + public static Func GetUnitTestResult; + + protected static GUIContent guiOpenInEditor = new GUIContent ("Open in editor"); + private string resultId; + private IList categories; + + public TestLine (TestMethod test, string resultId) : base (test) + { + renderedName = test.Parent is ParameterizedMethodSuite ? test.TestName.Name : test.MethodName; + this.resultId = resultId; + var c = new List(); + foreach (string category in test.Categories) + { + c.Add (category); + } + foreach (string category in test.Parent.Categories) + { + c.Add (category); + } + categories = c; + } + + public UnitTestResult result + { + get { return GetUnitTestResult (resultId); } + } + + public int CompareTo (TestLine other) + { + return result.Id.CompareTo (other.result.Id); + } + + protected override void DrawLine (bool isSelected, RenderingOptions options) + { + if (!IsVisible (options)) return; + + var tempColor = GUI.color; + if (result.Executed && result.Outdated) GUI.color = new Color (1, 1, 1, 0.7f); + + var icon = result.Executed || result.IsIgnored || result.ResultState == TestResultState.NotRunnable + ? GuiHelper.GetIconForResult (result.ResultState) + : Icons.unknownImg; + if (test.RunState == RunState.Ignored) + icon = GuiHelper.GetIconForResult (TestResultState.Ignored); + + var guiContent = new GUIContent (renderedName, icon, fullName); + + GUILayout.Space (10); + var rect = GUILayoutUtility.GetRect (guiContent, EditorStyles.label, GUILayout.ExpandWidth (true) /*, GUILayout.MaxHeight (18)*/); + + OnLeftMouseButtonClick (rect); + OnContextClick (rect); + + EditorGUI.LabelField (rect, guiContent, isSelected ? Styles.selectedLabel : Styles.label); + + if (result.Outdated) GUI.color = tempColor; + } + + protected internal override TestResultState? GetResult () + { + return result.ResultState; + } + + protected internal override bool IsVisible ( RenderingOptions options ) + { + if (!string.IsNullOrEmpty (options.nameFilter) && !fullName.ToLower().Contains (options.nameFilter.ToLower())) + return false; + if (options.categories != null && options.categories.Length >0 && !options.categories.Any (c => categories.Contains (c))) + return false; + if (!options.showIgnored && (test.RunState == RunState.Ignored || test.RunState == RunState.Skipped)) + return false; + if (!options.showFailed && (result.IsFailure || result.IsError || result.IsInconclusive)) + return false; + if (!options.showNotRunned && !result.Executed) + return false; + if (!options.showSucceeded && result.IsSuccess) + return false; + return true; + } + + public override string GetResultText () + { + var test = result; + var text = test.Name; + if (test.Executed) + text += " (" + test.Duration.ToString ("##0.###") + "s)"; + if (!test.IsSuccess) + { + text += "\n"; + if (!string.IsNullOrEmpty (test.Message)) + { + text += "---\n"; + text += test.Message.Trim (); + } + if (!string.IsNullOrEmpty (test.StackTrace)) + { + var stackTrace = StackTraceFilter.Filter (test.StackTrace).Trim (); + text += "\n---EXCEPTION---\n" + stackTrace; + } + } + return text.Trim (); + } + + private void OnContextClick (Rect rect) + { + if (rect.Contains (Event.current.mousePosition) && Event.current.type == EventType.ContextClick) + { + Event.current.Use (); + PrintTestContextMenu (); + } + } + + private void PrintTestContextMenu () + { + var m = new GenericMenu (); + var multilineSelection = SelectedLines.Count () > 1; + if (multilineSelection) + { + m.AddItem (guiRunSelected, + false, + data => RunTests (SelectedLines.Select (line => line.test.TestName).ToArray ()), + ""); + } + if (!string.IsNullOrEmpty (fullName)) + { + m.AddItem (guiRun, + false, + data => RunTests (new[] { test.TestName }), + ""); + } + if (!multilineSelection) + { + m.AddSeparator (""); + + m.AddItem (guiOpenInEditor, + false, + data => GuiHelper.OpenInEditor (result, false), + ""); + } + m.ShowAsContext (); + } + + private void OnLeftMouseButtonClick (Rect rect) + { + if (rect.Contains (Event.current.mousePosition) && Event.current.type == EventType.MouseDown && Event.current.button == 0) + { + OnSelect (); + if (Event.current.clickCount == 2 && SelectedLines.Count == 1) + { + GuiHelper.OpenInEditor (result, true); + } + } + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs.meta new file mode 100644 index 0000000..5f6cf25 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/TestLine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cfe0c7d95a79d374e9121633c719241e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs new file mode 100644 index 0000000..dedbbac --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Core; +using UnityEditor; +using UnityEngine; +using Event = UnityEngine.Event; + +namespace UnityTest +{ + public abstract class UnitTestRendererLine : IComparable + { + public static Action RunTest; + public static List SelectedLines; + + protected static bool refresh; + + protected static GUIContent guiRunSelected = new GUIContent ("Run Selected"); + protected static GUIContent guiRun = new GUIContent ("Run"); + protected static GUIContent guiTimeoutIcon = new GUIContent (Icons.stopwatchImg, "Timeout"); + + protected string uniqueId; + protected internal string fullName; + protected string renderedName; + protected internal Test test; + + protected UnitTestRendererLine ( Test test ) + { + this.fullName = test.TestName.FullName; + this.renderedName = test.TestName.Name; + this.uniqueId = test.TestName.UniqueName; + + this.test = test; + } + + public int CompareTo (UnitTestRendererLine other) + { + return uniqueId.CompareTo (other.uniqueId); + } + + public bool Render (RenderingOptions options) + { + refresh = false; + EditorGUIUtility.SetIconSize (new Vector2 (15, 15)); + Render (0, options); + EditorGUIUtility.SetIconSize (Vector2.zero); + return refresh; + } + + protected internal virtual void Render (int indend, RenderingOptions options) + { + EditorGUILayout.BeginHorizontal (); + GUILayout.Space (indend * 10); + DrawLine (SelectedLines.Contains (this), options); + EditorGUILayout.EndHorizontal (); + } + + protected void OnSelect () + { + if (!Event.current.control) SelectedLines.Clear (); + + if (Event.current.control && SelectedLines.Contains (this)) + SelectedLines.Remove (this); + else + SelectedLines.Add (this); + refresh = true; + } + + protected abstract void DrawLine ( bool isSelected, RenderingOptions options ); + protected internal abstract TestResultState? GetResult (); + protected internal abstract bool IsVisible (RenderingOptions options); + + public void RunTests (object[] testObjectsList) + { + RunTest (new TestFilter () { objects = testObjectsList }); + } + + public void RunTests ( string[] testList ) + { + RunTest (new TestFilter (){names = testList}); + } + + public void RunSelectedTests () + { + RunTest (new TestFilter () { objects = SelectedLines.Select (line => line.test.TestName).ToArray () }); + } + + public virtual string GetResultText () + { + return renderedName; + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs.meta new file mode 100644 index 0000000..6c73d20 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Renderer/UnitTestRendererLine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fddb568bfa3ed03438d5c482ea8c6aea +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner.meta new file mode 100644 index 0000000..a253f99 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 615921b0760fc0c4eaf10b7c88add37b +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs new file mode 100644 index 0000000..1b52f50 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + [InitializeOnLoad] + public partial class UnitTestView + { + static UnitTestView () + { + if (Instance != null && Instance.runOnRecompilation) + EnableBackgroundRunner (true); + } + + #region Background runner + + private static float nextCheck; + private static string uttRecompile = "UTT-recompile"; + + public static void EnableBackgroundRunner ( bool enable ) + { + EditorApplication.update -= BackgroudRunner; + + if (enable) + { + EditorApplication.update += BackgroudRunner; + nextCheck = 0; + } + } + + private static void BackgroudRunner () + { + if (EditorApplication.isPlayingOrWillChangePlaymode) return; + if (!Instance.runOnRecompilation) EnableBackgroundRunner (false); + if (EditorApplication.isCompiling) + { + EditorPrefs.SetString (uttRecompile, Application.dataPath); + EditorApplication.update -= BackgroudRunner; + return; + } + + var t = Time.realtimeSinceStartup; + if (t < nextCheck) return; + nextCheck = t + 0.5f; + + if (EditorPrefs.HasKey (uttRecompile)) + { + var recompile = EditorPrefs.GetString (uttRecompile); + if (recompile == Application.dataPath) + { + Instance.RunTests (); + Instance.Repaint (); + } + EditorPrefs.DeleteKey (uttRecompile); + nextCheck = 0; + } + } + #endregion + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs.meta new file mode 100644 index 0000000..84da919 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/BackgroundRunner.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c0ef055bc08798f448b1adba9948e351 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs new file mode 100644 index 0000000..561e32d --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs @@ -0,0 +1,162 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.Mdb; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; + +namespace UnityTest +{ + public static class GuiHelper + { + public static Texture GetIconForResult (TestResultState resultState) + { + switch (resultState) + { + case TestResultState.Success: + return Icons.successImg; + case TestResultState.Failure: + case TestResultState.Error: + return Icons.failImg; + case TestResultState.Ignored: + case TestResultState.Skipped: + return Icons.ignoreImg; + case TestResultState.Inconclusive: + case TestResultState.Cancelled: + case TestResultState.NotRunnable: + return Icons.inconclusiveImg; + default: + return Icons.unknownImg; + } + } + + public static Texture GetIconForResult ( TestResult.ResultType resultState ) + { + switch (resultState) + { + case TestResult.ResultType.Success: + return Icons.successImg; + case TestResult.ResultType.Timeout: + case TestResult.ResultType.Failed: + case TestResult.ResultType.FailedException: + return Icons.failImg; + case TestResult.ResultType.Ignored: + return Icons.ignoreImg; + case TestResult.ResultType.NotRun: + default: + return Icons.unknownImg; + } + } + + private static int ExtractSourceFileLine(string stackTrace) + { + int line = 0; + if (!string.IsNullOrEmpty(stackTrace)) + { + var regEx = new Regex(@".* in (?'path'.*):(?'line'\d+)"); + var matches = regEx.Matches(stackTrace); + for (int i = 0; i < matches.Count; i++) + { + line = int.Parse(matches[i].Groups["line"].Value); + if (line != 0) + break; + } + } + return line; + } + + private static string ExtractSourceFilePath(string stackTrace) + { + string path = ""; + if (!string.IsNullOrEmpty(stackTrace)) + { + var regEx = new Regex(@".* in (?'path'.*):(?'line'\d+)"); + var matches = regEx.Matches(stackTrace); + for (int i = 0; i < matches.Count; i++) + { + path = matches[i].Groups["path"].Value; + if (path != "") + break; + } + } + return path; + } + + public static void OpenInEditor(UnitTestResult test, bool openError) + { + + var sourceFilePath = ExtractSourceFilePath(test.StackTrace); + var sourceFileLine = ExtractSourceFileLine(test.StackTrace); + + if (!openError || sourceFileLine == 0 || string.IsNullOrEmpty (sourceFilePath)) + { + var sp = GetSequencePointOfTest(test); + if (sp != null) + { + sourceFileLine = sp.StartLine; + sourceFilePath = sp.Document.Url; + } + } + + OpenInEditorInternal(sourceFilePath, sourceFileLine); + } + + private static SequencePoint GetSequencePointOfTest(UnitTestResult test) + { + var readerParameters = new ReaderParameters + { + ReadSymbols = true, + SymbolReaderProvider = new MdbReaderProvider (), + ReadingMode = ReadingMode.Immediate + }; + + var assemblyDefinition = AssemblyDefinition.ReadAssembly (test.Test.AssemblyPath, readerParameters); + var classModule = assemblyDefinition.MainModule.Types.Single (t => t.FullName == test.Test.FullClassName); + + var methods = classModule.Methods; + MethodDefinition method = null; + while(classModule.BaseType != null) + { + methods = classModule.Methods; + if(methods.Any(t => t.Name == test.Test.MethodName)) + { + method = classModule.Methods.First(t => t.Name == test.Test.MethodName); + break; + } + classModule = classModule.BaseType as TypeDefinition; + } + if(method !=null) + { + var sp = method.Body.Instructions.First (i => i.SequencePoint != null).SequencePoint; + return sp; + } + return null; + } + + private static void OpenInEditorInternal (string filename, int line) + { + InternalEditorUtility.OpenFileAtLineExternal (filename, line); + } + + public static bool GetConsoleErrorPause () + { + Assembly assembly = Assembly.GetAssembly (typeof (SceneView)); + Type type = assembly.GetType ("UnityEditorInternal.LogEntries"); + PropertyInfo method = type.GetProperty ("consoleFlags"); + var result = (int)method.GetValue (new object (), new object[] { }); + return (result & (1 << 2)) != 0; + } + + public static void SetConsoleErrorPause ( bool b ) + { + Assembly assembly = Assembly.GetAssembly (typeof (SceneView)); + Type type = assembly.GetType ("UnityEditorInternal.LogEntries"); + MethodInfo method = type.GetMethod ("SetConsoleFlag"); + method.Invoke (new object (), new object[] { 1 << 2, b }); + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs.meta new file mode 100644 index 0000000..596d39f --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/GuiHelper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b0b95014154ef554485afc9c0316556d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs new file mode 100644 index 0000000..14c9274 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs @@ -0,0 +1,13 @@ +using System; + +namespace UnityTest.UnitTestRunner +{ + public interface ITestRunnerCallback + { + void TestStarted (string fullName); + void TestFinished (ITestResult fullName); + void RunStarted (string suiteName, int testCount); + void RunFinished (); + void RunFinishedException (Exception exception); + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs.meta new file mode 100644 index 0000000..9aea576 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/ITestRunnerCallback.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 45a983e950f22034ba987c6db2a8b216 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs new file mode 100644 index 0000000..2aabadb --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs @@ -0,0 +1,8 @@ +namespace UnityTest +{ + public interface IUnitTestEngine + { + UnitTestRendererLine GetTests (out UnitTestResult[] results, out string[] categories); + void RunTests ( TestFilter filter, UnitTestRunner.ITestRunnerCallback testRunnerEventListener ); + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs.meta new file mode 100644 index 0000000..9eba5da --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/IUnitTestEngine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 96615b7fd2cb32b4dbea04d84cc3f7fb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs new file mode 100644 index 0000000..b799a2c --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs @@ -0,0 +1,20 @@ +using NUnit.Core; + +namespace UnityTest +{ + public static class NUnitExtensions + { + public static UnitTestResult UnitTestResult ( this NUnit.Core.TestResult result ) + { + return new UnitTestResult() + { + Executed = result.Executed, + ResultState = (TestResultState)result.ResultState, + Message = result.Message, + StackTrace = result.StackTrace, + Duration = result.Time, + Test = new UnitTestInfo (result.Test.TestName.TestID.ToString ()), + }; + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs.meta new file mode 100644 index 0000000..00de790 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitExtensions.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7df86c5f85b0f7d4096d6bc23e9a4e01 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs new file mode 100644 index 0000000..dfc3ae8 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using NUnit.Core; +using System.Linq; +using NUnit.Core.Filters; +using UnityEditor; +using UnityEngine; + +namespace UnityTest +{ + public class NUnitTestEngine : IUnitTestEngine + { + static string[] whitelistedAssemblies = + { + "Assembly-CSharp-Editor", + "Assembly-Boo-Editor", + "Assembly-UnityScript-Editor" + }; + private TestSuite testSuite; + + public UnitTestRendererLine GetTests ( out UnitTestResult[] results, out string[] categories ) + { + if (testSuite == null) + { + List assemblies = GetAssembliesWithTests ().Select (a=>a.Location).ToList (); + TestSuite suite = PrepareTestSuite (assemblies); + testSuite = suite; + } + + var resultList = new List (); + var categoryList = new HashSet (); + + UnitTestRendererLine lines = null; + if(testSuite != null) + lines = ParseTestList (testSuite, resultList, categoryList).Single (); + results = resultList.ToArray (); + categories = categoryList.ToArray (); + + return lines; + } + + private UnitTestRendererLine[] ParseTestList ( Test test, List results, HashSet categories ) + { + foreach (string category in test.Categories) categories.Add (category); + + if (test is TestMethod) + { + var result = new UnitTestResult () + { + Test = new UnitTestInfo (test as TestMethod) + }; + + results.Add (result); + return new[] { new TestLine (test as TestMethod, result.Id) }; + } + + GroupLine group = null; + if (test is TestSuite) + group = new GroupLine (test as TestSuite); + + var namespaceList = new List (new []{group}); + + foreach (Test result in test.Tests ) + { + if (result is NamespaceSuite || test is TestAssembly) + namespaceList.AddRange (ParseTestList (result, results, categories)); + else + group.AddChildren (ParseTestList (result, results, categories)); + } + + namespaceList.Sort (); + return namespaceList.ToArray (); + } + + public void RunTests (UnitTestRunner.ITestRunnerCallback testRunnerEventListener) + { + RunTests (TestFilter.Empty, testRunnerEventListener); + } + + public void RunTests ( TestFilter filter, UnitTestRunner.ITestRunnerCallback testRunnerEventListener ) + { + try + { + if (testRunnerEventListener != null) + testRunnerEventListener.RunStarted (testSuite.TestName.FullName, testSuite.TestCount); + + ExecuteTestSuite (testSuite, testRunnerEventListener, filter); + + if (testRunnerEventListener != null) + testRunnerEventListener.RunFinished (); + } + catch (Exception e) + { + Debug.LogException (e); + if (testRunnerEventListener != null) + testRunnerEventListener.RunFinishedException (e); + } + } + + public static Assembly[] GetAssembliesWithTests () + { + var libs = new List (); + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies ()) + { + if(assembly.GetReferencedAssemblies ().All (a => a.Name != "nunit.framework")) continue; + if (assembly.Location.Replace ('\\', '/').StartsWith (Application.dataPath) + || whitelistedAssemblies.Contains (assembly.GetName ().Name)) libs.Add (assembly); + } + return libs.ToArray (); + } + + private TestSuite PrepareTestSuite(List assemblyList) + { + CoreExtensions.Host.InitializeService(); + var testPackage = new TestPackage (PlayerSettings.productName, assemblyList); + var builder = new TestSuiteBuilder(); + TestExecutionContext.CurrentContext.TestPackage = testPackage; + TestSuite suite = builder.Build(testPackage); + return suite; + } + + private void ExecuteTestSuite ( TestSuite suite, UnitTestRunner.ITestRunnerCallback testRunnerEventListener, TestFilter filter ) + { + EventListener eventListener; + if (testRunnerEventListener == null) + eventListener = new NullListener (); + else + eventListener = new TestRunnerEventListener (testRunnerEventListener); + suite.Run(eventListener, GetFilter(filter)); + } + + private ITestFilter GetFilter (TestFilter filter) + { + var nUnitFilter = new AndFilter(); + + if(filter.names != null && filter.names.Length>0) + nUnitFilter.Add ( new SimpleNameFilter(filter.names)); + if (filter.categories != null && filter.categories.Length > 0) + nUnitFilter.Add (new CategoryFilter(filter.categories)); + if (filter.objects != null && filter.objects.Length > 0) + nUnitFilter.Add (new OrFilter (filter.objects.Where (o => o is TestName).Select(o => new NameFilter (o as TestName)).ToArray ())); + return nUnitFilter; + } + + public class TestRunnerEventListener : EventListener + { + private UnitTestRunner.ITestRunnerCallback testRunnerEventListener; + + public TestRunnerEventListener(UnitTestRunner.ITestRunnerCallback testRunnerEventListener) + { + this.testRunnerEventListener = testRunnerEventListener; + } + + public void RunStarted(string name, int testCount) + { + testRunnerEventListener.RunStarted(name, testCount); + } + + public void RunFinished(NUnit.Core.TestResult result) + { + testRunnerEventListener.RunFinished(); + } + + public void RunFinished(Exception exception) + { + testRunnerEventListener.RunFinishedException(exception); + } + + public void TestStarted(NUnit.Core.TestName testName) + { + testRunnerEventListener.TestStarted(testName.FullName); + } + + public void TestFinished(NUnit.Core.TestResult result) + { + testRunnerEventListener.TestFinished(result.UnitTestResult()); + } + + public void SuiteStarted(NUnit.Core.TestName testName) + { + } + + public void SuiteFinished(NUnit.Core.TestResult result) + { + } + + public void UnhandledException(Exception exception) + { + } + + public void TestOutput(NUnit.Core.TestOutput testOutput) + { + } + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs.meta new file mode 100644 index 0000000..241b6f9 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f313d48559bf30145b88ef7f173685c9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs new file mode 100644 index 0000000..f55d0ca --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs @@ -0,0 +1,158 @@ +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityTest.UnitTestRunner; +using Event = UnityEngine.Event; + +namespace UnityTest +{ + public partial class UnitTestView + { + private void UpdateTestInfo ( ITestResult result ) + { + FindTestResult (result.Id).Update (result, false); + } + + private UnitTestResult FindTestResult( string resultId ) + { + var idx = resultList.FindIndex (testResult => testResult.Id == resultId); + if (idx == -1) + { + Debug.LogWarning ("Id not found for test: " + resultId); + return null; + } + return resultList.ElementAt (idx); + } + + private void RunTests () + { + var filter = new TestFilter(); + var categories = GetSelectedCategories (); + if (categories != null && categories.Length > 0) + filter.categories = categories; + RunTests(filter); + } + + private void RunTests ( TestFilter filter ) + { + if (runTestOnANewScene) + { + if (autoSaveSceneBeforeRun) EditorApplication.SaveScene (); + if (!EditorApplication.SaveCurrentSceneIfUserWantsTo ()) return; + } + + string currentScene = null; + int undoGroup = -1; + if(runTestOnANewScene) + currentScene = OpenNewScene (); + else + undoGroup = RegisterUndo (); + + StartTestRun (filter, new TestRunnerEventListener (UpdateTestInfo)); + + if (runTestOnANewScene) + LoadPreviousScene (currentScene); + else + PerformUndo (undoGroup); + } + + private string OpenNewScene () + { + var currentScene = EditorApplication.currentScene; + if (runTestOnANewScene) + EditorApplication.NewScene (); + return currentScene; + } + + private void LoadPreviousScene ( string currentScene ) + { + if (!string.IsNullOrEmpty (currentScene)) + EditorApplication.OpenScene (currentScene); + else + EditorApplication.NewScene (); + + if (Event.current != null) + GUIUtility.ExitGUI (); + } + + public void StartTestRun ( TestFilter filter, ITestRunnerCallback eventListener) + { + var callbackList = new TestRunnerCallbackList (); + if (eventListener != null) callbackList.Add (eventListener); + testEngine.RunTests ( filter, callbackList ); + } + + private static int RegisterUndo () + { +#if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 + Undo.RegisterSceneUndo ("UnitTestRunSceneSave"); + return -1; +#else + return Undo.GetCurrentGroup (); +#endif + } + + private static void PerformUndo (int undoGroup) + { + EditorUtility.DisplayProgressBar ("Undo", "Reverting changes to the scene", 0); + var undoStartTime = DateTime.Now; +#if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 + Undo.PerformUndo (); +#else + Undo.RevertAllDownToGroup (undoGroup); +#endif + if ((DateTime.Now - undoStartTime).Seconds > 1) + Debug.LogWarning ("Undo after unit test run took " + (DateTime.Now - undoStartTime).Seconds + " seconds. Consider running unit tests on a new scene for better performance."); + EditorUtility.ClearProgressBar (); + } + + public class TestRunnerEventListener : ITestRunnerCallback + { + private Action updateCallback; + + public TestRunnerEventListener ( Action updateCallback ) + { + this.updateCallback = updateCallback; + } + + public void TestStarted (string fullName) + { + EditorUtility.DisplayProgressBar ("Unit Tests Runner", fullName, 1); + } + + public void TestFinished (ITestResult result) + { + updateCallback (result); + } + + public void RunStarted (string suiteName, int testCount) + { + } + + public void RunFinished () + { + EditorUtility.ClearProgressBar (); + } + + public void RunFinishedException (Exception exception) + { + RunFinished (); + } + } + + [MenuItem ("Unity Test Tools/Unit Test Runner %#&u")] + public static void ShowWindow () + { + GetWindow (typeof (UnitTestView)).Show (); + } + } + + public class TestFilter + { + public string[] names; + public string[] categories; + public object[] objects; + public static TestFilter Empty = new TestFilter (); + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs.meta new file mode 100644 index 0000000..19127aa --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fbf567afda42eec43a7dbb052d318076 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs new file mode 100644 index 0000000..c2e1b42 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; + +namespace UnityTest.UnitTestRunner +{ + public class TestRunnerCallbackList : ITestRunnerCallback + { + private List callbackList = new List (); + + public void TestStarted (string fullName) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.TestStarted (fullName); + } + } + + public void TestFinished (ITestResult fullName) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.TestFinished (fullName); + } + } + + public void RunStarted (string suiteName, int testCount) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.RunStarted (suiteName, + testCount); + } + } + + public void RunFinished () + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.RunFinished (); + } + } + + public void RunFinishedException (Exception exception) + { + foreach (var unitTestRunnerCallback in callbackList) + { + unitTestRunnerCallback.RunFinishedException (exception); + } + } + + public void Add (ITestRunnerCallback callback) + { + callbackList.Add (callback); + } + + public void Remove (ITestRunnerCallback callback) + { + callbackList.Remove (callback); + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs.meta new file mode 100644 index 0000000..83288fb --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunnerCallbackList.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b7a6cf1b9d1273d4187ba9d5bc91fc30 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs new file mode 100644 index 0000000..108e36c --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs @@ -0,0 +1,97 @@ +using System; +using System.IO; +using System.Linq; +using NUnit.Core; +using System.Text.RegularExpressions; + +namespace UnityTest +{ + [Serializable] + public class UnitTestInfo + { + public string ParamName { get; private set; } + public string MethodName { get; private set; } + public string FullMethodName { get; private set; } + public string ClassName { get; private set; } + public string FullClassName { get; private set; } + public string Namespace { get; private set; } + public string FullName { get; private set; } + public string[] Categories { get; private set; } + public string AssemblyPath { get; private set; } + public string Id { get; private set; } + + public UnitTestInfo ( TestMethod testMethod ) + { + if (testMethod == null) + throw new ArgumentException(); + + MethodName = testMethod.MethodName; + FullMethodName = testMethod.Method.ToString (); + ClassName = testMethod.FixtureType.Name; + FullClassName = testMethod.ClassName; + Namespace = testMethod.Method.ReflectedType.Namespace; + FullName = testMethod.TestName.FullName; + ParamName = ExtractMethodCallParametersString (FullName); + Id = testMethod.TestName.TestID.ToString (); + + Categories = testMethod.Categories.Cast().ToArray(); + + AssemblyPath = GetAssemblyPath (testMethod); + } + + private string GetAssemblyPath (TestMethod testMethod) + { + var parent = testMethod as Test; + var assemblyPath = ""; + while (parent != null) + { + parent = parent.Parent; + if (!(parent is TestAssembly)) continue; + var path = (parent as TestAssembly).TestName.FullName; + if (!File.Exists (path)) continue; + assemblyPath = path; + break; + } + return assemblyPath; + } + + public UnitTestInfo (string id) + { + Id = id; + } + + public override bool Equals ( System.Object obj ) + { + if (!(obj is UnitTestInfo)) return false; + + var testInfo = (UnitTestInfo) obj; + return Id == testInfo.Id; + } + + public static bool operator == ( UnitTestInfo a, UnitTestInfo b ) + { + if (((object)a == null) || ((object)b == null)) return false; + return a.Id == b.Id; + } + + public static bool operator != (UnitTestInfo a, UnitTestInfo b) + { + return !(a == b); + } + + public override int GetHashCode () + { + return Id.GetHashCode (); + } + + static string ExtractMethodCallParametersString (string methodFullName) + { + var match = Regex.Match (methodFullName, @"\((.*)\)"); + string result = ""; + if (match.Groups [1].Success) { + result = match.Groups [1].Captures [0].Value; + } + return result; + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs.meta new file mode 100644 index 0000000..9198408 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestInfo.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 39d532431356ff74cb5a51afef8cc308 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs new file mode 100644 index 0000000..29b2671 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs @@ -0,0 +1,60 @@ +using System; +using UnityEngine; + +namespace UnityTest +{ + [Serializable] + public class UnitTestResult : ITestResult + { + public bool Executed { get; set; } + public string Name { get { return Test.MethodName; } } + public string FullName { get { return Test.FullName; } } + public TestResultState ResultState { get; set; } + public UnitTestInfo Test { get; set; } + public string Id { get { return Test.Id; } } + public double Duration { get; set; } + public string Message { get; set; } + public string StackTrace { get; set; } + + public bool Outdated { get; set; } + + public void Update (ITestResult source, bool outdated) + { + this.ResultState = source.ResultState; + this.Duration = source.Duration; + this.Message = source.Message; + this.StackTrace = source.StackTrace; + this.Executed = source.Executed; + this.Outdated = outdated; + } + + #region Helper methods + + public bool IsFailure + { + get { return ResultState == TestResultState.Failure; } + } + + public bool IsError + { + get { return ResultState == TestResultState.Error; } + } + + public bool IsSuccess + { + get { return ResultState == TestResultState.Success; } + } + + public bool IsInconclusive + { + get { return ResultState == TestResultState.Inconclusive; } + } + + public bool IsIgnored + { + get { return ResultState == TestResultState.Ignored; } + } + + #endregion + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs.meta new file mode 100644 index 0000000..03d07e0 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestResult.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 925cf9f45ea32814da65f61c1ebd7e6f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs new file mode 100644 index 0000000..df8d147 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs @@ -0,0 +1,320 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace UnityTest +{ + [Serializable] + public partial class UnitTestView : EditorWindow + { + private static UnitTestView Instance; + private static IUnitTestEngine testEngine = new NUnitTestEngine (); + + [SerializeField] private List resultList = new List (); + [SerializeField] private string[] availableCategories = null; + [SerializeField] private List foldMarkers = new List (); + [SerializeField] private List selectedLines = new List (); + UnitTestRendererLine testLines; + + #region runner steering vars + private Vector2 testListScroll, testInfoScroll; + private float horizontalSplitBarPosition = 200; + private float verticalSplitBarPosition = 300; + #endregion + + #region runner options vars + private bool optionsFoldout; + private bool filtersFoldout; + private bool runOnRecompilation; + private bool horizontalSplit = true; + private bool autoSaveSceneBeforeRun; + private bool runTestOnANewScene; + #endregion + + #region test filter vars + [SerializeField] private int categoriesMask; + private string testFilter = ""; + private bool showFailed = true; + private bool showIgnored = true; + private bool showNotRun = true; + private bool showSucceeded = true; + private Rect toolbarRect; + #endregion + + #region GUI Contents + private readonly GUIContent guiRunSelectedTestsIcon = new GUIContent (Icons.runImg, "Run selected tests"); + private readonly GUIContent guiRunAllTestsIcon = new GUIContent (Icons.runAllImg, "Run all tests"); + private readonly GUIContent guiRerunFailedTestsIcon = new GUIContent (Icons.runFailedImg, "Rerun failed tests"); + private readonly GUIContent guiOptionButton = new GUIContent ("Options", Icons.gearImg); + private readonly GUIContent guiHideButton = new GUIContent ("Hide", Icons.gearImg); + private readonly GUIContent guiRunOnRecompile = new GUIContent ("Run on recompile", "Run all tests after recompilation"); + private readonly GUIContent guiShowDetailsBelowTests = new GUIContent ("Show details below tests", "Show run details below test list"); + private readonly GUIContent guiRunTestsOnNewScene = new GUIContent ("Run tests on a new scene", "Run tests on a new scene"); + private readonly GUIContent guiAutoSaveSceneBeforeRun = new GUIContent ("Autosave scene", "The runner will automaticall save current scene changes before it starts"); + private readonly GUIContent guiShowSucceededTests = new GUIContent ("Succeeded", Icons.successImg, "Show tests that succeeded"); + private readonly GUIContent guiShowFailedTests = new GUIContent ("Failed", Icons.failImg, "Show tests that failed"); + private readonly GUIContent guiShowIgnoredTests = new GUIContent ("Ignored", Icons.ignoreImg, "Show tests that are ignored"); + private readonly GUIContent guiShowNotRunTests = new GUIContent ("Not Run", Icons.unknownImg, "Show tests that didn't run"); + #endregion + + public UnitTestView () + { + title = "Unit Tests Runner"; + resultList.Clear (); + if (EditorPrefs.HasKey ("UTR-runOnRecompilation")) + { + runOnRecompilation = EditorPrefs.GetBool ("UTR-runOnRecompilation"); + runTestOnANewScene = EditorPrefs.GetBool ("UTR-runTestOnANewScene"); + autoSaveSceneBeforeRun = EditorPrefs.GetBool ("UTR-autoSaveSceneBeforeRun"); + horizontalSplit = EditorPrefs.GetBool ("UTR-horizontalSplit"); + showFailed = EditorPrefs.GetBool ("UTR-showFailed"); + showIgnored = EditorPrefs.GetBool ("UTR-showIgnored"); + showNotRun = EditorPrefs.GetBool ("UTR-showNotRun"); + showSucceeded = EditorPrefs.GetBool ("UTR-showSucceeded"); + } + } + + public void SaveOptions() + { + EditorPrefs.SetBool("UTR-runOnRecompilation", runOnRecompilation); + EditorPrefs.SetBool("UTR-runTestOnANewScene", runTestOnANewScene); + EditorPrefs.SetBool("UTR-autoSaveSceneBeforeRun", autoSaveSceneBeforeRun); + EditorPrefs.SetBool("UTR-horizontalSplit", horizontalSplit); + EditorPrefs.SetBool("UTR-showFailed", showFailed); + EditorPrefs.SetBool("UTR-showIgnored", showIgnored); + EditorPrefs.SetBool("UTR-showNotRun", showNotRun); + EditorPrefs.SetBool("UTR-showSucceeded", showSucceeded); + } + + public void OnEnable () + { + Instance = this; + RefreshTests (); + EnableBackgroundRunner (runOnRecompilation); + } + + public void OnDestroy () + { + Instance = null; + EnableBackgroundRunner (false); + } + + public void Awake () + { + RefreshTests (); + } + + public void OnGUI () + { + GUILayout.Space (10); + EditorGUILayout.BeginVertical (); + + EditorGUILayout.BeginHorizontal (); + + var layoutOptions = new[] { + GUILayout.Width(32), + GUILayout.Height(24) + }; + if (GUILayout.Button (guiRunAllTestsIcon, Styles.buttonLeft, layoutOptions)) + { + RunTests(); + GUIUtility.ExitGUI (); + } + if (GUILayout.Button (guiRunSelectedTestsIcon, Styles.buttonMid, layoutOptions)) + { + testLines.RunSelectedTests (); + } + if (GUILayout.Button (guiRerunFailedTestsIcon, Styles.buttonRight, layoutOptions)) + { + testLines.RunTests (resultList.Where(result => result.IsFailure || result.IsError).Select (l => l.FullName).ToArray ()); + } + + GUILayout.FlexibleSpace (); + + if (GUILayout.Button (optionsFoldout ? guiHideButton : guiOptionButton, GUILayout.Height (24), GUILayout.Width (80))) + { + optionsFoldout = !optionsFoldout; + } + EditorGUILayout.EndHorizontal (); + + if (optionsFoldout) DrawOptions(); + + EditorGUILayout.BeginHorizontal (); + EditorGUILayout.LabelField("Filter:", GUILayout.Width(35)); + testFilter = EditorGUILayout.TextField(testFilter, EditorStyles.textField); + + if (availableCategories != null && availableCategories.Length > 1) + categoriesMask = EditorGUILayout.MaskField (categoriesMask, availableCategories, GUILayout.MaxWidth (90)); + + if (GUILayout.Button (filtersFoldout ? "Hide" : "Advanced", GUILayout.Width (80), GUILayout.Height (15))) + filtersFoldout = !filtersFoldout; + EditorGUILayout.EndHorizontal (); + + if (filtersFoldout) + DrawFilters (); + + if (horizontalSplit) + EditorGUILayout.BeginVertical (); + else + EditorGUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); + + RenderTestList (); + RenderTestInfo (); + + if (horizontalSplit) + EditorGUILayout.EndVertical (); + else + EditorGUILayout.EndHorizontal (); + + EditorGUILayout.EndVertical (); + } + + private string[] GetSelectedCategories () + { + var selectedCategories = new List (); + foreach (var availableCategory in availableCategories) + { + var idx = Array.FindIndex (availableCategories, ( a ) => a == availableCategory); + var mask = 1 << idx; + if ((categoriesMask & mask) != 0) selectedCategories.Add (availableCategory); + } + return selectedCategories.ToArray (); + } + + private void RenderTestList () + { + EditorGUILayout.BeginVertical (Styles.testList); + testListScroll = EditorGUILayout.BeginScrollView (testListScroll, + GUILayout.ExpandWidth (true), + GUILayout.MaxWidth (2000)); + if (testLines != null) + { + var options = new RenderingOptions (); + options.showSucceeded = showSucceeded; + options.showFailed = showFailed; + options.showIgnored = showIgnored; + options.showNotRunned = showNotRun; + options.nameFilter = testFilter; + options.categories = GetSelectedCategories (); + + if (testLines.Render (options)) Repaint (); + } + EditorGUILayout.EndScrollView (); + EditorGUILayout.EndVertical (); + } + + private void RenderTestInfo () + { + var ctrlId = EditorGUIUtility.GetControlID (FocusType.Passive); + var rect = GUILayoutUtility.GetLastRect (); + if (horizontalSplit) + { + rect.y = rect.height + rect.y - 1; + rect.height = 3; + } + else + { + rect.x = rect.width + rect.x - 1; + rect.width = 3; + } + + EditorGUIUtility.AddCursorRect (rect, horizontalSplit ? MouseCursor.ResizeVertical : MouseCursor.ResizeHorizontal); + var e = Event.current; + switch (e.type) + { + case EventType.MouseDown: + if (EditorGUIUtility.hotControl == 0 && rect.Contains (e.mousePosition)) + EditorGUIUtility.hotControl = ctrlId; + break; + case EventType.MouseDrag: + if (EditorGUIUtility.hotControl == ctrlId) + { + horizontalSplitBarPosition -= e.delta.y; + if (horizontalSplitBarPosition < 20) horizontalSplitBarPosition = 20; + verticalSplitBarPosition -= e.delta.x; + if (verticalSplitBarPosition < 20) verticalSplitBarPosition = 20; + Repaint (); + } + + break; + case EventType.MouseUp: + if (EditorGUIUtility.hotControl == ctrlId) + EditorGUIUtility.hotControl = 0; + break; + } + testInfoScroll = EditorGUILayout.BeginScrollView (testInfoScroll, horizontalSplit + ? GUILayout.MinHeight (horizontalSplitBarPosition) + : GUILayout.Width (verticalSplitBarPosition)); + + var text = ""; + if (selectedLines.Any ()) + { + text = selectedLines.First ().GetResultText (); + } + EditorGUILayout.TextArea (text, Styles.info); + + EditorGUILayout.EndScrollView (); + } + + private void DrawFilters () + { + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal (); + showSucceeded = GUILayout.Toggle (showSucceeded, guiShowSucceededTests, GUI.skin.FindStyle (GUI.skin.button.name + "left"), GUILayout.ExpandWidth (true)); + showFailed = GUILayout.Toggle (showFailed, guiShowFailedTests, GUI.skin.FindStyle (GUI.skin.button.name + "mid")); + showIgnored = GUILayout.Toggle (showIgnored, guiShowIgnoredTests, GUI.skin.FindStyle (GUI.skin.button.name + "mid")); + showNotRun = GUILayout.Toggle (showNotRun, guiShowNotRunTests, GUI.skin.FindStyle (GUI.skin.button.name + "right"), GUILayout.ExpandWidth (true)); + EditorGUILayout.EndHorizontal (); + if (EditorGUI.EndChangeCheck()) SaveOptions(); + } + + + + private void DrawOptions () + { + EditorGUI.BeginChangeCheck (); + + EditorGUI.BeginChangeCheck (); + runOnRecompilation = EditorGUILayout.Toggle (guiRunOnRecompile, runOnRecompilation); + if (EditorGUI.EndChangeCheck ()) EnableBackgroundRunner (runOnRecompilation); + + runTestOnANewScene = EditorGUILayout.Toggle (guiRunTestsOnNewScene, runTestOnANewScene); + EditorGUI.BeginDisabledGroup (!runTestOnANewScene); + autoSaveSceneBeforeRun = EditorGUILayout.Toggle (guiAutoSaveSceneBeforeRun, autoSaveSceneBeforeRun); + EditorGUI.EndDisabledGroup (); + horizontalSplit = EditorGUILayout.Toggle (guiShowDetailsBelowTests, horizontalSplit); + + if (EditorGUI.EndChangeCheck ()) + { + SaveOptions(); + } + EditorGUILayout.Space (); + } + + + + private void RefreshTests () + { + UnitTestResult[] newResults; + testLines = testEngine.GetTests (out newResults, out availableCategories); + + foreach (var newResult in newResults) + { + var result = resultList.Where (t => t.Test == newResult.Test && t.FullName == newResult.FullName).ToArray(); + if (result.Count () != 1) continue; + newResult.Update(result.Single(), true); + } + + UnitTestRendererLine.SelectedLines = selectedLines; + UnitTestRendererLine.RunTest = RunTests; + GroupLine.FoldMarkers = foldMarkers; + TestLine.GetUnitTestResult = FindTestResult; + + resultList = new List (newResults); + + Repaint (); + } + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs.meta new file mode 100644 index 0000000..55bd700 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ba152083ecc3cdb4a82881c6a9ae73c1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs b/src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs new file mode 100644 index 0000000..e6f4d7b --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using UnityEditor; +using UnityEngine; + +[TestFixture] +public abstract class UnityUnitTest +{ + public GameObject CreateGameObject () + { + return CreateGameObject (""); + } + + public GameObject CreateGameObject ( string name ) + { + var go = string.IsNullOrEmpty (name) ? new GameObject () : new GameObject (name); + Undo.RegisterCreatedObjectUndo (go,""); + return go; + } + + public GameObject CreatePrimitive ( PrimitiveType type ) + { + var p = GameObject.CreatePrimitive (type); + Undo.RegisterCreatedObjectUndo (p, ""); + return p; + } +} diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs.meta new file mode 100644 index 0000000..0185d4b --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/UnityUnitTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3ec01611d948e574c99a1bd24650a4a9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/UnityTestTools/changelog.txt b/src/Assets/UnityTestTools/changelog.txt new file mode 100644 index 0000000..3145e0b --- /dev/null +++ b/src/Assets/UnityTestTools/changelog.txt @@ -0,0 +1,109 @@ +Version 1.3.2 + +- Fixed integration tests performance issues + +Version 1.3.1 + +- Updated Japanese docs + +Version 1.3 + +Fixes: +(unit tests) +- nUnit will no longer change the Environment.CurrentDirectory when running tests +- fixed issues with asserting GameObject == null +(integration tests) +- fix the issue with passing or failing test in first frame +- fixed bug where ignored tests were still run in ITF +(assertion component) +- fixed resolving properties to include derived types + +Improvements: +(unit tests) +- refactored result renderer +- reenabled Random attribute +- added Category filter +- NSubstitute updated to version 1.7.2 +- result now will be dimmed after recompilation +- running tests in background will now work without having the window focused +- all assemblies in the project referencing 'nunit.framework' will now be included in the test list +(integration tests) +- updated platform exclusion mechanism +- refactored result renderer +- the runner should work even if the runner window is not focused +- added possibility to create integration tests from code +- the runner will now always run in background (if the window is not focused) +(assertion component) +- added API for creating assertions from code +- added new example +(common) +- GUI improvements +- you no longer need to change the path to icons when moving the tools to another directory +- made test details/results resizeable and scrollable +- added character escape for generated result XML + +Version 1.2.1 +- Fixed Unit Test Batch runner + +Version 1.2 +Fixes: +- Windows Store related compilation issues +- other +Improvements: +(unit tests) +- unit test runner can run in background now without having the runner window open +- unit test batch runner can take a result file path as a parameter +- changed undo system for unit test runner and UnityUnitTest base class +- execution time in now visible in test details +- fixed a bug with tests that inherit from a base test class +(integration tests) +- added hierarchical structure for integration tests +- added Player runner to automate running integration tests on platforms +- Integration tests batch runner can take a result directory as a parameter +- Integration tests batch runner can run tests on platforms +- results are rendered in a player +(assertion component) +- changed default failure messages +- it's possible to override failure action on comparer failure +- added code stripper for assertions. +- vast performance improvement +- fixed bugs +Other: +- "Hide in hierarchy" option was removed from integration test runner +- "Focus on selection" option was removed from integration test runner +- "Hide test runner" option was removed from integration test runner +- result files for unit tests and integration tests are now not generated when running tests from the editor +- UI improvements +- removed UnityScript and Boo examples +- WP8 compatibility fixes + +Version 1.1.1 +Other: +- Documentation in Japanese was added + +Version 1.1 +Fixes: +- fixed display error that happened when unit test class inherited from another TestFixture class +- fixed false positive result when "Succeed on assertions" was checked and no assertions were present in the test +- fixed XmlResultWriter to be generate XML file compatible with XSD scheme +- XmlResultWriter result writer was rewritten to remove XML libraries dependency +- Fixed an issue with a check that should be executed once after a specified frame in OnUpdate. +- added missing file UnityUnitTest.cs +Improvements: +- Added Japanese translation of the documentation +- ErrorPause value will be reverted to previous state after test run finishes +- Assertion Component will not copy reference to a GameObject if the GameObject is the same as the component is attached to. Instead, it will set the reference to the new GameObject. +- Integration tests batch runner can now run multiple scenes +- Unit test runner will now include tests written in UnityScript and Boo +- Unit tests will not run automatically if the compilation failes +- Added scene auto-save option to the Unit Test Runner +Other: +- changed icons +- restructured project files +- moved XmlResultWriter to Common folder +- added UnityScript and Boo unit tests examples +- added more unit tests examples +- Test runners visual adjustments + +Version 1.0 +- Initial release \ No newline at end of file diff --git a/src/Assets/UnityTestTools/changelog.txt.meta b/src/Assets/UnityTestTools/changelog.txt.meta new file mode 100644 index 0000000..8c28fef --- /dev/null +++ b/src/Assets/UnityTestTools/changelog.txt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 29b770d9107643740b69cb98b00430aa +TextScriptImporter: + userData: diff --git a/src/Assets/quickgraph4unity.meta b/src/Assets/quickgraph4unity.meta new file mode 100644 index 0000000..aeed3a7 --- /dev/null +++ b/src/Assets/quickgraph4unity.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 65cd09552d83d4bd88d57e7cd286bf82 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor.meta b/src/Assets/quickgraph4unity/Editor.meta new file mode 100644 index 0000000..af54a4f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: f6e6e086edcd7408a8a7f294e2c16ad8 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests.meta b/src/Assets/quickgraph4unity/Editor/Tests.meta new file mode 100644 index 0000000..1e4c905 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: d95440520d3484083bedeacd296fa32c +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests.meta new file mode 100644 index 0000000..b8bb444 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: af4bc4c61b3ed46f0b8821afec1eaccd +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs new file mode 100755 index 0000000..71d8986 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs @@ -0,0 +1,150 @@ +using System; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; +using QuickGraph; + +namespace QuickGraph { + public class NamedVertex : IdentifiableVertex { + private string name; + public NamedVertex(string id) + : base(id) { } + + [System.Xml.Serialization.XmlAttribute] + public string Name { + get { return this.name; } + set { this.name = value; } + } + + public sealed class Factory : IIdentifiableVertexFactory { + public NamedVertex CreateVertex(string id) { + return new NamedVertex(id); + } + } + } + + public class NamedEdge : IdentifiableEdge { + private string name; + public NamedEdge(string id, NamedVertex source, NamedVertex target) + : base(id, source, target) { } + + [System.Xml.Serialization.XmlAttribute] + public string Name { + get { return this.name; } + set { this.name = value; } + } + + public sealed class Factory : IIdentifiableEdgeFactory { + public NamedEdge CreateEdge(string id, NamedVertex source, NamedVertex target) { + return new NamedEdge(id, source, target); + } + } + } + + public class AdjacencyGraphFactory + { + private static AdjacencyGraph> CreateGraph() + { + return new AdjacencyGraph>(false); + } + + public static Type CreateType() + { + return typeof(AdjacencyGraph>); + } + + [Factory] + public AdjacencyGraph> Empty() + { + return CreateGraph(); + } + + [Factory] + public AdjacencyGraph> NoEdges() + { + AdjacencyGraph> g = CreateGraph(); + GraphFactory.NoEdges(g); + return g; + } + + [Factory] + public AdjacencyGraph> Loop() + { + AdjacencyGraph> g = CreateGraph(); + GraphFactory.Loop(g); + return g; + } + + [Factory] + public AdjacencyGraph> LoopDouble() + { + AdjacencyGraph> g = CreateGraph(); + GraphFactory.LoopDouble(g); + return g; + } + + [Factory] + public AdjacencyGraph> FileDependency() + { + AdjacencyGraph> g = CreateGraph(); + GraphFactory.FileDependency(g); + return g; + } + + [Factory] + public AdjacencyGraph> RegularLattice10x10() + { + AdjacencyGraph> g = CreateGraph(); + GraphFactory.RegularLattice(10, 10, g); + return g; + } + + [Factory] + public AdjacencyGraph> Simple() + { + AdjacencyGraph> g = CreateGraph(); + GraphFactory.Simple(g); + return g; + } + + [Factory] + public AdjacencyGraph> UnBalancedFlow() + { + AdjacencyGraph> g = CreateGraph(); + GraphFactory.UnBalancedFlow(g); + return g; + } + + [Factory] + public AdjacencyGraph SimpleIdentifiable() + { + return Convert(Simple()); + } + + private static AdjacencyGraph Convert(AdjacencyGraph> g) + { + AdjacencyGraph cg = + new AdjacencyGraph(); + System.Collections.Generic.Dictionary vertices = new System.Collections.Generic.Dictionary(g.VertexCount); + foreach (string v in g.Vertices) + { + NamedVertex iv = new NamedVertex(v); + iv.Name = v; + vertices.Add(v, iv); + cg.AddVertex(iv); + } + int count = 0; + foreach(Edge e in g.Edges) + { + NamedEdge edge = new NamedEdge( + count.ToString(), + vertices[e.Source], + vertices[e.Target] + ); + edge.Name = edge.Source.Name + "->" + edge.Target.Name; + cg.AddEdge(edge); + count++; + } + return cg; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs.meta new file mode 100644 index 0000000..52e2872 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/AdjacencyGraphFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 54a8b300bedb542f4961c3df8140afad +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms.meta new file mode 100644 index 0000000..cf447bf --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 2857065f179244e80a20e67ed424f736 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs new file mode 100755 index 0000000..debd940 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs @@ -0,0 +1,10 @@ +using System; +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms +{ + [TestFixture] + public class CentralityApproximationAlgorithmTest + { + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs.meta new file mode 100644 index 0000000..98e2abd --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/CentralityApproximationAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1345a7aef9b3643eabe2a9aef9d28db0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation.meta new file mode 100644 index 0000000..bf0eec3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 4f092405f9d2542239adf313b18f0eec +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs new file mode 100755 index 0000000..b379bac --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs @@ -0,0 +1,95 @@ +using System; +using System.IO; +using System.Collections.Generic; + +using QuickGraph.Unit; + +using QuickGraph.Algorithms.Condensation; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms.Condensation +{ + [PexClass] + [TypeFixture(typeof(IMutableVertexAndEdgeListGraph>))] + [TypeFactory(typeof(AdjacencyGraphFactory))] + [TypeFactory(typeof(BidirectionalGraphFactory))] + public partial class StronglyConnectedCondensationGraphAlgorithmTest + { + private CondensationGraphAlgorithm,AdjacencyGraph>> algo; + [Test, PexMethod] + public void CondensateAndCheckVertexCount( + [PexAssumeNotNull]IVertexAndEdgeListGraph> g) + { + this.algo = new CondensationGraphAlgorithm, AdjacencyGraph>>(g); + algo.Compute(); + CheckVertexCount(g); + } + + [Test, PexMethod] + public void CondensateAndCheckEdgeCount( + [PexAssumeNotNull]IVertexAndEdgeListGraph> g) + { + this.algo = new CondensationGraphAlgorithm, AdjacencyGraph>>(g); + algo.Compute(); + CheckEdgeCount(g); + } + [Test, PexMethod] + public void CondensateAndCheckComponentCount( + [PexAssumeNotNull]IVertexAndEdgeListGraph> g) + { + this.algo = new CondensationGraphAlgorithm, AdjacencyGraph>>(g); + algo.Compute(); + CheckComponentCount(g); + } + [Test, PexMethod] + public void CondensateAndCheckDAG( + [PexAssumeNotNull]IVertexAndEdgeListGraph> g) + { + this.algo = new CondensationGraphAlgorithm, AdjacencyGraph>>(g); + algo.Compute(); + CheckDAG(g); + } + + private void CheckVertexCount( + IVertexAndEdgeListGraph> g) + { + int count = 0; + foreach (AdjacencyGraph> vertices in this.algo.CondensatedGraph.Vertices) + count += vertices.VertexCount; + Assert.AreEqual(g.VertexCount, count, "VertexCount does not match"); + } + + private void CheckEdgeCount(IVertexAndEdgeListGraph> g) + { + // check edge count + int count = 0; + foreach (CondensatedEdge, AdjacencyGraph>> edges in this.algo.CondensatedGraph.Edges) + count += edges.Edges.Count; + foreach (AdjacencyGraph> vertices in this.algo.CondensatedGraph.Vertices) + count += vertices.EdgeCount; + Assert.AreEqual(g.EdgeCount, count, "EdgeCount does not match"); + } + + + private void CheckComponentCount(IVertexAndEdgeListGraph> g) + { + // check number of vertices = number of storngly connected components + int components = AlgoUtility.StronglyConnectedComponents>(g, new Dictionary()); + Assert.AreEqual(components, algo.CondensatedGraph.VertexCount, "ComponentCount does not match"); + } + + private void CheckDAG(IVertexAndEdgeListGraph> g) + { + // check it's a dag + try + { + AlgoUtility.TopologicalSort(this.algo.CondensatedGraph); + } + catch (NonAcyclicGraphException) + { + Assert.Fail("Graph is not a DAG."); + } + + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs.meta new file mode 100644 index 0000000..75a5989 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/StronglyConnectedCondensationGraphAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 13350b50ef88c4b9bb3755dfcd9282bf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs new file mode 100755 index 0000000..10c210f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using System.Collections.Generic; + +using QuickGraph.Unit; + +using QuickGraph.Algorithms.Condensation; + +namespace QuickGraph.Algorithms.Condensation +{ + [TypeFixture(typeof(IMutableVertexAndEdgeListGraph>))] + [TypeFactory(typeof(AdjacencyGraphFactory))] + [TypeFactory(typeof(BidirectionalGraphFactory))] + public class WeaklyConnectedCondensationGraphAlgorithmTest + { + private CondensationGraphAlgorithm, AdjacencyGraph>> algo; + [Test] + public void CondensateAndCheckVertexCount(IVertexAndEdgeListGraph> g) + { + this.algo = new CondensationGraphAlgorithm, AdjacencyGraph>>(g); + this.algo.StronglyConnected = false; + algo.Compute(); + CheckVertexCount(g); + } + + [Test] + public void CondensateAndCheckEdgeCount(IVertexAndEdgeListGraph> g) + { + this.algo = new CondensationGraphAlgorithm, AdjacencyGraph>>(g); + this.algo.StronglyConnected = false; + algo.Compute(); + CheckEdgeCount(g); + } + [Test] + public void CondensateAndCheckComponentCount(IVertexAndEdgeListGraph> g) + { + this.algo = new CondensationGraphAlgorithm, AdjacencyGraph>>(g); + this.algo.StronglyConnected = false; + algo.Compute(); + CheckComponentCount(g); + } + + private void CheckVertexCount(IVertexAndEdgeListGraph> g) + { + int count = 0; + foreach (AdjacencyGraph> vertices in this.algo.CondensatedGraph.Vertices) + count += vertices.VertexCount; + Assert.AreEqual(g.VertexCount, count, "VertexCount does not match"); + } + + private void CheckEdgeCount(IVertexAndEdgeListGraph> g) + { + // check edge count + int count = 0; + foreach (CondensatedEdge, AdjacencyGraph>> edges in this.algo.CondensatedGraph.Edges) + count += edges.Edges.Count; + foreach (AdjacencyGraph> vertices in this.algo.CondensatedGraph.Vertices) + count += vertices.EdgeCount; + Assert.AreEqual(g.EdgeCount, count, "EdgeCount does not match"); + } + + + private void CheckComponentCount(IVertexAndEdgeListGraph> g) + { + // check number of vertices = number of storngly connected components + int components = AlgoUtility.WeaklyConnectedComponents>(g, new Dictionary()); + Assert.AreEqual(components, algo.CondensatedGraph.VertexCount, "ComponentCount does not match"); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs.meta new file mode 100644 index 0000000..03ae468 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Condensation/WeaklyConnectedCondensationGraphTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 46599d0997e094ccc8180a58a79f9c47 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs new file mode 100755 index 0000000..0108cbf --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs @@ -0,0 +1,41 @@ +using System; +using QuickGraph.Unit; +using QuickGraph.Algorithms.Matrix; + +namespace QuickGraph.Algorithms +{ + public class DoubleDenseMatrixFactory + { + [Factory] + public DoubleDenseMatrix Identity2() + { + return DoubleDenseMatrix.Identity(2); + } + + [Factory] + public DoubleDenseMatrix Zero2() + { + return new DoubleDenseMatrix(2, 2); + } + + [Factory] + public DoubleDenseMatrix Chain() + { + DoubleDenseMatrix m = new DoubleDenseMatrix(3, 3); + m[0, 1] = 1; + m[1, 2] = 1; + return m; + } + + [Factory] + public DoubleDenseMatrix Evenly23() + { + DoubleDenseMatrix m = new DoubleDenseMatrix(2, 3); + int k = 0; + for (int i = 0; i < m.RowCount; ++i) + for (int j = 0; j < m.ColumnCount; ++j) + m[i, j] = k++; + return m; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs.meta new file mode 100644 index 0000000..0724e26 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f4a809053e1904678af346c59a3f69e7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs new file mode 100755 index 0000000..c772f64 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs @@ -0,0 +1,34 @@ +using System; +using QuickGraph.Unit; +using QuickGraph.Algorithms.Matrix; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms +{ + [TestFixture, PexClass] + public partial class DoubleDenseMatrixTest + { + [PexMethod] + public void ToString([PexAssumeNotNull]DoubleDenseMatrix matrix) + { + Console.WriteLine(matrix); + } + + [PexMethod] + public void WriteMatrix([PexAssumeNotNull]DoubleDenseMatrix matrix) + { + matrix.WriteMatrix(Console.Out); + } + + [PexMethod] + public void SelfSimilarity([PexAssumeNotNull]DoubleDenseMatrix matrix) + { + Console.WriteLine("Matrix"); + matrix.WriteMatrix(Console.Out); + + Console.WriteLine("Similarity"); + DoubleDenseMatrix similarity = DoubleDenseMatrix.Similarity(matrix, matrix, 0.001); + similarity.WriteMatrix(Console.Out); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs.meta new file mode 100644 index 0000000..01ac988 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/DoubleDenseMatrixTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e80a3d8fe35aa4143964ca36035bf41d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs new file mode 100755 index 0000000..64874de --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms +{ +// [TypeFixture(typeof(IVertexAndEdgeListGraph>))] +// [TypeFactory(typeof(AdjacencyGraphFactory))] +// [TypeFactory(typeof(BidirectionalGraphFactory))] + public class EulerianTrailAlgorithmTest + { + [Test] + public void ComputeTrail(IMutableVertexAndEdgeListGraph> g) + { + if (g.VertexCount == 0) + return; + + GraphConsoleSerializer.DisplayGraph(g); + + int oddCount = 0; + foreach (string v in g.Vertices) + if (g.OutDegree(v) % 2 == 0) + oddCount++; + + int circuitCount = EulerianTrailAlgorithm>.ComputeEulerianPathCount(g); + if (circuitCount == 0) + return; + + EulerianTrailAlgorithm> trail = new EulerianTrailAlgorithm>(g); + trail.AddTemporaryEdges(new EdgeFactory()); + trail.Compute(); + ICollection>> trails = trail.Trails(); + trail.RemoveTemporaryEdges(); + + Console.WriteLine("trails: {0}", trails.Count); + int index = 0; + foreach (ICollection> t in trails) + { + Console.WriteLine("trail {0}", index++); + foreach (Edge edge in t) + Console.WriteLine("\t{0}", t); + } + + // lets make sure all the edges are in the trail + Dictionary, GraphColor> edgeColors = new Dictionary, GraphColor>(g.EdgeCount); + foreach (Edge edge in g.Edges) + edgeColors.Add(edge, GraphColor.White); + foreach (ICollection> t in trails) + foreach (Edge edge in t) + CollectionAssert.ContainsKey(edgeColors, edge); + + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs.meta new file mode 100644 index 0000000..b240d8c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/EulerianTrailAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 052a825892a71412aa31e7e2f65edfa2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow.meta new file mode 100644 index 0000000..dc5d9df --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 630609d0f8091458bad5ffe2468cea1b +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs new file mode 100755 index 0000000..71c0fac --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs @@ -0,0 +1,96 @@ +using System; +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + [TypeFixture(typeof(IMutableVertexAndEdgeListGraph>))] + [TypeFactory(typeof(AdjacencyGraphFactory))] + [TypeFactory(typeof(BidirectionalGraphFactory))] + public class AllVerticesGraphAugmentorAlgorithmTest + { + private AllVerticesGraphAugmentorAlgorithm> augmentor; + + public void SetUp(IMutableVertexAndEdgeListGraph> g) + { + this.augmentor = new AllVerticesGraphAugmentorAlgorithm>( + g, + new StringVertexFactory(), + new EdgeFactory() + ); + } + + [TearDown] + public void TearDown() + { + if (this.augmentor != null) + { + this.augmentor.Rollback(); + this.augmentor = null; + } + } + + [Test] + public void AddSuperSourceAndSink(IMutableVertexAndEdgeListGraph> g) + { + SetUp(g); + int vertexCount = g.VertexCount; + this.augmentor.Compute(); + + Assert.AreEqual(vertexCount + 2, g.VertexCount); + Assert.IsTrue(g.ContainsVertex(this.augmentor.SuperSource)); + Assert.IsTrue(g.ContainsVertex(this.augmentor.SuperSink)); + } + + [Test] + public void AddAndRemove(IMutableVertexAndEdgeListGraph> g) + { + SetUp(g); + int vertexCount = g.VertexCount; + int edgeCount = g.EdgeCount; + this.augmentor.Compute(); + this.augmentor.Rollback(); + Assert.AreEqual(g.VertexCount, vertexCount); + Assert.AreEqual(g.EdgeCount, edgeCount); + } + + [Test] + public void AddAndVerifySourceConnected(IMutableVertexAndEdgeListGraph> g) + { + SetUp(g); + this.augmentor.Compute(); + foreach (string v in g.Vertices) + { + if (v == this.augmentor.SuperSource) + continue; + if (v == this.augmentor.SuperSink) + continue; + Assert.IsTrue(g.ContainsEdge(this.augmentor.SuperSource, v)); + } + } + + [Test] + public void AddAndVerifySinkConnected(IMutableVertexAndEdgeListGraph> g) + { + SetUp(g); + this.augmentor.Compute(); + foreach (string v in g.Vertices) + { + if (v == this.augmentor.SuperSink) + continue; + if (v == this.augmentor.SuperSink) + continue; + Assert.IsTrue(g.ContainsEdge(v, this.augmentor.SuperSink)); + } + } + + private sealed class StringVertexFactory : IVertexFactory + { + private int id = 0; + + public string CreateVertex() + { + return "Super"+(++id).ToString(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs.meta new file mode 100644 index 0000000..4437a05 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5167ef1785bdc456f8476fa8211c4f3e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree.meta new file mode 100644 index 0000000..b39ac2a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 9c59136148ee84faeb7a5dd5da2af775 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs new file mode 100755 index 0000000..6b892e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using QuickGraph.Algorithms.Observers; + +namespace QuickGraph.Algorithms.MinimumSpanningTree +{ + [TypeFixture(typeof(IUndirectedGraph>))] + [TypeFactory(typeof(UndirectedGraphFactory))] + public class PrimMinimumSpanningTreeAlgorithmTest + { + [Test] + public void Compute(IUndirectedGraph> g) + { + Dictionary, double> distances = new Dictionary,double>(); + foreach(Edge edge in g.Edges) + distances.Add(edge, 1); + PrimMinimumSpanningTreeAlgorithm> prim = new PrimMinimumSpanningTreeAlgorithm>(g, distances); + + VertexPredecessorRecorderObserver> predecessors = new VertexPredecessorRecorderObserver>(); + predecessors.Attach(prim); + prim.Compute(); + + foreach (string v in g.Vertices) + { + Edge edge; + if (predecessors.VertexPredecessors.TryGetValue(v, out edge)) + Console.WriteLine("{0}: {1}", v, edge); + else + Console.WriteLine("{0}", v); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs.meta new file mode 100644 index 0000000..dcd19eb --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e5d26f29409174e25a7e6663bab5253c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks.meta new file mode 100644 index 0000000..93d8e38 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: eeca027c2f6a642c4a01dca6e21a9854 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs new file mode 100755 index 0000000..22a3953 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs @@ -0,0 +1,42 @@ +using System; +using QuickGraph.Unit; +using QuickGraph.Algorithms.RandomWalks; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [TestFixture] + public class CyclePoppingRandomTreeAlgorithmTest + { + private CyclePoppingRandomTreeAlgorithm> target = null; + + [Test] + public void IsolatedVertex() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex(0); + + target = new CyclePoppingRandomTreeAlgorithm>(g); + target.RandomTree(); + } + + [Test] + public void RootIsNotAccessible() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex(0); + g.AddVertex(1); + g.AddEdge(new Edge(0, 1)); + + target = new CyclePoppingRandomTreeAlgorithm>(g); + target.RandomTreeWithRoot(0); + } + + [Test] + public void Loop() + { + CyclePoppingRandomTreeAlgorithm> target = new CyclePoppingRandomTreeAlgorithm>(new AdjacencyGraphFactory().Loop()); + target.RandomTree(); + } + + } +} \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs.meta new file mode 100644 index 0000000..b3d5389 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 693e216c502d94e38984b5fda768e296 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs new file mode 100755 index 0000000..d3f8d39 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms.RandomWalks +{ + public class EdgeChainFactory + { + private IVertexAndEdgeListGraph> g = new BidirectionalGraphFactory().RegularLattice10x10(); + + [Factory] + public KeyValuePair< + IVertexAndEdgeListGraph>, + IEdgeChain>> + RoundRobin() + { + return new KeyValuePair>,IEdgeChain>>( + this.g, + new RoundRobinEdgeChain>() + ); + } + + [Factory] + public KeyValuePair< + IVertexAndEdgeListGraph>, + IEdgeChain>> + NormalizedMarkov() + { + return new KeyValuePair>,IEdgeChain>>( + this.g, + new NormalizedMarkovEdgeChain>() + ); + } + + [Factory] + public KeyValuePair< + IVertexAndEdgeListGraph>, + IEdgeChain>> + WeightedMarkov() + { + Dictionary, double> weights = new Dictionary, double>(); + int i=1; + foreach (Edge e in g.Edges) + weights.Add(e,1 + i / g.EdgeCount * 3.0); + return new KeyValuePair>,IEdgeChain>>( + this.g, + new WeightedMarkovEdgeChain>(weights) + ); + } + + [Factory] + public KeyValuePair< + IVertexAndEdgeListGraph>, + IEdgeChain>> + VanishingWeightedMarkov() + { + Dictionary, double> weights = new Dictionary, double>(); + int i = 1; + foreach (Edge e in g.Edges) + weights.Add(e, 1 + i / g.EdgeCount * 3.0); + return new KeyValuePair>,IEdgeChain>>( + this.g, + new VanishingWeightedMarkovEdgeChain>(weights) + ); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs.meta new file mode 100644 index 0000000..0661348 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5179fe5ede845421aa6a4f1f3f6d7980 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs new file mode 100755 index 0000000..4174741 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using QuickGraph.Algorithms.Observers; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [TestFixture] + public class EdgeChainTest + { + [CombinatorialTest] + public void Generate( + [UsingFactories(typeof(EdgeChainFactory))] + KeyValuePair>,IEdgeChain>> eg + ) + { + RandomWalkAlgorithm> walker = + new RandomWalkAlgorithm>(eg.Key, eg.Value); + + walker.Generate(TraversalHelper.GetFirstVertex(eg.Key)); + } + + [CombinatorialTest] + public void GenerateWithVisitor( + [UsingFactories(typeof(EdgeChainFactory))] + KeyValuePair>,IEdgeChain>> eg + ) + { + RandomWalkAlgorithm> walker = + new RandomWalkAlgorithm>(eg.Key, eg.Value); + + EdgeRecorderObserver> vis = new EdgeRecorderObserver>(); + vis.Attach(walker); + walker.Generate(TraversalHelper.GetFirstVertex(eg.Key)); + vis.Detach(walker); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs.meta new file mode 100644 index 0000000..7706fdc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/EdgeChainTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ad18bad2cd126490a98f8b43383257ac +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs new file mode 100755 index 0000000..c75d6dc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs @@ -0,0 +1,46 @@ +using System; +using QuickGraph.Unit; + +using QuickGraph.Algorithms.Observers; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [TypeFixture(typeof(IVertexListGraph>))] + [TypeFactory(typeof(AdjacencyGraphFactory))] + [TypeFactory(typeof(BidirectionalGraphFactory))] + public class RandomWalkAlgorithmTest + { + [Test] + public void RoundRobinTest(IVertexListGraph> g) + { + if (g.VertexCount == 0) + return; + + RandomWalkAlgorithm> walker = + new RandomWalkAlgorithm>(g); + walker.EdgeChain = new NormalizedMarkovEdgeChain>(); + + string root = TraversalHelper.GetFirstVertex(g); + walker.Generate(root); + } + + [Test] + public void RoundRobinTestWithVisitor(IVertexListGraph> g) + { + if (g.VertexCount == 0) + return; + + RandomWalkAlgorithm> walker = + new RandomWalkAlgorithm>(g); + walker.EdgeChain = new NormalizedMarkovEdgeChain>(); + + string root = TraversalHelper.GetFirstVertex(g); + + EdgeRecorderObserver> vis = new EdgeRecorderObserver>(); + vis.Attach(walker); + walker.Generate(root); + vis.Detach(walker); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs.meta new file mode 100644 index 0000000..69dc64d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/RandomWalks/RandomWalkAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5d7ef2580616d4125b50701207439894 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search.meta new file mode 100644 index 0000000..41e24de --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: ebc1b21e2b2f44d05963ad0139efeb5c +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs new file mode 100755 index 0000000..9002479 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms.Search +{ + [TypeFixture(typeof(IBidirectionalGraph>))] + [TypeFactory(typeof(BidirectionalGraphFactory))] + public class BidirectionalDepthFirstSearchAlgorithmTest + { + private BidirectionalDepthFirstSearchAlgorithm> dfs; + + [Test] + public void EmptyGraph(IBidirectionalGraph> g) + { + this.dfs = new BidirectionalDepthFirstSearchAlgorithm>(g); + this.dfs.Compute(); + + VerifyDfs(); + } + + private void VerifyDfs() + { + // let's make sure + foreach (string v in dfs.VisitedGraph.Vertices) + { + Assert.IsTrue(dfs.VertexColors.ContainsKey(v)); + Assert.AreEqual(dfs.VertexColors[v], GraphColor.Black); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs.meta new file mode 100644 index 0000000..913d3b5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9bff12e78551f43e68f827a6fc670672 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs new file mode 100755 index 0000000..734ccaf --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms.Search +{ + [TestFixture] + public class BreadthFirstAlgorithmSearchTest + { + private IDictionary parents; + private IDictionary distances; + private int currentVertex; + private int sourceVertex; + private int currentDistance; + private BreadthFirstSearchAlgorithm> algo; + private AdjacencyGraph> g; + + private void InitializeVertex(Object sender, VertexEventArgs args) + { + Assert.AreEqual(algo.VertexColors[args.Vertex], GraphColor.White); + } + + private void ExamineVertex(Object sender, VertexEventArgs args) + { + int u = args.Vertex; + currentVertex = u; + // Ensure that the distances monotonically increase. + Assert.IsTrue( + distances[u] == currentDistance + || distances[u] == currentDistance + 1 + ); + + if (distances[u] == currentDistance + 1) // new level + ++currentDistance; + } + + private void DiscoverVertex(Object sender, VertexEventArgs args) + { + int u = args.Vertex; + + Assert.AreEqual(algo.VertexColors[u], GraphColor.Gray); + if (u == sourceVertex) + currentVertex = sourceVertex; + else + { + Assert.AreEqual(parents[u], currentVertex); + Assert.AreEqual(distances[u], currentDistance + 1); + Assert.AreEqual(distances[u], distances[parents[u]] + 1); + } + } + + private void ExamineEdge(Object sender, EdgeEventArgs> args) + { + Assert.AreEqual(args.Edge.Source, currentVertex); + } + + private void TreeEdge(Object sender, EdgeEventArgs> args) + { + int u = args.Edge.Source; + int v = args.Edge.Target; + + Assert.AreEqual(algo.VertexColors[v], GraphColor.White); + Assert.AreEqual(distances[u], currentDistance); + parents[v] = u; + distances[v] = distances[u] + 1; + } + + private void NonTreeEdge(Object sender, EdgeEventArgs> args) + { + int u = args.Edge.Source; + int v = args.Edge.Target; + + Assert.IsFalse(algo.VertexColors[v] == GraphColor.White); + + if (algo.VisitedGraph.IsDirected) + { + // cross or back edge + Assert.IsTrue(distances[v] <= distances[u] + 1); + } + else + { + // cross edge (or going backwards on a tree edge) + Assert.IsTrue( + distances[v] == distances[u] + || distances[v] == distances[u] + 1 + || distances[v] == distances[u] - 1 + ); + } + } + + private void GrayTarget(Object sender, EdgeEventArgs> args) + { + Assert.AreEqual(algo.VertexColors[args.Edge.Target], GraphColor.Gray); + } + + private void BlackTarget(Object sender, EdgeEventArgs> args) + { + Assert.AreEqual(algo.VertexColors[args.Edge.Target], GraphColor.Black); + + foreach (Edge e in algo.VisitedGraph.OutEdges(args.Edge.Target)) + Assert.IsFalse(algo.VertexColors[e.Target] == GraphColor.White); + } + + private void FinishVertex(Object sender, VertexEventArgs args) + { + Assert.AreEqual(algo.VertexColors[args.Vertex], GraphColor.Black); + } + + [SetUp] + public void Init() + { + this.parents = new Dictionary(); + this.distances = new Dictionary(); + this.currentDistance = 0; + this.currentVertex = 0; + this.algo = null; + this.g = null; + } + + private class IntVertexFactory : IVertexFactory + { + private int id = 0; + public int CreateVertex() + { + return id++; + } + } + + [CombinatorialTest] + public void GraphWithSelfEdges( + [UsingLinear(2, 9)] int i, + [UsingLinear(0, 10)] int j + ) + { + if (i == 0 && j == 0) + return; + + Random rnd = new Random(); + + g = new AdjacencyGraph>(true); + RandomGraphFactory.Create>(g, + new IntVertexFactory(), + FactoryCompiler.GetEdgeFactory>(), + rnd, i, j, true); + + algo = new BreadthFirstSearchAlgorithm>(g); + try + { + algo.InitializeVertex += new VertexEventHandler(this.InitializeVertex); + algo.DiscoverVertex += new VertexEventHandler(this.DiscoverVertex); + algo.ExamineEdge += new EdgeEventHandler>(this.ExamineEdge); + algo.ExamineVertex += new VertexEventHandler(this.ExamineVertex); + algo.TreeEdge += new EdgeEventHandler>(this.TreeEdge); + algo.NonTreeEdge += new EdgeEventHandler>(this.NonTreeEdge); + algo.GrayTarget += new EdgeEventHandler>(this.GrayTarget); + algo.BlackTarget += new EdgeEventHandler>(this.BlackTarget); + algo.FinishVertex += new VertexEventHandler(this.FinishVertex); + + parents.Clear(); + distances.Clear(); + currentDistance = 0; + sourceVertex = RandomGraphFactory.GetVertex(g, rnd); + + foreach (int v in g.Vertices) + { + distances[v] = int.MaxValue; + parents[v] = v; + } + distances[sourceVertex] = 0; + algo.Compute(sourceVertex); + + CheckBfs(); + } + finally + { + algo.InitializeVertex -= new VertexEventHandler(this.InitializeVertex); + algo.DiscoverVertex -= new VertexEventHandler(this.DiscoverVertex); + algo.ExamineEdge -= new EdgeEventHandler>(this.ExamineEdge); + algo.ExamineVertex -= new VertexEventHandler(this.ExamineVertex); + algo.TreeEdge -= new EdgeEventHandler>(this.TreeEdge); + algo.NonTreeEdge -= new EdgeEventHandler>(this.NonTreeEdge); + algo.GrayTarget -= new EdgeEventHandler>(this.GrayTarget); + algo.BlackTarget -= new EdgeEventHandler>(this.BlackTarget); + algo.FinishVertex -= new VertexEventHandler(this.FinishVertex); + } + } + + protected void CheckBfs() + { + // All white vertices should be unreachable from the source. + foreach (int v in g.Vertices) + { + if (algo.VertexColors[v] == GraphColor.White) + { + //!IsReachable(start,u,g); + } + } + + // The shortest path to a child should be one longer than + // shortest path to the parent. + foreach (int v in g.Vertices) + { + if (parents[v] != v) // *ui not the root of the bfs tree + Assert.AreEqual(distances[v], distances[parents[v]] + 1); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs.meta new file mode 100644 index 0000000..432f2b4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/BreadthFirstSearchAlgirthmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3faabe673f67540c0889d1037a30120f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs new file mode 100755 index 0000000..18ee036 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms.Search +{ + [TestFixture] + public class DepthFirstAlgorithmSearchTest + { + private Dictionary parents; + private Dictionary discoverTimes; + private Dictionary finishTimes; + private int time; + private AdjacencyGraph> g; + private DepthFirstSearchAlgorithm> dfs; + + private void StartVertex(Object sender, VertexEventArgs args) + { + Assert.AreEqual(dfs.VertexColors[args.Vertex], GraphColor.White); + } + + private void DiscoverVertex(Object sender, VertexEventArgs args) + { + Assert.AreEqual(dfs.VertexColors[args.Vertex], GraphColor.Gray); + Assert.AreEqual(dfs.VertexColors[parents[args.Vertex]], GraphColor.Gray); + + discoverTimes[args.Vertex] = time++; + } + + private void ExamineEdge(Object sender, EdgeEventArgs> args) + { + Assert.AreEqual(dfs.VertexColors[args.Edge.Source], GraphColor.Gray); + } + + private void TreeEdge(Object sender, EdgeEventArgs> args) + { + Assert.AreEqual(dfs.VertexColors[args.Edge.Target], GraphColor.White); + parents[args.Edge.Target] = args.Edge.Source; + } + + private void BackEdge(Object sender, EdgeEventArgs> args) + { + Assert.AreEqual(dfs.VertexColors[args.Edge.Target], GraphColor.Gray); + } + + private void FowardOrCrossEdge(Object sender, EdgeEventArgs> args) + { + Assert.AreEqual(dfs.VertexColors[args.Edge.Target], GraphColor.Black); + } + + private void FinishVertex(Object sender, VertexEventArgs args) + { + Assert.AreEqual(dfs.VertexColors[args.Vertex], GraphColor.Black); + finishTimes[args.Vertex] = time++; + } + + public bool IsDescendant(string u, string v) + { + string t = null; + string p = u; + do + { + t = p; + p = parents[t]; + if (p == v) + return true; + } + while (t != p); + + return false; + } + + [SetUp] + public void Init() + { + + parents = new Dictionary(); + discoverTimes = new Dictionary(); + finishTimes = new Dictionary(); + time = 0; + g = new AdjacencyGraph>(true); + dfs = new DepthFirstSearchAlgorithm>(g); + + dfs.StartVertex += new VertexEventHandler(this.StartVertex); + dfs.DiscoverVertex += new VertexEventHandler(this.DiscoverVertex); + dfs.ExamineEdge += new EdgeEventHandler>(this.ExamineEdge); + dfs.TreeEdge += new EdgeEventHandler>(this.TreeEdge); + dfs.BackEdge += new EdgeEventHandler>(this.BackEdge); + dfs.ForwardOrCrossEdge += new EdgeEventHandler>(this.FowardOrCrossEdge); + dfs.FinishVertex += new VertexEventHandler(this.FinishVertex); + } + + [TearDown] + public void TearDown() + { + dfs.StartVertex -= new VertexEventHandler(this.StartVertex); + dfs.DiscoverVertex -= new VertexEventHandler(this.DiscoverVertex); + dfs.ExamineEdge -= new EdgeEventHandler>(this.ExamineEdge); + dfs.TreeEdge -= new EdgeEventHandler>(this.TreeEdge); + dfs.BackEdge -= new EdgeEventHandler>(this.BackEdge); + dfs.ForwardOrCrossEdge -= new EdgeEventHandler>(this.FowardOrCrossEdge); + dfs.FinishVertex -= new VertexEventHandler(this.FinishVertex); + } + + [Test] + public void GraphWithSelfEdges() + { + AdjacencyGraph> g = new AdjacencyGraph>(false); + g.AddVertex("v1"); + g.AddEdge(new Edge("v1","v1")); + + foreach (string v in g.Vertices) + parents[v] = v; + + // compute + dfs.Compute(); + + CheckDfs(); + } + + [Test] + public void GraphWithoutSelfEdges() + { + AdjacencyGraph> g = new AdjacencyGraphFactory().FileDependency(); + + foreach (string v in g.Vertices) + parents[v] = v; + + // compute + dfs.Compute(); + CheckDfs(); + } + + protected void CheckDfs() + { + // check + // all vertices should be black + foreach (string v in g.Vertices) + { + Assert.IsTrue(dfs.VertexColors.ContainsKey(v)); + Assert.AreEqual(dfs.VertexColors[v], GraphColor.Black); + } + + foreach (string u in g.Vertices) + { + foreach (string v in g.Vertices) + { + if (u != v) + { + Assert.IsTrue( + finishTimes[u] < discoverTimes[v] + || finishTimes[v] < discoverTimes[u] + || ( + discoverTimes[v] < discoverTimes[u] + && finishTimes[u] < finishTimes[v] + && IsDescendant(u, v) + ) + || ( + discoverTimes[u] < discoverTimes[v] + && finishTimes[v] < finishTimes[u] + && IsDescendant(v, u) + ) + ); + } + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs.meta new file mode 100644 index 0000000..9273efd --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/DepthFirstSearchAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9866cf69251484682826f204b86737d9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs new file mode 100755 index 0000000..4c9339e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Unit; +using QuickGraph.Algorithms.Search; + +namespace QuickGraph.Tests.Algorithms.Search +{ + [TypeFixture(typeof(IVertexAndEdgeListGraph>))] + [TypeFactory(typeof(AdjacencyGraphFactory))] + public class SearchingExamplesTest + { + [Test] + public void BreadthFirstSearch(IVertexAndEdgeListGraph> g) + { + var bfs = new BreadthFirstSearchAlgorithm>(g); + bfs.Compute(); + } + + [Test] + public void DepthFirstSearch(IVertexAndEdgeListGraph> g) + { + var bfs = new DepthFirstSearchAlgorithm>(g); + bfs.Compute(); + } + } + +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs.meta new file mode 100644 index 0000000..6a00b8c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/SearchingExamplesTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6b1fa8c1b1de74702834883a6cb3012d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs new file mode 100755 index 0000000..54505b3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs @@ -0,0 +1,229 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; + +namespace QuickGraph.Algorithms.Search +{ + [TypeFixture(typeof(IUndirectedGraph>))] + [TypeFactory(typeof(UndirectedGraphFactory))] + public class UndirectedBreadthFirstAlgorithmSearchTest + { + private IDictionary parents; + private IDictionary distances; + private string currentVertex; + private string sourceVertex; + private int currentDistance; + private UndirectedBreadthFirstSearchAlgorithm> algo; + + private void InitializeVertex(Object sender, VertexEventArgs args) + { + Assert.AreEqual(algo.VertexColors[args.Vertex], GraphColor.White); + } + + private void ExamineVertex(Object sender, VertexEventArgs args) + { + string u = args.Vertex; + currentVertex = u; + // Ensure that the distances monotonically increase. + Assert.IsTrue( + distances[u] == currentDistance + || distances[u] == currentDistance + 1 + ); + + if (distances[u] == currentDistance + 1) // new level + ++currentDistance; + } + + private void DiscoverVertex(Object sender, VertexEventArgs args) + { + string u = args.Vertex; + + Assert.AreEqual(algo.VertexColors[u], GraphColor.Gray); + if (u == sourceVertex) + currentVertex = sourceVertex; + else + { + Assert.AreEqual(parents[u], currentVertex); + Assert.AreEqual(distances[u], currentDistance + 1); + Assert.AreEqual(distances[u], distances[parents[u]] + 1); + } + } + + private void TreeEdge(Object sender, EdgeEventArgs> args) + { + string u, v; + if (args.Edge.Source == currentVertex) + { + u = args.Edge.Source; + v = args.Edge.Target; + } + else + { + v = args.Edge.Source; + u = args.Edge.Target; + } + + Assert.AreEqual(algo.VertexColors[v], GraphColor.White); + Assert.AreEqual(distances[u], currentDistance); + parents[v] = u; + distances[v] = distances[u] + 1; + } + + private void NonTreeEdge(Object sender, EdgeEventArgs> args) + { + string u, v; + if (args.Edge.Source == currentVertex) + { + u = args.Edge.Source; + v = args.Edge.Target; + } + else + { + v = args.Edge.Source; + u = args.Edge.Target; + } + + Assert.IsFalse(algo.VertexColors[v] == GraphColor.White); + + if (algo.VisitedGraph.IsDirected) + { + // cross or back edge + Assert.IsTrue(distances[v] <= distances[u] + 1); + } + else + { + // cross edge (or going backwards on a tree edge) + Assert.IsTrue( + distances[v] == distances[u] + || distances[v] == distances[u] + 1 + || distances[v] == distances[u] - 1 + ); + } + } + + private void GrayTarget(Object sender, EdgeEventArgs> args) + { + string v; + if (args.Edge.Source == currentVertex) + { + v = args.Edge.Target; + } + else + { + v = args.Edge.Source; + } + Assert.AreEqual(algo.VertexColors[v], GraphColor.Gray); + } + + private void BlackTarget(Object sender, EdgeEventArgs> args) + { + string u, v; + if (args.Edge.Source == currentVertex) + { + u = args.Edge.Source; + v = args.Edge.Target; + } + else + { + v = args.Edge.Source; + u = args.Edge.Target; + } + + Assert.AreEqual(algo.VertexColors[v], GraphColor.Black); + + foreach (Edge e in algo.VisitedGraph.AdjacentEdges(v)) + { + Assert.IsFalse(algo.VertexColors[ + (e.Source==v) ? e.Target : e.Source + ] == GraphColor.White); + } + } + + private void FinishVertex(Object sender, VertexEventArgs args) + { + Assert.AreEqual(algo.VertexColors[args.Vertex], GraphColor.Black); + } + + [SetUp] + public void Init() + { + this.parents = new Dictionary(); + this.distances = new Dictionary(); + this.currentDistance = 0; + this.currentVertex = null; + this.algo = null; + } + + [Test] + public void GraphWithSelfEdges(IUndirectedGraph> graph) + { + List vertices = new List(graph.Vertices); + + foreach (string v in vertices) + Search(graph, v); + } + + private void Search(IUndirectedGraph> graph, string rootVertex) + { + Console.WriteLine(rootVertex); + algo = new UndirectedBreadthFirstSearchAlgorithm>(graph); + try + { + algo.InitializeVertex += new VertexEventHandler(this.InitializeVertex); + algo.DiscoverVertex += new VertexEventHandler(this.DiscoverVertex); + algo.ExamineVertex += new VertexEventHandler(this.ExamineVertex); + algo.TreeEdge += new EdgeEventHandler>(this.TreeEdge); + algo.NonTreeEdge += new EdgeEventHandler>(this.NonTreeEdge); + algo.GrayTarget += new EdgeEventHandler>(this.GrayTarget); + algo.BlackTarget += new EdgeEventHandler>(this.BlackTarget); + algo.FinishVertex += new VertexEventHandler(this.FinishVertex); + + parents.Clear(); + distances.Clear(); + currentDistance = 0; + sourceVertex = rootVertex; + + foreach (string v in this.algo.VisitedGraph.Vertices) + { + distances[v] = int.MaxValue; + parents[v] = v; + } + distances[sourceVertex] = 0; + algo.Compute(sourceVertex); + + CheckBfs(); + } + finally + { + algo.InitializeVertex -= new VertexEventHandler(this.InitializeVertex); + algo.DiscoverVertex -= new VertexEventHandler(this.DiscoverVertex); + algo.ExamineVertex -= new VertexEventHandler(this.ExamineVertex); + algo.TreeEdge -= new EdgeEventHandler>(this.TreeEdge); + algo.NonTreeEdge -= new EdgeEventHandler>(this.NonTreeEdge); + algo.GrayTarget -= new EdgeEventHandler>(this.GrayTarget); + algo.BlackTarget -= new EdgeEventHandler>(this.BlackTarget); + algo.FinishVertex -= new VertexEventHandler(this.FinishVertex); + } + } + + protected void CheckBfs() + { + // All white vertices should be unreachable from the source. + foreach (string v in this.algo.VisitedGraph.Vertices) + { + if (algo.VertexColors[v] == GraphColor.White) + { + //!IsReachable(start,u,g); + } + } + + // The shortest path to a child should be one longer than + // shortest path to the parent. + foreach (string v in this.algo.VisitedGraph.Vertices) + { + if (parents[v] != v) // *ui not the root of the bfs tree + Assert.AreEqual(distances[v], distances[parents[v]] + 1); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs.meta new file mode 100644 index 0000000..2968afc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/Search/UndirectedBreathFirstSearchAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1de1ba3badfd4441bea393c5e6fb8f4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath.meta new file mode 100644 index 0000000..0430390 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: ac185b66c24114eb5854af5dc42b903f +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs new file mode 100755 index 0000000..2629caa --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using QuickGraph.Algorithms.Observers; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms.ShortestPath +{ + [TestFixture, PexClass] + public partial class DagShortestPathAlgorithmTest + { + [PexMethod] + public void Compute(IVertexListGraph> g) + { + // is this a dag ? + bool isDag = AlgoUtility.IsDirectedAcyclicGraph(g); + + IDistanceRelaxer relaxer = new ShortestDistanceRelaxer(); + List vertices = new List(g.Vertices); + foreach (string root in vertices) + { + if (isDag) + Search(g, root, relaxer); + else + { + try + { + Search(g, root, relaxer); + } + catch (NonAcyclicGraphException) + { + Console.WriteLine("NonAcyclicGraphException caught (as expected)"); + } + } + } + } + + [Test] + public void Simple() + { + AdjacencyGraph> g = new AdjacencyGraph>(); + GraphFactory.Simple(g); + this.Compute(g); + this.ComputeCriticalPath(g); + } + + [Test] + public void FileDependency() + { + AdjacencyGraph> g = new AdjacencyGraph>(); + GraphFactory.FileDependency(g); + this.Compute(g); + this.ComputeCriticalPath(g); + } + + [PexMethod] + public void ComputeCriticalPath(IVertexListGraph> g) + { + // is this a dag ? + bool isDag = AlgoUtility.IsDirectedAcyclicGraph(g); + + var relaxer = new CriticalDistanceRelaxer(); + var vertices = new List(g.Vertices); + foreach (string root in vertices) + { + if (isDag) + Search(g, root, relaxer); + else + { + try + { + Search(g, root, relaxer); + Assert.Fail("should have found the acyclic graph"); + } + catch (NonAcyclicGraphException) + { + Console.WriteLine("NonAcyclicGraphException caught (as expected)"); + } + } + } + } + + private void Search( + IVertexListGraph> g, + string root, IDistanceRelaxer relaxer) + { + DagShortestPathAlgorithm> algo = + new DagShortestPathAlgorithm>( + g, + DagShortestPathAlgorithm>.UnaryWeightsFromVertexList(g), + relaxer + ); + VertexPredecessorRecorderObserver> predecessors = new VertexPredecessorRecorderObserver>(); + predecessors.Attach(algo); + algo.Compute(root); + + Verify(algo, predecessors); + } + + private static void Verify(DagShortestPathAlgorithm> algo, VertexPredecessorRecorderObserver> predecessors) + { + // let's verify the result + foreach (string v in algo.VisitedGraph.Vertices) + { + Edge predecessor; + if (!predecessors.VertexPredecessors.TryGetValue(v, out predecessor)) + continue; + if (predecessor.Source == v) + continue; + Assert.AreEqual( + algo.Distances[v], algo.Distances[predecessor.Source] + 1 + ); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs.meta new file mode 100644 index 0000000..7985395 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DagShortestPathAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1596ccde901264e58ab798528f6cec5d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs new file mode 100755 index 0000000..1cae9ae --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Unit; + +using QuickGraph.Collections; +using QuickGraph.Predicates; +using QuickGraph.Algorithms.Observers; + +namespace QuickGraph.Algorithms.ShortestPath +{ + [TypeFixture(typeof(IVertexAndEdgeListGraph>))] + [TypeFactory(typeof(AdjacencyGraphFactory))] + public class DijkstraShortestPathExamplesTest + { + [Test] + public void Compute(IVertexAndEdgeListGraph> g) + { + if (g.VertexCount == 0) return; + + var rnd = new Random(); + var distances = new Dictionary, double>(); + foreach(var edge in g.Edges) + distances.Add(edge, rnd.Next(100)); + var bfs = new DijkstraShortestPathAlgorithm>(g, distances); + + bfs.Compute(TraversalHelper.GetFirstVertex(g)); + } + } + + [TestFixture, CurrentFixture] + public class DijkstraShortestPathTest + { + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void CreateAlgorithmWithNullGraph() + { + DijkstraShortestPathAlgorithm> dij = new + DijkstraShortestPathAlgorithm>(null, null); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void CreateAlgorithmWithNullWeights() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + DijkstraShortestPathAlgorithm> dij = + new DijkstraShortestPathAlgorithm>(g, null); + } + + [Test] + public void UnaryWeights() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + Dictionary, double> weights = + DijkstraShortestPathAlgorithm>.UnaryWeightsFromEdgeList(g); + } + + [Test] + public void RunOnLineGraph() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex(1); + g.AddVertex(2); + g.AddVertex(3); + + g.AddEdge(new Edge(1,2)); + g.AddEdge(new Edge(2,3)); + + Dictionary,double> weights = + DijkstraShortestPathAlgorithm>.UnaryWeightsFromEdgeList(g); + DijkstraShortestPathAlgorithm> dij = new DijkstraShortestPathAlgorithm>(g, weights); + dij.Compute(1); + + Assert.AreEqual(0, dij.Distances[1]); + Assert.AreEqual(1, dij.Distances[2]); + Assert.AreEqual(2, dij.Distances[3]); + } + + [Test] + public void CheckPredecessorLineGraph() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex(1); + g.AddVertex(2); + g.AddVertex(3); + + Edge e12 = new Edge(1, 2); g.AddEdge(e12); + Edge e23 = new Edge(2, 3); g.AddEdge(e23); + + Dictionary, double> weights = + DijkstraShortestPathAlgorithm>.UnaryWeightsFromEdgeList(g); + DijkstraShortestPathAlgorithm> dij = new DijkstraShortestPathAlgorithm>(g, weights); + VertexPredecessorRecorderObserver> vis = new VertexPredecessorRecorderObserver>(); + vis.Attach(dij); + dij.Compute(1); + + IList> col = vis.Path(2); + Assert.AreEqual(1, col.Count); + Assert.AreEqual(e12, col[0]); + + col = vis.Path(3); + Assert.AreEqual(2, col.Count); + Assert.AreEqual(e12, col[0]); + Assert.AreEqual(e23, col[1]); + } + + + [Test] + public void RunOnDoubleLineGraph() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex(1); + g.AddVertex(2); + g.AddVertex(3); + + Edge e12 = new Edge(1, 2); g.AddEdge(e12); + Edge e23 = new Edge(2, 3); g.AddEdge(e23); + Edge e13 = new Edge(1, 3); g.AddEdge(e13); + + Dictionary,double> weights = DijkstraShortestPathAlgorithm>.UnaryWeightsFromEdgeList(g); + DijkstraShortestPathAlgorithm> dij = new DijkstraShortestPathAlgorithm>(g, weights); + dij.Compute(1); + + Assert.AreEqual(0.0, dij.Distances[1]); + Assert.AreEqual(1.0, dij.Distances[2]); + Assert.AreEqual(1.0, dij.Distances[3]); + } + + [Test] + public void CheckPredecessorDoubleLineGraph() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex(1); + g.AddVertex(2); + g.AddVertex(3); + + Edge e12 = new Edge(1, 2); g.AddEdge(e12); + Edge e23 = new Edge(2, 3); g.AddEdge(e23); + Edge e13 = new Edge(1, 3); g.AddEdge(e13); + + Dictionary, double> weights = DijkstraShortestPathAlgorithm>.UnaryWeightsFromEdgeList(g); + DijkstraShortestPathAlgorithm> dij = new DijkstraShortestPathAlgorithm>(g, weights); + VertexPredecessorRecorderObserver> vis = new VertexPredecessorRecorderObserver>(); + vis.Attach(dij); + dij.Compute(1); + + IList> col = vis.Path(2); + Assert.AreEqual(1, col.Count); + Assert.AreEqual(e12, col[0]); + + col = vis.Path(3); + Assert.AreEqual(1, col.Count); + Assert.AreEqual(e13, col[0]); + } + } + + [TestFixture, CurrentFixture] + public class DijkstraAlgoTest + { + AdjacencyGraph> graph; + DijkstraShortestPathAlgorithm> algo; + List path; + VertexPredecessorRecorderObserver> predecessorObserver; + + [Test] + public void CreateGraph() + { + graph = new AdjacencyGraph>(true); + + // Add some vertices to the graph + graph.AddVertex("A"); + graph.AddVertex("B"); + + graph.AddVertex("D"); + graph.AddVertex("C"); + graph.AddVertex("E"); + + // Create the edges + var a_b = new Edge("A", "B"); + var a_c = new Edge("A", "C"); + var b_e = new Edge("B", "E"); + var c_d = new Edge("C", "D"); + var d_e = new Edge("D", "E"); + + // Add edges to the graph + graph.AddEdge(a_b); + graph.AddEdge(a_c); + graph.AddEdge(c_d); + graph.AddEdge(d_e); + graph.AddEdge(b_e); + + // Define some weights to the edges + var weight = new Dictionary, double>(graph.EdgeCount); + weight.Add(a_b, 30); + weight.Add(a_c, 30); + weight.Add(b_e, 60); + weight.Add(c_d, 40); + weight.Add(d_e, 4); + + algo = new DijkstraShortestPathAlgorithm>(graph, weight); + + // Attach a Vertex Predecessor Recorder Observer to give us the paths + predecessorObserver = new VertexPredecessorRecorderObserver>(); + + using (ObserverScope.Create>>(algo, predecessorObserver)) + { + // Run the algorithm with A set to be the source + algo.Compute("A"); + } + + path = new List(); + PopulatePath("E"); + + Assert.IsTrue(algo.Distances["E"] == 74); + path.Reverse(); + + Console.WriteLine(String.Join(" -> ", path.ToArray())); + } + + void PopulatePath(string vertex) + { + path.Add(vertex); + if (vertex == "A") + return; + PopulatePath(predecessorObserver.VertexPredecessors[vertex].Source); + } + } + + [TestFixture, CurrentFixture] + public class BoostDijkstraTest + { + [Test] + public void Compute() + { + var g = new AdjacencyGraph>(); + var distances = new Dictionary, double>(); + + g.AddVertexRange("ABCDE"); + AddEdge(g, distances, 'A', 'C', 1); + AddEdge(g, distances, 'B', 'B', 2); + AddEdge(g, distances, 'B', 'D', 1); + AddEdge(g, distances, 'B', 'E', 2); + AddEdge(g, distances, 'C', 'B', 7); + AddEdge(g, distances, 'C', 'D', 3); + AddEdge(g, distances, 'D', 'E', 1); + AddEdge(g, distances, 'E', 'A', 1); + AddEdge(g, distances, 'E', 'B', 1); + + var dijkstra = new DijkstraShortestPathAlgorithm>(g, distances); + var predecessors = new VertexPredecessorRecorderObserver>(); + + predecessors.Attach(dijkstra); + dijkstra.Compute('A'); + + Assert.AreEqual(0, dijkstra.Distances['A']); + Assert.AreEqual(6, dijkstra.Distances['B']); + Assert.AreEqual(1, dijkstra.Distances['C']); + Assert.AreEqual(4, dijkstra.Distances['D']); + Assert.AreEqual(5, dijkstra.Distances['E']); + } + + private static void AddEdge( + AdjacencyGraph> g, + Dictionary, double> distances, + char source, char target, double weight) + { + var ac = new Edge(source, target); distances[ac] = weight; g.AddEdge(ac); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs.meta new file mode 100644 index 0000000..7670e5e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e00b92d6ecaac4f25b35036c8df8f5ef +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs new file mode 100755 index 0000000..85027a2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using QuickGraph.Algorithms.Observers; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms.ShortestPath +{ + [TestFixture, PexClass] + public partial class DijkstraShortestPathAlgorithmTest2 + { + [PexMethod] + public void Compute([PexAssumeNotNull]IVertexAndEdgeListGraph> g) + { + List vertices = new List(g.Vertices); + foreach (string root in vertices) + { + Search(g, root); + } + } + + private void Search(IVertexAndEdgeListGraph> g, string root) + { + DijkstraShortestPathAlgorithm> algo = new DijkstraShortestPathAlgorithm>(g, + DijkstraShortestPathAlgorithm>.UnaryWeightsFromEdgeList(g) + ); + VertexPredecessorRecorderObserver> predecessors = new VertexPredecessorRecorderObserver>(); + predecessors.Attach(algo); + algo.Compute(root); + + Verify(algo, predecessors); + } + + private static void Verify(DijkstraShortestPathAlgorithm> algo, VertexPredecessorRecorderObserver> predecessors) + { + // let's verify the result + foreach (string v in algo.VisitedGraph.Vertices) + { + Edge predecessor; + if (!predecessors.VertexPredecessors.TryGetValue(v, out predecessor)) + continue; + if (predecessor.Source == v) + continue; + Assert.AreEqual( + algo.Distances[v], algo.Distances[predecessor.Source] + 1 + ); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs.meta new file mode 100644 index 0000000..9f6bf5e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/ShortestPath/DijkstraShortestPathAlgorithmTest2.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b4977fb687ec413487232366774076d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs new file mode 100755 index 0000000..28040ce --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs @@ -0,0 +1,25 @@ +using System; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms +{ + [TestFixture, PexClass] + public partial class SourceFirstTopologicalSortAlgorithmTest + { + [Test] + [ExpectedException(typeof(NonAcyclicGraphException))] + public void SortCyclic() + { + IVertexAndEdgeListGraph> g = new AdjacencyGraphFactory().Loop(); + this.Sort(g); + } + + [PexMethod] + public void Sort([PexAssumeNotNull]IVertexAndEdgeListGraph> g) + { + SourceFirstTopologicalSortAlgorithm> topo = new SourceFirstTopologicalSortAlgorithm>(g); + topo.Compute(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs.meta new file mode 100644 index 0000000..c509e03 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/SourceFirstTopologicalSortAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 16b90d91df864451890938c1757d6f72 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs new file mode 100755 index 0000000..e0ce7f8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms +{ + [TestFixture, PexClass] + public partial class StronglyConnectedComponentAlgorithmTest + { + [Test, PexMethod] + public void EmptyGraph() + { + IVertexListGraph> g = new AdjacencyGraph>(true); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + strong.Compute(); + Assert.AreEqual(0, strong.ComponentCount); + checkStrong(strong); + } + + [Test, PexMethod] + public void OneVertex() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex("test"); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + strong.Compute(); + Assert.AreEqual(1, strong.ComponentCount); + + checkStrong(strong); + } + + [Test, PexMethod] + public void TwoVertex() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex("v1"); + g.AddVertex("v2"); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + strong.Compute(); + Assert.AreEqual(2, strong.ComponentCount); + + checkStrong(strong); + } + + [Test, PexMethod] + public void TwoVertexOnEdge() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex("v1"); + g.AddVertex("v2"); + g.AddEdge(new Edge("v1", "v2")); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + strong.Compute(); + Assert.AreEqual(2, strong.ComponentCount); + + checkStrong(strong); + } + + + [Test, PexMethod] + public void TwoVertexCycle() + { + AdjacencyGraph> g = new AdjacencyGraph>(true); + g.AddVertex("v1"); + g.AddVertex("v2"); + g.AddEdge(new Edge("v1", "v2")); + g.AddEdge(new Edge("v2", "v1")); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + strong.Compute(); + Assert.AreEqual(1, strong.ComponentCount); + + checkStrong(strong); + } + + [Test, PexMethod] + public void Loop() + { + IVertexListGraph> g = new AdjacencyGraphFactory().Loop(); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + strong.Compute(); + Assert.AreEqual(1, strong.ComponentCount); + + checkStrong(strong); + } + + [Test, PexMethod] + public void Simple() + { + IVertexListGraph> g = new AdjacencyGraphFactory().Simple(); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + + strong.Compute(); + checkStrong(strong); + } + + [Test, PexMethod] + public void FileDependency() + { + IVertexListGraph> g = new AdjacencyGraphFactory().FileDependency(); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + + strong.Compute(); + checkStrong(strong); + } + + [Test, PexMethod] + public void RegularLattice() + { + IVertexListGraph> g = new AdjacencyGraphFactory().RegularLattice10x10(); + StronglyConnectedComponentsAlgorithm> strong = new StronglyConnectedComponentsAlgorithm>(g); + + strong.Compute(); + checkStrong(strong); + } + + private void checkStrong(StronglyConnectedComponentsAlgorithm> strong) + { + Assert.AreEqual(strong.VisitedGraph.VertexCount, strong.Components.Count); + Assert.AreEqual(strong.VisitedGraph.VertexCount, strong.DiscoverTimes.Count); + Assert.AreEqual(strong.VisitedGraph.VertexCount, strong.Roots.Count); + + foreach (string v in strong.VisitedGraph.Vertices) + { + Assert.IsTrue(strong.Components.ContainsKey(v)); + Assert.IsTrue(strong.DiscoverTimes.ContainsKey(v)); + } + + foreach (KeyValuePair de in strong.Components) + { + Assert.IsNotNull(de.Key); + Assert.LowerEqualThan(de.Value, strong.ComponentCount); + } + + foreach (KeyValuePair de in strong.DiscoverTimes) + { + Assert.IsNotNull(de.Key); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs.meta new file mode 100644 index 0000000..bd9ba4f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/StronglyConnectedComponentsAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41133fb40930846dea15262d662a6022 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs new file mode 100755 index 0000000..5c2e0b1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs @@ -0,0 +1,30 @@ +using System; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms +{ + [TestFixture, PexClass] + [CurrentFixture] + public partial class TopologicalSortAlgorithmTest + { + [PexMethod] + public void SortCyclic( + [PexAssumeNotNull]IVertexListGraph> g) + { + TopologicalSortAlgorithm> topo = new TopologicalSortAlgorithm>(g); + topo.Compute(); + } + + [Test] + public void OneTwo() + { + var graph = new AdjacencyGraph>(); + graph.AddVertex(1); + graph.AddVertex(2); + graph.AddEdge(new Edge(1, 2)); + var t = new TopologicalSortAlgorithm>(graph); + t.Compute(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs.meta new file mode 100644 index 0000000..a62ccd4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f4dc066b26de64569900ad241b1786fe +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs new file mode 100755 index 0000000..042237d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms +{ + [TypeFixture(typeof(IUndirectedGraph>)), PexClass] + [TypeFactory(typeof(UndirectedGraphFactory))] + public partial class UndirectedFirstTopologicalSortAlgorithmTest + { + + [Test, PexMethod] + public void Compute([PexAssumeNotNull]IUndirectedGraph> g) + { + var topo = + new UndirectedFirstTopologicalSortAlgorithm>(g); + topo.AllowCyclicGraph = true; + topo.Compute(); + + Display(topo); + } + + private void Display(UndirectedFirstTopologicalSortAlgorithm> topo) + { + int index = 0; + foreach (string v in topo.SortedVertices) + Console.WriteLine("{0}: {1}", index++, v); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs.meta new file mode 100644 index 0000000..ee3ac54 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedFirstTopologicalSortAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7ba8a716fc354471891469ecbc7da9cb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs new file mode 100755 index 0000000..fba3fd1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms +{ + [TestFixture, PexClass] + public partial class UndirectedTopologicalSortAlgorithmTest + { + [PexMethod] + public void Compute([PexAssumeNotNull]IUndirectedGraph> g) + { + UndirectedTopologicalSortAlgorithm> topo = + new UndirectedTopologicalSortAlgorithm>(g); + topo.AllowCyclicGraph = true; + topo.Compute(); + + Display(topo); + } + + private void Display(UndirectedTopologicalSortAlgorithm> topo) + { + int index = 0; + foreach (string v in topo.SortedVertices) + Console.WriteLine("{0}: {1}", index++, v); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs.meta new file mode 100644 index 0000000..7f14067 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/UndirectedTopologicalSortAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5d16dd45f52954a028868beccbf02880 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs new file mode 100755 index 0000000..79c0740 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Algorithms +{ + [TestFixture, PexClass] + public partial class WeaklyConnectedComponentsAlgorithmTest + { + [PexMethod] + public void Compute([PexAssumeNotNull]IVertexListGraph> g) + { + GraphConsoleSerializer.DisplayGraph(g); + + WeaklyConnectedComponentsAlgorithm> dfs = + new WeaklyConnectedComponentsAlgorithm>(g); + dfs.Compute(); + + Console.WriteLine("Weak components: {0}", dfs.ComponentCount); + Assert.AreEqual(g.VertexCount, dfs.Components.Count); + foreach (KeyValuePair kv in dfs.Components) + { + Console.WriteLine("\t{0}: {1}", kv.Key, kv.Value); + } + + foreach(KeyValuePair kv in dfs.Components) + { + Assert.IsLowerEqual(0, kv.Value); + Assert.IsLower(kv.Value, dfs.ComponentCount); + } + + foreach(string vertex in g.Vertices) + foreach (Edge edge in g.OutEdges(vertex)) + { + Assert.AreEqual(dfs.Components[edge.Source], dfs.Components[edge.Target]); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs.meta new file mode 100644 index 0000000..da35cf5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Algorithms/WeaklyConnectedComponentsAlgorithmTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6bb4b3a45b42342c3affd4ad906ceb18 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs new file mode 100755 index 0000000..a493d91 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs @@ -0,0 +1,82 @@ +using System; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; +using QuickGraph; + +namespace QuickGraph +{ + public class BidirectionalGraphFactory + { + private static BidirectionalGraph> CreateGraph() + { + return new BidirectionalGraph>(false); + } + + public static Type CreateType() + { + return typeof(BidirectionalGraph>); + } + + [Factory] + public BidirectionalGraph> Empty() + { + return CreateGraph(); + } + + [Factory] + public BidirectionalGraph> NoEdges() + { + BidirectionalGraph> g = CreateGraph(); + GraphFactory.NoEdges(g); + return g; + } + + [Factory] + public BidirectionalGraph> Loop() + { + BidirectionalGraph> g = CreateGraph(); + GraphFactory.Loop(g); + return g; + } + + [Factory] + public BidirectionalGraph> LoopDouble() + { + BidirectionalGraph> g = CreateGraph(); + GraphFactory.LoopDouble(g); + return g; + } + + [Factory] + public BidirectionalGraph> FileDependency() + { + BidirectionalGraph> g = CreateGraph(); + GraphFactory.FileDependency(g); + return g; + } + + [Factory] + public BidirectionalGraph> RegularLattice10x10() + { + BidirectionalGraph> g = CreateGraph(); + GraphFactory.RegularLattice(10, 10, g); + return g; + } + + [Factory] + public BidirectionalGraph> Simple() + { + BidirectionalGraph> g = CreateGraph(); + GraphFactory.Simple(g); + return g; + } + + [Factory] + public BidirectionalGraph> UnBalancedFlow() + { + BidirectionalGraph> g = CreateGraph(); + GraphFactory.UnBalancedFlow(g); + return g; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs.meta new file mode 100644 index 0000000..e632b9e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalGraphFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ab2e7dafdbce241d599f3a36f599b53b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs new file mode 100755 index 0000000..99b444c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using QuickGraph; +using Microsoft.Pex.Framework; + +namespace QuickGraph +{ + public class BidirectionalMatrixGraphFactory + { + [Factory] + public BidirectionalMatrixGraph> Empty() + { + return new BidirectionalMatrixGraph>(10); + } + + [Factory] + public BidirectionalMatrixGraph> OneEdge() + { + BidirectionalMatrixGraph < Edge > g= new BidirectionalMatrixGraph>(10); + g.AddEdge(new Edge(0, 1)); + return g; + } + + [Factory] + public BidirectionalMatrixGraph> TwoDisjointEdges() + { + BidirectionalMatrixGraph> g = new BidirectionalMatrixGraph>(10); + g.AddEdge(new Edge(0, 1)); + g.AddEdge(new Edge(5, 6)); + return g; + } + + [Factory] + public BidirectionalMatrixGraph> TwoConnectedEdges() + { + BidirectionalMatrixGraph> g = new BidirectionalMatrixGraph>(10); + g.AddEdge(new Edge(0, 1)); + g.AddEdge(new Edge(1, 2)); + return g; + } + + [Factory] + public BidirectionalMatrixGraph> SelfEdge() + { + BidirectionalMatrixGraph> g = new BidirectionalMatrixGraph>(10); + g.AddEdge(new Edge(1, 1)); + return g; + } + + [Factory] + public BidirectionalMatrixGraph> Loop() + { + BidirectionalMatrixGraph> g = new BidirectionalMatrixGraph>(10); + g.AddEdge(new Edge(0, 1)); + g.AddEdge(new Edge(1, 0)); + return g; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs.meta new file mode 100644 index 0000000..e6709d3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/BidirectionalMatrixGraphFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82cc0b2740f004c42b951e5828640fb7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections.meta new file mode 100644 index 0000000..760dcd8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 625bc1191c5f5430bbcd9fcfb05fb141 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentAfterMoveNextFinished.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentAfterMoveNextFinished.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..638a5b2b2369d524daf59073501cba9ff03e0962 GIT binary patch literal 2842 zcmeH{TW`}q5QXO%iT~ioM5KTYF?Lc% zsK67dtj%s_=W^!E%>MX(XonVA-@e$?mYmMmXEx?EvV|p<+W<)t?gm!ye_?ZEInojP zjBkzh1e=7Fg}brE$O_x2x9t`&74;duB0I4+#Ed!YQw@b35C9k%4 zmF5JCcSKNEsXh+_%6+#T>w-(YDo)h9>TPx73nbpR>gTIo-ja=O&e2qFr*uWf-eV)K zuIe8L?F|1*))_jTO&@lw7d)sQ7u;p|tjG6miZ?#h0SWQEdMT$7c9AvXY0geQz6M?* zEcK;iGlT_Yq<;fYhz(7YCVs|g$rsrXQpL~U_$85*d7n%&nq0kEvE8w|pl>%a(9B!OPgA`f1@C#7OI0(s zCsbh=q}!GCJ}!Oj?oAevJ>JtLJvu@&ruwhx@NVG2tJNaE_NK#kqm=(&!^FDQSEu-! z;-fj6C7d}HP4NZi>)5yKeqiUpZ&8&mm-6|u+BV^DHC99KsPfv!)VI(d^_eQUyO|=N aqI>`O6z%VgvJS8pQ{;2yzdr#fp}?{L literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentAfterMoveNextFinished.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentAfterMoveNextFinished.g.cs.meta new file mode 100644 index 0000000..ad75ba0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentAfterMoveNextFinished.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 558b4afa6e1c34c5aba04c95e74e2b8c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentBeforeMoveNext.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.CurrentBeforeMoveNext.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..ef6dbaab99ff36479c629b5e301653da7216c94b GIT binary patch literal 2786 zcmd^jT_0zxfC1Xv&zX_)6p8?x)$+)^v7hb0YXJuCS?w;8qqYoB$> zv%-5!Ov;;wv!M;Jl~^WtCcHy36ud3FYj>!rs?W)l*onQRenQqcQ4W#kYG zvI&(iXTf(#>>Q89Uof-j<~4jc8+A?8pV$U>wfGq6d+8LN9ry$bcf4u~G2$Cy_f zDUWwQAj)G>c14XH&zIrnGvb|#9kHa0EA}O;v=S!+?DBP{VyY^K^r-8z(Qc!Xt1VvT zIVR#g6*N`S=W#%}@3dtdaA{V>iDp-`t!aFT#phP@d_BuMy3xrwo|^59sc6{;V#L*T z|Ks4DlYhZG!l$*K!33IpMto^*y@}-e$DtI8zlPF@>H4)rxQvrC(vs;QcIEx3%=i zt#a+Iv53T;?wN}tWn5QKpP;^0?|6??tfM}md;>%dnt8FrnF zK~^{*gsk<<_H_4DS9S0AZ`-zQiS_K0O|4{i$~v<#yP+*Cv&#BdGI!Run)ijxu~k@y ztTTQ~yeGtDJcT&#htqK3Aqw`X|K3HA?t#uDF~FWiXhUx z8Ck=v?OaXP_e2UyVkfMhS$$=y;+#9qunJut%)Yj*7AB8(PRxWn!d~DnZ0D>AYr%hQ zIXT3FY(gc>x$`|Ic7aEE17@0Pj^M+y(bh!uiA~`N=U4R`fK3|CS-q#!3#do7Mf4aw zCOqOud3^OFqI^uou4=L4^X2&Y9`Tin9kHa0OZGLZv=S#H?DF+Y#Z*-e>Cx7w(XLU+ zt1VvTIU(W=H>j(m&wYn--DzqE;8L%O6ZNioTiy5!i|RR{Ab-hoicfmkhp8R94ASF*vx1!M`+YZ!E_12_GVb&0 zI9?JW^~N_~(y1K?95_`C&KMv^yO_!8k(%T2FUawQfcB$^yx4nR!Wvio3$TuZNyqeN> zz#%M}-wW1F;yZTNv9tGERN!@0XZIhUob_E1 edSH{z_kDJg$=P$0b8l_022_9Rz;-Y-$C&6V{oH*^O*rsg*XslDe~jRs3Jr99xNX z#5&_y;XNTH<;~sM*b;0NmMNYQ@0biFZ)~^i7I*5_r{s$4$X;=OMAijSQxGU$*@8&- zreqDbHgnZk-xDb;ksY(1v--+Z#gaQtu?pP)%)Yj*1}2YpPRxWn!k*(VY)jUNHRrdo zj2vP?HlY&c%=s>fUEopNfSJ0Q1NiW4G<%}@#HR3s^UM7kf=xY~vwBZ;FQ86ri|8@^ znDB}tR0?DF+YwRKfF)Q@I=>fY5| z^4%7%@|+Oyh8v_R_2+>@x#={vJ#a~@;zZh&wx!1BSiEkf=c`#>Q;kke@szeRR1w=- zV#L)||3l}UlfU3S!6&}ZVQl*@gZgpCSx(O8{a#JUMNTOo?KKIjH_bc$V3yzLMlX06k@BCr(UF%vqs&zi~ zb(uOXAHYQc8nOF?ePV~4=?ikid%k83-@KmP0eQEz`gYC&H*LLo==xW>nN%lBdrSw0 z&br=Jui=pE^4b;=*`o~#*+&hUFZF(fy7yS69nEOR?o!>)Z+nT~s-dZ4VyEP2ucojb zID|zLe8zg6_>SFk?Cks!RrqSf_B(xT!`^A_gub7uX%kCdoHm-X6uR|)dU~kq-=3b$ fx(F(`j{3dQZZbVPZhG!-RBJ%>_fC(WC;$5$L3q5# literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndMoveNextAndModify.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndMoveNextAndModify.g.cs.meta new file mode 100644 index 0000000..72ca7c3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndMoveNextAndModify.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 27afb8f93f9af4a8997cb4101405b3c4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndResetAndModify.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndResetAndModify.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..e7710d6b4725f9e81f095c9a6b20c2a9cf76f221 GIT binary patch literal 2802 zcmd^<&2Q5{5XI+=#Q)%9B2{iFDi=N^S}0VgP$0koaY*7cL`@vaA88}RzYhG~ZWlYP z1B%K4fg)$uvoo`A-kb6FZ`-zQk@f7eO{`#d$~v_XyP?f3wbJ@nQg_z3iubwAu$5Sc ztW$nVyvM|(Jh?j?S%R&?GQl(A8IhsniS4%C;!fTAgj|umv{&38k#$bg1O&=gwjk2I zDOtm<&0KZX4@3$}WGAc_tiCc;vEYs~tU}iZv#)Kdfyv{Y5i=%_u;=&-+k!P>&H1k^ zBZpX!O{j!9bG{2==Xex1V5Y9-2tGU;O-)pv*c6^{epSB#*ref%)q6_4fI6`)qDSa4 z<`GBAD*;lO6N}MFvlNEzHimf*R#B)8l9Zssou`$irC%} zBd)IdA3N`y`~}Y`KJjHA#&+m3NRM;Qa&k8B_uZ6S=2Qoy+~?KH*bRw`tQ}8#b;|L@ z@e&cKUq&?pSWrcJ>w`jUXreUnQ+5Tv$o8@7{v3{&KtIpH{rbGNnbcD4d5Z7Mx*%9U;!rD180;C|q& zt9ttG4Y{taZ4r?@T+0I_I`^he6M2LOwl&fomLI>%~Un(`1$I(qB%c7r~i9mcK`8-S>F*s d|4lmH_t;G)X3tH`y|sNBQ2mV)<7deK{{W>@xBLJA literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndResetAndModify.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndResetAndModify.g.cs.meta new file mode 100644 index 0000000..e7c66ed --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertAndResetAndModify.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c1019afa7a13a44d3a9bd17722f9f055 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndDoubleForEach.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndDoubleForEach.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..3a07b62db26548f72d2c0119b77bf6a6840b9a79 GIT binary patch literal 8154 zcmeI0U2hUm5QgX4#Q(6DkW>ov%f^qyYO9T@)>!qT@qz+H(iX_Fv=ZZASD*JBR+jca z(^iwRA!IqroS8W@?|d9Gzke;;vPE`a->hwY-i}#Mt;t*6y4JD8YEU|EuVw>&ckK*X z0=3S1%4Z073z-g2?Dm@0fHr{AhBM-6q9Nfa*+YB4nL70qx*~gL?>Rq0YZs|D7D!(b zut?{2(3+l_)iu`o1xeWw**@!cR_~d-IOmKLsIsnx&EB`Aj7{F&Gh|xmk?k@3vhAET zVvYG8SPvaSK{QzO@jJpc#qf;Pb1HhN z)eT!hx=B1*JiHyiA9;B!iCE*MraJi1%FR2qkG8@;+cytb|Dex_CWOp{PoS z;*pKdICkSG`DhDQakh~7$O+0S#pj8$a@uamUSgMWRhTGumD|e3*HC=kDxa@v`G7at zIe}BT-6JbX_6Zqbb(Me5amVQI^Blud8s%ZhcAN&qr^j^U>?^ zR!1(fusvb#q~nLfB|=i49^M>*f;`f%8deAmRg^0Jl(#;g$hM&B{1}YiaI!o^rd zY?t>#D4(6|0FG_=2hLvK1H^RzT@jKcsST4BrPRZ}yk94{$NRpT$MH(>+QN>4v!=&s z!o2X0tuI>9!d6YdmyC#@PhA#>v=u~P4Yn)ZL?n|tIAfv@?y~Y zFlH$>p;$e2@k?AyDw2skCjv)~IvG`;!>O*zYe*upXHzm{$N8c=LV2UAQ(y3rD&S#p zl--w4Nq@hEdzi_oePr9{2zhfzOd{9KLlVkiS*hB-V7-~&z~-fvQ?KNyr{FXRdZfvmAR?2%A(Gw?aBYm`MJ+la$aZibDu5hEYJTN zS94xx^K+k77x!6?@3Xa>*V+8sXNx+^^L@6S^E#WK`)uXf`|Kujm57;G`3`fLf<3aw zXjrjLzN@y*y6z@inlc|VD;hAtOvoNT@zUHbGy_RzAzEiod8SWZ4w=?z{-ha`yqc|N zF)f!%hNhVRb1HlPy3qz5Xw&ti3jJu6NAueI-i>bBvn$tj(c913)zd2= ixHdwvN-tH9pN-?}Zab@M>z`xVwJSO6+J5TqzyAREXxZ)n literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndDoubleForEach.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndDoubleForEach.g.cs.meta new file mode 100644 index 0000000..386c899 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndDoubleForEach.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec949ec355248426aa89167a5db72f9a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndEnumerateUntyped.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndEnumerateUntyped.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..2809c36ca2ccb9d2cd129a7b016971659d518089 GIT binary patch literal 7352 zcmeI0?Qar65XR@TiT}fWgruPbv}$}wY_-~$YK>JtG=89kB54Z*?r4eeUsr$6E-Od7 zwCRh9P(qG9c4uavd1mJJnBTvaZP^mrvG3NhK6eLQ^*{C9!SBQ%3KZycn>@A+thP1GD#SDTm49Jw~UA9bxYwFKh$G zgt5nWW?gKE1T_u^UIpM_ar~vWdngc2HI+K2IIWX{#k$2bXeHoG5pd+sei_%=o-jKA*Sp5pT3| zh@^76OIDQZGdkkxy!@7v?qR>rb%0E1l!qnTa26Dg6V`gz%mIuLucAz%Yp@%P zyl~6ti&nHas!2ZebZNO<-h_)jXvFRo4C(pslJELCmKrXX#HG;JZN9ir*|nq53m z?@IkCd3CX!tFlxcS-wu^>;Ga&|4sr+>A(K~uAgYg literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndEnumerateUntyped.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndEnumerateUntyped.g.cs.meta new file mode 100644 index 0000000..c6c1a99 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndEnumerateUntyped.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8cfd77f6614ca498388a5332e5edfce6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndMoveNextAndReset.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndMoveNextAndReset.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..8fc987b5c483e5267ede6409ed8a04e22c3ca761 GIT binary patch literal 8236 zcmeI1T~8BH5QgX4#Q(6DZ9)od6*PV%f}+HLsHhjji$Y6nfVOFO3ytxwtIvB**KXky z!pDW(Hk<9)oij6M=AD^6+u1+Amu=Z1+p{0mvOZTwj3?IM>d-pYw%BS=+HS693HKd4 zg%(3SWIW**!rers&DnEv4XZ;-ptRtOI2&k)IZO7?9H%3F!v$XmSc8>G9szk@7NauHp-YTCjYx#&b znmLA3x!olzO7;aAVRe~*+i~~M-{(Anr!>mLl5IK-ipLpqJ#=Q*_t{h*=~M=^Sy)bYW*Gr{uv;yJ?M&%EJh&a9_?ayY3R!#B)i)-JLwbcDRwCo++HriUby$+A)ve#Uq+%`51>8kh8WRZh4bFXhbJ_L?-`{^Zcx(RmZDU- O2Bq2jQsBQG_}{-$tL&!$ literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndMoveNextAndReset.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndMoveNextAndReset.g.cs.meta new file mode 100644 index 0000000..51ef277 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueEnumeratorTest.InsertManyAndMoveNextAndReset.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f0181411533264bb4b75a01825a7f125 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.Constructor.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.Constructor.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..b9e18ee8c0c45527ba7f7828aa94390b6c4e4bcf GIT binary patch literal 1974 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 literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndIndexOf.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndIndexOf.g.cs.meta new file mode 100644 index 0000000..ec471b5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndIndexOf.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3703d79495da420894901e301f7ff54 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndMinimum.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndMinimum.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..d811429f1c6f85314757ab2e1cd9cbf76dcae79d GIT binary patch literal 12224 zcmeHN+iu!G5S`~r{RcmSln}5@0QDj@snSMO+f+^4ho}!E5Q-8m0+SR~{q?rz?BZgQ zHLjs1*s?6MX1zO?GqW?Z3%`Hu$(~qpD&M3lV?14=y_PnfE@U8m@uZ2KzIxY`3BC`c zhdvLz7ih0>O){2Gf|e!k; zE+im5&ma-`_CeL>8l*L+`UNv7izO#$zoXTfQHvY!xI!caK z9__dE=lfJXKpVcf!btk|5MEJ|Pnbij?vH<~Mvp*$jQbK}N;5w!$&sQ!d)(sP2sDHI zwKuh9H0c3-@YB{C;^_kOEHTSt){ZoOC|oSe)^I6TEV8khIT7z7Dev91w-m|}Bzb=fPzt<~wZW|w) z1Mn;;&O>k`zJ)a;ElN?$5-j4xsL@qEdJIg);7rtB;JGEVH+`W8WP4JU3M48TwK8Mj z>ukdNsiN(vbww_oJO{Gps&~;c+7EqNcU#j8OP+;T`3M%}8ljb^@X$lFv_IEb0s0kZ z9(tFH|NRZdO#^;$g1KGLFlloJ{4EucO*80+l#=W77HvGr70_Oeiyw_j5@lDD>;B%d0WL}Arr!3SH zWn;bIX8_%l&iR?T<-RHr-bdABPXnEcY&u?d-&x}rK zsn>EkdH((Psyc~U)y-o{NTp_~_mZqtojj(5SYj-BOqrjlZU6qan(>(8L}tf0**|SD zW%d1dL29Tvs$xqWt&?aCQjSrB#IY7@n#!!YS>;S(lNbc+uu4Q778e6MB^a<$_iIr* z0)xC3eb`!bKjV2LJ!e7b+~3xbUmCKn_PTb0``cu5i|GXT|DFSE3a2>vCy%`k8+&UR zkG*bcYIZk;=Kys?T^n)NLEAuUCw8`&?%2CIoZ`gZ&DQ=d&V+6FNfqA0UEqFVz7nVQ zkBfnm_<8;2e1#{E{vOH6_el61WQu>fZ0CPV>Uo|HIVIlod3`m3JiX4@+AelKHRRqJ zB5MU%I6AUM?KGDEa(5MC2cFg^o29dY()Q+P)^fJmO|xy_ytWpRrIYieWV3iyd?`*2 ck6Y`wYn}COQ(WTS%CB_X6jwU>zk>Sn58o^9y#N3J literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndMinimum.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndMinimum.g.cs.meta new file mode 100644 index 0000000..cbfd837 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndMinimum.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5b01c10d5d355436db56ee1f0ecd6296 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAt.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAt.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..82accfc5bcad417b5596d199d587a16c51e0efb4 GIT binary patch literal 11126 zcmeI2TTc@~6vxlAiQi!#OM->A6llC8fTF}GsHhLb2cS?JpftTN&5KJ9pXb>O^@c*&(5X-OEnJhy3OE9s<6zhJ$l zqO2+$vPZvtdbaCX$y-}`6=a1GAD|$wl6@XKF5|vtZ418StI~;lSH3N8d`XY@Tlw>C zEbov;U(SG(Z`bjPtbJsRbafm4je~B0zsY?HO!nFjv$pLp$R1aGYk;$#zW1i`HBNaz z4SL>sb)JqH7g#hu(b5UWcc+(tk-F+gbA%Qok=_pBLfTM7DdNw0YH|g(Nw4TP(D5rM zOY(grY0xj;C4HBkPi|}*h<$EZLsUb0H>roc2Y+C{+<@+Ve?i>V!6#cOTJyBI5 zF5~D6Mq19;4t*WROBMKCH`?bSZ|mC_7Hq-d==;pk^Nr9po5(y!`Tm-U=isKDl(i&P z;G}FKv#hp(#ASQWTbP|T=v}rP94H6N?PAI@|7V>s06G@^C` zt5nEI%5w6qU7q!OieGD9(5mA9iQN30M{X|G>p~wJFTSQ1xw*tfZXs5OlSJ+;&v%71 zYGQJI)QmCB`7XIp6TfDdBx=TArKadKr)ZoJo}^PS&Oj$WxwXTD1#cd!;P z-X61P|SRMW_vEOJ-V$eo$U9cMQjPSI9A4RquRk5Yr*`h*R6GyIGp-JD6X_s_+{;`At~{EM zF0@98*FsdKEL`2G9WLE4EonCuYAH7Y&%df8ra4|`4^fr#yPcIx=LBGF&U5_i)DcIo z&c@AeljZnFWOZe?62Ez}eTh2>`EArJkmk4aoJ9Y>@O7j0G`}Te4O3$@j@N_=6t7NHq`U=DW7c-8 zCh8YFRg1Grf^{F}ZcF?LR)H}mxOdQo-VXxX&NQbQWU0O*Dp&*^A zQq85eUEw>&V(|cEnr<$@BcRddMEwa()f3Nm`5RE1IGiDarPzyA=XQYi2tLLvVWc>r z`y8*}Q?RRB=!AGBc40=Qo1>c0IO zZ(R|8!MedF+st8R=RSh?xZ|uMW;=hFrhF4q6Ht&ZuvfAh;^!<~Pr5tB`0jCWc=RG>9(5rTJzee-f`!2EQvBZY5#(dk^ zqxR~L?e&&*a~^JP!%f8Igq$6pxg?wL?L45;u5~S4!8T6%YE1l$UVzDh%tGy$eQqCk zi(iLhuho*bx`}-wUYI^~~1Fzj?D9mGwwJTE|&YtgK`y6I< zSH$+3Nj*hs4s_o-blBZY>TZ_!{u;Y=Yd$XVoe(3{%@sU2|7A{jXdYFi?&%%!{~{j| l`|r5KuTp0J%5SQNPLdIQ6ZMai?rR^0Km6phZ&J{N-`{rxKDYn? literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAtAll.g.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAtAll.g.cs.meta new file mode 100644 index 0000000..42ae697 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveAtAll.g.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 022e52dae42444e1498d5eab3cce99e6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveMinimum.g.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTPriorityTValueTest.InsertAndRemoveMinimum.g.cs new file mode 100755 index 0000000000000000000000000000000000000000..45f0d3422885813dc9091f39f44b5d5bc02d0a06 GIT binary patch literal 20356 zcmeHP+fLg+5S`~r{Rck=2|{egNl-6Rp`t}qTiVk0A?gDVpb;cQxd2hsUvGQPZrm7f z;yP)P^Pygaq<8%s$`o49i18D@OK3e+mf=ZWHS(%qu$fG_GQF`@2K zx2cV<(4+O1`h1_t2keG-&M}g@-GNpV)`4b^BjriCw_ON@k8O_U?z_ac5?(2xFdc#1Q$eu7DbD{ zz*P^2BircZ`dwiB8Y^?>2iQp${p6jyAEM`rnmfRV1DuowR}I&@y?WSN|2y{Et<;5`3HKj|{ZmD|uWXE~^yN8FK2p86rKEK-q;ChbZIY? z_z>E# zdpa(mXDUh>8OQCT5Gxh>Mn<0ay-mXLr_!FNMTN*d6dUp^w;?w(Hst0uH1d26#GEX} zA>VQv%1#{0ZD{=cFk3cMw%mrY6NkJ!4rMeB1(w@TcH&TOLs^YO70YcXJ8{TQj6-Q^ z6b|Z2r8#OG1=)}qDEP94zn)akR#df!71&cmi~*{9eQ1xa9Zp9Nmcx1tcQu_(UU`|V&bsL8Wz}*|<7cMwVw$J%VBaqMiw_Uu!s}F5=xJEl{Z~(u z)*rhg%Cpp*3-H0_pcM7TZh}8fi;`yzO3aEwUGfr8%A=Nw_H)@%LlDSdKB$U!bt+cV-pDVVTgc5V;Ft+;%u{|wHWou9>M^GyN zXOseKPzoX_1qmqSd7_zl;#Qs~PIwzB?wzJZzMDm#GrdBX)*sJTN3Eis;UPEV`+Fti zi(W#OIGy+N2`KlZ4(j8WlvE{6i@|)g3m3JWK+3AJ!)kH~2j5^@buHPf+QsrT#pE1s z3wlz9egyb-<*8#;nvy2R%j2?%ahV?1?sulM^VGq#`VF5o1S%$1l(#7-L?j#I^71e+ zyY^B=eo{r$;ZvyO3~h1Gxy_Bs%hQxJQ8#TCJ6~mGc^H^mH(4GAc~#^l@@v8@{$h>K ztL@Idf(QNdEGZ7^`uJ>bJ8VFAT*PD--vAkx`E79P0cL1?>%#{E6`agcR+*icp2HC# z)(!YX)=$utB;B1o+h1%Bm&A8=Y;Li6o;^4%HW#!9r#xTGe!gh?ud^!;I$xY8HZd0r zRCR`R8a^2aRu-Sa<)i>_))] + public static BinaryHeap Create(int capacity) + { + var heap = new BinaryHeap(capacity, (i, j) => i.CompareTo(j)); + heap.ObjectInvariant(); + return heap; + } + } + + ///

+ /// This class contains parameterized unit tests for BinaryHeap`2 + /// + [TestFixture] + [PexClass(typeof(BinaryHeap<,>))] + [PexUseGenericArguments(typeof(int), typeof(int))] + public partial class BinaryHeapTPriorityTValueTest + { + /// + /// Checks heap invariant + /// + private static void AssertInvariant( + BinaryHeap target + ) + { + Assert.IsTrue(target.Capacity >= 0); + Assert.IsTrue(target.Count >= 0); + Assert.IsTrue(target.Count <= target.Capacity); + target.ObjectInvariant(); + } + + [Test] + public void Constructor() + { + var target = new BinaryHeap(); + AssertInvariant(target); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void ConstructorWithNullComparison() + { + var target = new BinaryHeap(0, null); + } + + [PexMethod] + [PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentNullException))] + [PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentOutOfRangeException))] + public void Constructor(int capacity) + { + var target = new BinaryHeap(capacity, Comparer.Default.Compare); + Assert.AreEqual(target.Capacity, capacity); + AssertInvariant(target); + } + + [PexMethod(MaxRuns = 20)] + public void Insert( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + var count = target.Count; + foreach (var kv in kvs) + { + target.Add(kv.Key, kv.Value); + AssertInvariant(target); + } + Assert.IsTrue(count + kvs.Length == target.Count); + } + + [PexMethod(MaxRuns = 20)] + public void InsertAndIndexOf( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + foreach (var kv in kvs) + target.Add(kv.Key, kv.Value); + foreach (var kv in kvs) + Assert.IsTrue(target.IndexOf(kv.Value) > -1, "target.IndexOf(kv.Value) > -1"); + } + + [PexMethod(MaxRuns = 20)] + [PexAllowedExceptionFromTypeUnderTest(typeof(InvalidOperationException))] + [PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentOutOfRangeException))] + public void InsertAndRemoveAt( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs, + int removeAtIndex) + { + foreach (var kv in kvs) + target.Add(kv.Key, kv.Value); + var count = target.Count; + var removed = target.RemoveAt(removeAtIndex); + Assert.AreEqual(count - 1, target.Count); + AssertInvariant(target); + } + + [PexMethod(MaxRuns = 20)] + [PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentOutOfRangeException))] + public void InsertAndRemoveAtAll( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + foreach (var kv in kvs) + target.Add(kv.Key, kv.Value); + var call = PexChoose.FromCall(this); + for (int i = target.Count - 1; i > -1; ++i) + { + target.RemoveAt(call.ValueFromRange(i.ToString(), 0, target.Count - 1)); + AssertInvariant(target); + } + } + + [PexMethod(MaxRuns = 20)] + public void InsertAndEnumerate( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + var dic = new Dictionary(); + foreach (var kv in kvs) + { + target.Add(kv.Key, kv.Value); + dic[kv.Key] = kv.Value; + } + PexAssert.TrueForAll(target, kv => dic.ContainsKey(kv.Key)); + } + + [PexMethod(MaxRuns = 100)] + [PexAllowedExceptionFromTypeUnderTest(typeof(InvalidOperationException))] + public void InsertAndRemoveMinimum( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + var count = target.Count; + foreach (var kv in kvs) + target.Add(kv.Key, kv.Value); + + TPriority minimum = default(TPriority); + for (int i = 0; i < kvs.Length; ++i) + { + if (i == 0) + minimum = target.RemoveMinimum().Key; + else + { + var m = target.RemoveMinimum().Key; + Assert.IsTrue(target.PriorityComparison(minimum, m) <= 0); + minimum = m; + } + AssertInvariant(target); + } + + Assert.AreEqual(0, target.Count); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void RemoveMinimumOnEmpty() + { + new BinaryHeap().RemoveMinimum(); + } + + [PexMethod(MaxRuns = 40)] + [PexAllowedExceptionFromTypeUnderTest(typeof(InvalidOperationException))] + public void InsertAndMinimum( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + PexAssume.IsTrue(kvs.Length > 0); + + var count = target.Count; + TPriority minimum = default(TPriority); + for (int i = 0; i < kvs.Length; ++i) + { + var kv = kvs[i]; + if (i == 0) + minimum = kv.Key; + else + minimum = target.PriorityComparison(kv.Key, minimum) < 0 ? kv.Key : minimum; + target.Add(kv.Key, kv.Value); + // check minimum + var kvMin = target.Minimum(); + Assert.AreEqual(minimum, kvMin.Key); + } + AssertInvariant(target); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void MinimumOnEmpty() + { + new BinaryHeap().Minimum(); + } + } + + [TestFixture] + [PexClass(typeof(BinaryHeap<,>))] + [PexUseGenericArguments(typeof(int), typeof(int))] + public partial class BinaryHeapTPriorityTValueEnumeratorTest + { + [PexMethod(MaxRuns = 20)] + public void InsertManyAndEnumerateUntyped( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + foreach (var kv in kvs) + target.Add(kv.Key, kv.Value); + foreach (KeyValuePair kv in (IEnumerable)target) ; + } + + [PexMethod(MaxRuns = 20)] + public void InsertManyAndDoubleForEach( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + foreach (var kv in kvs) + target.Add(kv.Key, kv.Value); + PexEnumerablePatterns.DoubleForEach(target); + } + + [PexMethod(MaxRuns = 20)] + public void InsertManyAndMoveNextAndReset( + [PexAssumeUnderTest]BinaryHeap target, + [PexAssumeNotNull] KeyValuePair[] kvs) + { + foreach (var kv in kvs) + target.Add(kv.Key, kv.Value); + PexEnumerablePatterns.MoveNextAndReset(target); + } + + [PexMethod(MaxRuns = 20)] + public void InsertAndMoveNextAndModify( + [PexAssumeUnderTest]BinaryHeap target, + KeyValuePair kv) + { + target.Add(kv.Key, kv.Value); + PexAssert.Throws(delegate + { + var enumerator = target.GetEnumerator(); + target.Add(kv.Key, kv.Value); + enumerator.MoveNext(); + }); + } + + [PexMethod(MaxRuns = 20)] + public void InsertAndResetAndModify( + [PexAssumeUnderTest]BinaryHeap target, + KeyValuePair kv) + { + target.Add(kv.Key, kv.Value); + PexAssert.Throws(delegate + { + var enumerator = target.GetEnumerator(); + target.Add(kv.Key, kv.Value); + enumerator.Reset(); + }); + } + + [PexMethod(MaxRuns = 20)] + public void InsertAndCurrentAndModify( + [PexAssumeUnderTest]BinaryHeap target, + KeyValuePair kv) + { + target.Add(kv.Key, kv.Value); + PexAssert.Throws(delegate + { + var enumerator = target.GetEnumerator(); + target.Add(kv.Key, kv.Value); + var current = enumerator.Current; + }); + } + + [PexMethod(MaxRuns = 20)] + public void CurrentAfterMoveNextFinished( + [PexAssumeUnderTest]BinaryHeap target, + KeyValuePair kv) + { + target.Add(kv.Key, kv.Value); + PexAssert.Throws(delegate + { + var enumerator = target.GetEnumerator(); + while (enumerator.MoveNext()) ; + var current = enumerator.Current; + }); + } + + [PexMethod(MaxRuns = 20)] + public void CurrentBeforeMoveNext( + [PexAssumeUnderTest]BinaryHeap target, + KeyValuePair kv) + { + target.Add(kv.Key, kv.Value); + PexAssert.Throws(delegate + { + var enumerator = target.GetEnumerator(); + var current = enumerator.Current; + }); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTest.cs.meta new file mode 100644 index 0000000..5c9ade9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Collections/BinaryHeapTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bbc2f693670e4479bbff8f0df928602b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs new file mode 100755 index 0000000..eb14ca4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Tests +{ + [TestFixture, PexClass] + public partial class DegreeTest + { + [PexMethod] + public void DegreeSumEqualsTwiceEdgeCount( + [PexAssumeNotNull]IBidirectionalGraph> graph) + { + int edgeCount = graph.EdgeCount; + int degCount = 0; + foreach (string v in graph.Vertices) + degCount += graph.Degree(v); + + Assert.AreEqual(edgeCount * 2, degCount); + } + + [PexMethod] + public void InDegreeSumEqualsEdgeCount([PexAssumeNotNull] IBidirectionalGraph> graph) + { + int edgeCount = graph.EdgeCount; + int degCount = 0; + foreach (string v in graph.Vertices) + degCount += graph.InDegree(v); + + Assert.AreEqual(edgeCount, degCount); + } + + [PexMethod] + public void OutDegreeSumEqualsEdgeCount([PexAssumeNotNull] IBidirectionalGraph> graph) + { + int edgeCount = graph.EdgeCount; + int degCount = 0; + foreach (string v in graph.Vertices) + degCount += graph.OutDegree(v); + + Assert.AreEqual(edgeCount, degCount); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs.meta new file mode 100644 index 0000000..9a54014 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/DegreeTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d4b8ea73cb1f0405fab62a872fd696ae +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs new file mode 100755 index 0000000..2dc1ba9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; +using QuickGraph; + +namespace QuickGraph +{ + public class EdgeListGraphFactory + { + [Factory] + public EdgeListGraph> Empty() + { + return new EdgeListGraph>(); + } + + [Factory] + public EdgeListGraph> OneEdge() + { + EdgeListGraph> g = new EdgeListGraph>(); + g.AddEdge(new Edge(0,1)); + return g; + } + + [Factory] + public EdgeListGraph> TwoEdges() + { + EdgeListGraph> g = new EdgeListGraph>(); + g.AddEdge(new Edge(0, 1)); + g.AddEdge(new Edge(2, 3)); + return g; + } + + [Factory] + public EdgeListGraph> Loop() + { + EdgeListGraph> g = new EdgeListGraph>(); + g.AddEdge(new Edge(0, 1)); + g.AddEdge(new Edge(1, 0)); + return g; + } + + [Factory] + public EdgeListGraph> ParralelEdges() + { + EdgeListGraph> g = new EdgeListGraph>(); + g.AddEdge(new Edge(0, 1)); + g.AddEdge(new Edge(0, 1)); + return g; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs.meta new file mode 100644 index 0000000..7a46bd1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 18fda315b8a9f4006b757b0fd647fbda +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs new file mode 100755 index 0000000..91b7643 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs @@ -0,0 +1,35 @@ +using System; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph +{ + [TestFixture, PexClass] + public static class EdgeListGraphTest where E : IEdge + { + [PexMethod] + public static void Iteration([PexAssumeUnderTest]IEdgeListGraph g) + { + int n = g.EdgeCount; + int i = 0; + foreach (E e in g.Edges) + ++i; + } + + [PexMethod] + public static void Count([PexAssumeUnderTest]IEdgeListGraph g) + { + int n = g.EdgeCount; + if (n == 0) + Assert.IsTrue(g.IsEdgesEmpty); + + int i = 0; + foreach (E e in g.Edges) + { + e.ToString(); + ++i; + } + Assert.AreEqual(n, i); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs.meta new file mode 100644 index 0000000..fd275ce --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/EdgeListGraphInvariant.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 58d033b28e9a64c349a40cbb64e34965 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs new file mode 100755 index 0000000..5817b1c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph +{ + [TestFixture, PexClass] + public partial class FactoryCompilerTest + { + public interface IFoo + { + T Boo(); + } + public class Foo : IFoo + { + public int Boo() + { + return 0; + } + } + + [Test, PexMethod] + public void CreateVertexFactory() + { + MethodInfo boo = typeof(Foo).GetMethod("Boo"); + + IVertexFactory factory = FactoryCompiler.GetVertexFactory(); + Assert.IsNotNull(factory); + Foo foo = factory.CreateVertex(); + Assert.IsNotNull(foo); + } + + [Test, PexMethod] + public void CreateVertexFactoryTwice() + { + IVertexFactory factory = FactoryCompiler.GetVertexFactory(); + Assert.IsNotNull(factory); + Assert.IsNotNull(factory.CreateVertex()); + IVertexFactory factory2 = FactoryCompiler.GetVertexFactory(); + Assert.IsNotNull(factory2); + Assert.IsNotNull(factory2.CreateVertex()); + } + + [Test, PexMethod] + public void CreateEdgeFactory() + { + IEdgeFactory> factory = FactoryCompiler.GetEdgeFactory>(); + Assert.IsNotNull(factory); + Foo source = new Foo(); + Foo target = new Foo(); + Edge edge = factory.CreateEdge(source, target); + + Assert.IsNotNull(edge); + Assert.IsNotNull(edge.Source); + Assert.IsNotNull(edge.Target); + } + + [Test, PexMethod] + public void CreateEdgeFactoryTwice() + { + CreateEdgeFactory(); + CreateEdgeFactory(); + } + + [Test, PexMethod] + public void CreateDifferentFactories() + { + FactoryCompiler.GetEdgeFactory>(); + FactoryCompiler.GetEdgeFactory>(); + FactoryCompiler.GetEdgeFactory>(); + FactoryCompiler.GetEdgeFactory>(); + FactoryCompiler.GetEdgeFactory>(); + FactoryCompiler.GetEdgeFactory>(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs.meta new file mode 100644 index 0000000..1175891 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/FactoryCompilerTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 95df7ab65041244e781800ffaef1f019 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs new file mode 100755 index 0000000..d369b54 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs @@ -0,0 +1,16 @@ +using System; + +namespace QuickGraph +{ + public static class GraphConsoleSerializer + { + public static void DisplayGraph(IVertexListGraph g) + where Edge : IEdge + { + Console.WriteLine("{0} vertices", g.VertexCount); + foreach(Vertex v in g.Vertices) + foreach (Edge edge in g.OutEdges(v)) + Console.WriteLine("\t{0}", edge); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs.meta new file mode 100644 index 0000000..8a8f19a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphConsoleSerializer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10397b63e092142468112091ef268087 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs new file mode 100755 index 0000000..420f137 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; + +namespace QuickGraph +{ + public static class GraphFactory + { + public static void NoEdges(IMutableVertexAndEdgeListGraph> g) + { + string x = "x"; g.AddVertex(x); + string y = "y"; g.AddVertex(y); + string z = "z"; g.AddVertex(z); + } + + public static void Loop(IMutableVertexAndEdgeListGraph> g) + { + string x = "x"; g.AddVertex(x); + string y = "y"; g.AddVertex(y); + string z = "z"; g.AddVertex(z); + + g.AddEdge(new Edge(x, y)); + g.AddEdge(new Edge(y, z)); + g.AddEdge(new Edge(z, x)); + } + + public static void LoopDouble(IMutableVertexAndEdgeListGraph> g) + { + string x = "x"; g.AddVertex(x); + string y = "y"; g.AddVertex(y); + string z = "z"; g.AddVertex(z); + + g.AddEdge(new Edge(x, y)); + g.AddEdge(new Edge(y, z)); + g.AddEdge(new Edge(z, x)); + g.AddEdge(new Edge(x, z)); + } + + + public static void UnBalancedFlow(IMutableVertexAndEdgeListGraph> g) + { + string x = "x"; g.AddVertex(x); + string y = "y"; g.AddVertex(y); + string z = "z"; g.AddVertex(z); + string w = "w"; g.AddVertex(w); + + g.AddEdge(new Edge(x, y)); + g.AddEdge(new Edge(x, z)); + g.AddEdge(new Edge(y, z)); + g.AddEdge(new Edge(x, w)); + g.AddEdge(new Edge(w, y)); + g.AddEdge(new Edge(w, z)); + } + + public static void Simple(IMutableVertexAndEdgeListGraph> g) + { + string x = "x"; g.AddVertex(x); + string y = "y"; g.AddVertex(y); + string z = "z"; g.AddVertex(z); + string w = "w"; g.AddVertex(w); + string u = "u"; g.AddVertex(u); + string v = "v"; g.AddVertex(v); + + g.AddEdge(new Edge(u, x)); + g.AddEdge(new Edge(u, v)); + g.AddEdge(new Edge(w, z)); + g.AddEdge(new Edge(w, y)); + g.AddEdge(new Edge(w, u)); + g.AddEdge(new Edge(x, v)); + g.AddEdge(new Edge(v, y)); + g.AddEdge(new Edge(y, x)); + g.AddEdge(new Edge(z, y)); + } + + public static void FileDependency(IMutableVertexAndEdgeListGraph> g) + { + // adding files and storing names + string zig_cpp = "zip.cpp"; g.AddVertex(zig_cpp); + string boz_h = "boz.h"; g.AddVertex(boz_h); + string zag_cpp = "zag.cpp"; g.AddVertex(zag_cpp); + string yow_h = "yow.h"; g.AddVertex(yow_h); + string dax_h = "dax.h"; g.AddVertex(dax_h); + string bar_cpp = "bar.cpp"; g.AddVertex(bar_cpp); + string zow_h = "zow.h"; g.AddVertex(zow_h); + string foo_cpp = "foo.cpp"; g.AddVertex(foo_cpp); + + string zig_o = "zig.o"; g.AddVertex(zig_o); + string zag_o = "zago"; g.AddVertex(zag_o); + string bar_o = "bar.o"; g.AddVertex(bar_o); + string foo_o = "foo.o"; g.AddVertex(foo_o); + string libzigzag_a = "libzigzig.a"; g.AddVertex(libzigzag_a); + string libfoobar_a = "libfoobar.a"; g.AddVertex(libfoobar_a); + + string killerapp = "killerapp.exe"; g.AddVertex(killerapp); + + // adding dependencies + g.AddEdge(new Edge(dax_h, foo_cpp)); + g.AddEdge(new Edge(dax_h, bar_cpp)); + g.AddEdge(new Edge(dax_h, yow_h)); + g.AddEdge(new Edge(yow_h, bar_cpp)); + g.AddEdge(new Edge(yow_h, zag_cpp)); + g.AddEdge(new Edge(boz_h, bar_cpp)); + g.AddEdge(new Edge(boz_h, zig_cpp)); + g.AddEdge(new Edge(boz_h, zag_cpp)); + g.AddEdge(new Edge(zow_h, foo_cpp)); + g.AddEdge(new Edge(foo_cpp, foo_o)); + g.AddEdge(new Edge(foo_o, libfoobar_a)); + g.AddEdge(new Edge(bar_cpp, bar_o)); + g.AddEdge(new Edge(bar_o, libfoobar_a)); + g.AddEdge(new Edge(libfoobar_a, libzigzag_a)); + g.AddEdge(new Edge(zig_cpp, zig_o)); + g.AddEdge(new Edge(zig_o, libzigzag_a)); + g.AddEdge(new Edge(zag_cpp, zag_o)); + g.AddEdge(new Edge(zag_o, libzigzag_a)); + g.AddEdge(new Edge(libzigzag_a, killerapp)); + } + + public static void RegularLattice(int rows, int columns, IMutableVertexAndEdgeListGraph> g) + { + string[,] latice = new string[rows, columns]; + // adding vertices + for (int i = 0; i < rows; ++i) + { + for (int j = 0; j < columns; ++j) + { + latice[i, j] = String.Format("{0},{1}", i.ToString(), j.ToString()); + g.AddVertex(latice[i, j]); + } + } + + // adding edges + for (int i = 0; i < rows - 1; ++i) + { + for (int j = 0; j < columns - 1; ++j) + { + g.AddEdge(new Edge(latice[i, j], latice[i, j + 1])); + g.AddEdge(new Edge(latice[i, j + 1], latice[i, j])); + + g.AddEdge(new Edge(latice[i, j], latice[i + 1, j])); + g.AddEdge(new Edge(latice[i + 1, j], latice[i, j])); + } + } + + for (int j = 0; j < columns - 1; ++j) + { + g.AddEdge(new Edge(latice[rows - 1, j], latice[rows - 1, j + 1])); + g.AddEdge(new Edge(latice[rows - 1, j + 1], latice[rows - 1, j])); + } + + for (int i = 0; i < rows - 1; ++i) + { + g.AddEdge(new Edge(latice[i, columns - 1], latice[i + 1, columns - 1])); + g.AddEdge(new Edge(latice[i + 1, columns - 1], latice[i, columns - 1])); + } + } + + public static void Fsm(IMutableVertexAndEdgeListGraph> g) + { + string s0 = "S0"; g.AddVertex(s0); + string s1 = "S1"; g.AddVertex(s1); + string s2 = "S2"; g.AddVertex(s2); + string s3 = "S3"; g.AddVertex(s3); + string s4 = "S4"; g.AddVertex(s4); + string s5 = "S5"; g.AddVertex(s5); + + g.AddEdge(new NamedEdge(s0, s1,"StartCalc")); + + g.AddEdge(new NamedEdge(s1, s0,"StopCalc")); + g.AddEdge(new NamedEdge(s1, s1,"SelectStandard")); + g.AddEdge(new NamedEdge(s1, s1,"ClearDisplay")); + g.AddEdge(new NamedEdge(s1, s2,"SelectScientific")); + g.AddEdge(new NamedEdge(s1, s3,"EnterDecNumber")); + + g.AddEdge(new NamedEdge(s2, s1,"SelectStandard")); + g.AddEdge(new NamedEdge(s2, s2,"SelectScientific")); + g.AddEdge(new NamedEdge(s2, s2,"ClearDisplay")); + g.AddEdge(new NamedEdge(s2, s4,"EnterDecNumber")); + g.AddEdge(new NamedEdge(s2, s5,"StopCalc")); + + g.AddEdge(new NamedEdge(s3, s0,"StopCalc")); + g.AddEdge(new NamedEdge(s3, s1,"ClearDisplay")); + g.AddEdge(new NamedEdge(s3, s3,"SelectStandard")); + g.AddEdge(new NamedEdge(s3, s3,"EnterDecNumber")); + g.AddEdge(new NamedEdge(s3, s4,"SelectScientific")); + + g.AddEdge(new NamedEdge(s4, s2,"ClearDisplay")); + g.AddEdge(new NamedEdge(s4, s3,"SelectStandard")); + g.AddEdge(new NamedEdge(s4, s4,"SelectScientific")); + g.AddEdge(new NamedEdge(s4, s4,"EnterDecNumber")); + g.AddEdge(new NamedEdge(s4, s5,"StopCalc")); + + g.AddEdge(new NamedEdge(s5, s2, "StartCalc")); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs.meta new file mode 100644 index 0000000..4035dba --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/GraphFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 38d3356ba1343493998e21ff6a4804d2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap.meta new file mode 100644 index 0000000..73ad1ee --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: af91c64d7e5d447c9aa4c727d22ca88f +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs new file mode 100755 index 0000000..6360cb8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Unit; +using QuickGraph.Heap; + +namespace QuickGraph.Tests.Heap +{ + [TestFixture] + public partial class HeapTest + { + private GcTypeHeap LoadHeap() + { + GcTypeHeap heap = GcTypeHeap.Load(@"heap\gcheap.xml"); + return heap; + } + [Test] + public void Roots() + { + GcTypeHeap heap = this.LoadHeap(); + Console.WriteLine(heap.Roots); + } + + [Test] + public void Types() + { + GcTypeHeap heap = this.LoadHeap(); + Console.WriteLine(heap.Types); + } + + [Test] + public void Size() + { + GcTypeHeap heap = this.LoadHeap(); + Console.WriteLine(heap.Size); + } + + [Test] + public void Touching() + { + GcTypeHeap heap = this.LoadHeap(); + Console.WriteLine(heap.Touching("Byte").Types); + } + + [Test] + public void Merge() + { + GcTypeHeap heap = this.LoadHeap(); + Console.WriteLine(heap.Merge(1000).Types); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs.meta new file mode 100644 index 0000000..974ddc4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/HeapTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9dd3c2ad231bc414d99b076608699ec7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml new file mode 100755 index 0000000..d5eeca5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml @@ -0,0 +1,207636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml.meta new file mode 100644 index 0000000..d518350 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Heap/gcheap.xml.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 1852ccd845c7c437c95726bc9cb6735a +TextScriptImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs new file mode 100755 index 0000000..d20b065 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs @@ -0,0 +1,98 @@ +using System; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph +{ + [TestFixture, PexClass(MaxRuns = 50)] + public partial class MutableVertexAndEdgeListGraphTest + { + [PexMethod] + public void AddVertexOnly([PexAssumeNotNull]IMutableVertexAndEdgeListGraph> g, string v) + { + int vertexCount = g.VertexCount; + g.AddVertex(v); + Assert.AreEqual(vertexCount + 1, g.VertexCount); + Assert.IsTrue(g.ContainsVertex(v)); + VerifyCounts(g); + } + + [PexMethod] + public void AddAndRemoveVertex([PexAssumeNotNull]IMutableVertexAndEdgeListGraph> g, int v) + { + int vertexCount = g.VertexCount; + g.AddVertex(v); + Assert.AreEqual(vertexCount + 1, g.VertexCount); + Assert.IsTrue(g.ContainsVertex(v)); + g.RemoveVertex(v); + Assert.AreEqual(vertexCount, g.VertexCount); + Assert.IsFalse(g.ContainsVertex(v)); + //VerifyCounts(g); + } + + [PexMethod] + public void AddVertexAddEdgesAndRemoveTargetVertex([PexAssumeNotNull]IMutableVertexAndEdgeListGraph> g, string v1, string v2) + { + int vertexCount = g.VertexCount; + int edgeCount = g.EdgeCount; + + g.AddVertex(v1); + g.AddVertex(v2); + Assert.AreEqual(vertexCount + 2, g.VertexCount); + Assert.IsTrue(g.ContainsVertex(v1)); + Assert.IsTrue(g.ContainsVertex(v2)); + + g.AddEdge(new Edge(v1, v2)); + Assert.AreEqual(edgeCount + 1, g.EdgeCount); + + g.RemoveVertex(v2); + Assert.AreEqual(vertexCount + 1, g.VertexCount); + Assert.AreEqual(edgeCount, g.EdgeCount); + Assert.IsTrue(g.ContainsVertex(v1)); + Assert.IsFalse(g.ContainsVertex(v2)); + VerifyCounts(g); + } + + [PexMethod] + public void AddVertexAddEdgesAndRemoveSourceVertex([PexAssumeNotNull]IMutableVertexAndEdgeListGraph> g, string v1, string v2) + { + int vertexCount = g.VertexCount; + int edgeCount = g.EdgeCount; + + g.AddVertex(v1); + g.AddVertex(v2); + Assert.AreEqual(vertexCount + 2, g.VertexCount); + Assert.IsTrue(g.ContainsVertex(v1)); + Assert.IsTrue(g.ContainsVertex(v2)); + + g.AddEdge(new Edge(v1, v2)); + Assert.AreEqual(edgeCount + 1, g.EdgeCount); + + g.RemoveVertex(v1); + Assert.AreEqual(vertexCount + 1, g.VertexCount); + Assert.AreEqual(edgeCount, g.EdgeCount); + Assert.IsTrue(g.ContainsVertex(v2)); + Assert.IsFalse(g.ContainsVertex(v1)); + VerifyCounts(g); + } + + private void VerifyCounts(IMutableVertexAndEdgeListGraph> g) + { + int i = 0; + foreach (string v in g.Vertices) + i++; + Assert.AreEqual(g.VertexCount, i); + + i = 0; + foreach (string v in g.Vertices) + foreach (Edge e in g.OutEdges(v)) + i++; + Assert.AreEqual(g.EdgeCount, i); + + i = 0; + foreach (Edge e in g.Edges) + i++; + Assert.AreEqual(g.EdgeCount, i); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs.meta new file mode 100644 index 0000000..8af8f3b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/MutableVertexAndEdgeListGraphTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a2a4f25545c4f46859b6040a0e04cbb7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs new file mode 100755 index 0000000..666589a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Unit; + +namespace QuickGraph.Tests +{ + class Program + { + static int Main(string[] args) + { + return TestRunner.TestMain(args); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs.meta new file mode 100644 index 0000000..7d123e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Program.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 286b7c6cd03ad4579a733ab5129f8a0a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties.meta new file mode 100644 index 0000000..629e13c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 1e67a21160d9144fab61ff2cf7746e6c +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..3004289 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,23 @@ +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("QuickGraph.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("MSIT")] +[assembly: AssemblyProduct("QuickGraph.Tests")] +[assembly: AssemblyCopyright("Copyright © MSIT 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("54248720-0e2d-43de-a8e8-731ced0c15c2")] diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..cf4f641 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7c4576500da2540a5ab65e81c1269a0d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs new file mode 100755 index 0000000..eda4e83 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Pex.Framework; +using Microsoft.Pex.Framework.Instrumentation; +using Microsoft.Pex.Framework.Settings; +using Microsoft.Pex.Framework.Focus; +using Microsoft.Pex.Framework.Validation; +using QuickGraph.Unit.Pex; + +[assembly: PexAssemblyUnderTest(typeof(QuickGraph.GraphColor))] +[assembly: QuickGraphPackage] +[assembly: PexAssemblySettings( + TestFramework = "QuickGraph")] +[assembly: PexAllowedExceptionFromAssembly( + typeof(ArgumentException), + "QuickGraph", + AcceptExceptionSubtypes = true)] diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs.meta new file mode 100644 index 0000000..f65fdc6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Properties/PexAssemblyInfo.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b29aa903a15a54bee846d1c3cff672fd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj new file mode 100755 index 0000000..19e1e1f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj @@ -0,0 +1,193 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {61DF76E1-DE2B-4DF1-AD5F-89939AB06693} + Exe + Properties + QuickGraph.Tests + QuickGraph.Tests + SAK + SAK + SAK + SAK + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + Off + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Off + + + + False + + + + + + + + + Properties\version.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + BinaryHeapTest.cs + + + + + + + + + + + + + + + + + + + + + + + {960C14D1-EDBD-40E5-8AE6-25E311551B87} + QuickGraph.Data + + + {ACDD0973-E5D9-4C2B-9EAF-B5B5DF44EDDD} + QuickGraph.Glee + + + {595D6322-637A-4A36-97F1-D53F3F9ECEA7} + QuickGraph.Graphviz + + + {2DEC7C6E-68DF-47EC-A75E-2C1238986B8E} + QuickGraph.Heap + + + {9FF2B839-743F-4A15-9D33-F11253BF6AE1} + QuickGraph.Unit + + + {A9A5C115-0680-44B3-A87E-5ECF4C93814E} + QuickGraph + + + + + Always + + + + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.meta new file mode 100644 index 0000000..dc15234 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: eda10f293cb574ac690eac844d648b5b +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc new file mode 100755 index 0000000..feffdec --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc.meta new file mode 100644 index 0000000..7fc03d3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/QuickGraph.Tests.csproj.vspscc.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: f6ece3fda440440ec83ec13db4a3644d +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression.meta new file mode 100644 index 0000000..5e7a1e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 960b63c3b7c9f4809a526d48b942ee44 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs new file mode 100755 index 0000000..8d77a49 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Unit; +using QuickGraph.Algorithms.ShortestPath; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Algorithms; + +namespace QuickGraph.Tests.Regression { + [TestFixture] + class DijkstraTest { + [Test] + public void Scenario() { + AdjacencyGraph> graph = new AdjacencyGraph>(true); + + // Add some vertices to the graph + graph.AddVertex("A"); + graph.AddVertex("B"); + graph.AddVertex("C"); + graph.AddVertex("D"); + graph.AddVertex("E"); + graph.AddVertex("F"); + graph.AddVertex("G"); + graph.AddVertex("H"); + graph.AddVertex("I"); + graph.AddVertex("J"); + + // Create the edges + Edge a_b = new Edge("A", "B"); + Edge a_d = new Edge("A", "D"); + Edge b_a = new Edge("B", "A"); + Edge b_c = new Edge("B", "C"); + Edge b_e = new Edge("B", "E"); + Edge c_b = new Edge("C", "B"); + Edge c_f = new Edge("C", "F"); + Edge c_j = new Edge("C", "J"); + Edge d_e = new Edge("D", "E"); + Edge d_g = new Edge("D", "G"); + Edge e_d = new Edge("E", "D"); + Edge e_f = new Edge("E", "F"); + Edge e_h = new Edge("E", "H"); + Edge f_i = new Edge("F", "I"); + Edge f_j = new Edge("F", "J"); + Edge g_d = new Edge("G", "D"); + Edge g_h = new Edge("G", "H"); + Edge h_g = new Edge("H", "G"); + Edge h_i = new Edge("H", "I"); + Edge i_f = new Edge("I", "F"); + Edge i_j = new Edge("I", "J"); + Edge i_h = new Edge("I", "H"); + Edge j_f = new Edge("J", "F"); + + // Add the edges + graph.AddEdge(a_b); + graph.AddEdge(a_d); + graph.AddEdge(b_a); + graph.AddEdge(b_c); + graph.AddEdge(b_e); + graph.AddEdge(c_b); + graph.AddEdge(c_f); + graph.AddEdge(c_j); + graph.AddEdge(d_e); + graph.AddEdge(d_g); + graph.AddEdge(e_d); + graph.AddEdge(e_f); + graph.AddEdge(e_h); + graph.AddEdge(f_i); + graph.AddEdge(f_j); + graph.AddEdge(g_d); + graph.AddEdge(g_h); + graph.AddEdge(h_g); + graph.AddEdge(h_i); + graph.AddEdge(i_f); + graph.AddEdge(i_h); + graph.AddEdge(i_j); + graph.AddEdge(j_f); + + // Define some weights to the edges + Dictionary, double> edgeCost = new Dictionary, double>(graph.EdgeCount); + edgeCost.Add(a_b, 4); + edgeCost.Add(a_d, 1); + edgeCost.Add(b_a, 74); + edgeCost.Add(b_c, 2); + edgeCost.Add(b_e, 12); + edgeCost.Add(c_b, 12); + edgeCost.Add(c_f, 74); + edgeCost.Add(c_j, 12); + edgeCost.Add(d_e, 32); + edgeCost.Add(d_g, 22); + edgeCost.Add(e_d, 66); + edgeCost.Add(e_f, 76); + edgeCost.Add(e_h, 33); + edgeCost.Add(f_i, 11); + edgeCost.Add(f_j, 21); + edgeCost.Add(g_d, 12); + edgeCost.Add(g_h, 10); + edgeCost.Add(h_g, 2); + edgeCost.Add(h_i, 72); + edgeCost.Add(i_f, 31); + edgeCost.Add(i_h, 18); + edgeCost.Add(i_j, 7); + edgeCost.Add(j_f, 8); + + // We want to use Dijkstra on this graph + DijkstraShortestPathAlgorithm> dijkstra = new DijkstraShortestPathAlgorithm>(graph, edgeCost); + + // Attach a Vertex Predecessor Recorder Observer to give us the paths + VertexPredecessorRecorderObserver> predecessorObserver = new VertexPredecessorRecorderObserver>(); + using (ObserverScope.Create>>(dijkstra, predecessorObserver)) { + // Run the algorithm with A set to be the source + dijkstra.Compute("A"); + } + + foreach (KeyValuePair> kvp in predecessorObserver.VertexPredecessors) + Console.WriteLine("If you want to get to {0} you have to enter through the in edge {1}", kvp.Key, kvp.Value); + + foreach (string v in graph.Vertices) { + double distance = AlgoUtility.ComputePredecessorCost( + predecessorObserver.VertexPredecessors, + edgeCost, + v); + Console.WriteLine("A -> {0}: {1}", v, distance); + } + + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs.meta new file mode 100644 index 0000000..70cc20b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Regression/DijkstraTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 026e3dd6bc59a4ce59216c99d4697b2e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs new file mode 100755 index 0000000..59304f2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Unit; + +namespace QuickGraph.Tests +{ + [TestFixture] + public class ReversedBidirectionalGraphTest + { + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs.meta new file mode 100644 index 0000000..c2a7e99 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/ReversedBidirectionalGraphTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c9c8b9112e0a448c905c78af1507a97 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization.meta new file mode 100644 index 0000000..2d2bfe8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 26cae03a50b33430ba27c6f0fc8eb688 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs new file mode 100755 index 0000000..70c68e1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Serialization +{ + [TestFixture, PexClass] + public partial class GraphMLSerializerTest + { + [Test, PexMethod] + public void RoundTrip() + { + RoundTripGraph(new AdjacencyGraphFactory().SimpleIdentifiable()); + } + + [PexMethod] + public void RoundTripGraph([PexAssumeNotNull]IMutableVertexAndEdgeListGraph g) + { + GraphMLSerializer serializer = new GraphMLSerializer(); + AdjacencyGraph gd = new AdjacencyGraph(); + string baseLine; + string output; + + using (StringWriter writer = new StringWriter()) + { + serializer.Serialize(writer, g); + baseLine = writer.ToString(); + TestConsole.WriteLineBold("Original graph:"); + Console.WriteLine(writer.ToString()); + TestConsole.WriteLineBold("---"); + + using (XmlTextReader reader = new XmlTextReader(new StringReader(writer.ToString()))) + { + serializer.Deserialize( + reader, + gd, + new NamedVertex.Factory(), + new NamedEdge.Factory() + ); + } + } + + TestConsole.WriteLineBold("Roundtripped graph:"); + using (StringWriter sw = new StringWriter()) + { + serializer.Serialize(sw, gd); + output = sw.ToString(); + Console.WriteLine(sw.ToString()); + } + + Assert.AreEqual(g.VertexCount, gd.VertexCount); + Assert.AreEqual(g.EdgeCount, gd.EdgeCount); + StringAssert.AreEqual( + baseLine, + output, + StringComparison.InvariantCulture + ); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs.meta new file mode 100644 index 0000000..effd4d2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a3862419fe224549949445675ceaeb7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs new file mode 100755 index 0000000..e73ce03 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using System.IO; +using System.Xml; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph.Serialization +{ + [TestFixture, PexClass] + public partial class GraphMLSerializerWithArgumentsTest + { + public sealed class TestVertex : IIdentifiable + { + private string id; + private string _string; + private int _int; + private long _long; + private float _float; + private double _double; + private bool _bool; + private object _object; + + public TestVertex( + string id, + string _string, + int _int, + long _long, + double _double, + float _float, + bool _bool, + object _object) + { + this.id = id; + this._string = _string; + this._int = _int; + this._long = _long; + this._float = _float; + this._double = _double; + this._bool = _bool; + this._object = _object; + } + + public string ID + { + get { return this.id; } + } + + [XmlAttribute("string")] + public string String + { + get { return this._string; } + } + [XmlAttribute("int")] + public int Int + { + get { return this._int; } + } + [XmlAttribute("long")] + public long Long + { + get { return this._long; } + } + [XmlAttribute("float")] + public float Float + { + get { return this._float; } + } + [XmlAttribute("double")] + public double Double + { + get { return this._double; } + } + [XmlAttribute("object")] + public object Object + { + get { return this._object; } + } + } + + public sealed class TestEdge : Edge, IIdentifiable + { + private string id; + private string _string; + private int _int; + private long _long; + private float _float; + private double _double; + private bool _bool; + private object _object; + + public TestEdge( + TestVertex source, + TestVertex target, + string id, + string _string, + int _int, + long _long, + double _double, + float _float, + bool _bool, + object _object) + : base(source, target) + { + this.id = id; + this._string = _string; + this._int = _int; + this._long = _long; + this._float = _float; + this._double = _double; + this._bool = _bool; + this._object = _object; + } + + public string ID + { + get { return this.id; } + } + + [XmlAttribute("string")] + public string String + { + get { return this._string; } + } + [XmlAttribute("int")] + public int Int + { + get { return this._int; } + } + [XmlAttribute("long")] + public long Long + { + get { return this._long; } + } + [XmlAttribute("float")] + public float Float + { + get { return this._float; } + } + [XmlAttribute("double")] + public double Double + { + get { return this._double; } + } + [XmlAttribute("object")] + public object Object + { + get { return this._object; } + } + } + + public sealed class TestAdjacencyGraph : AdjacencyGraph + { } + + [Test] + [Repeat(2)] + public void WriteVertex() + { + TestAdjacencyGraph g = new TestAdjacencyGraph(); + TestVertex v = new TestVertex( + "v1", + "string", + 1, + 2, + 3.0, + 4.0F, + true, + new Dummy() + ); + + g.AddVertex(v); + VerifySerialization(g); + } + + private void VerifySerialization(TestAdjacencyGraph g) + { + GraphMLSerializer serializer = new GraphMLSerializer(); + + using (StringWriter writer = new StringWriter()) + { + serializer.Serialize(writer, g); + String xml = writer.ToString(); + Console.WriteLine(xml); + XmlAssert.IsWellFormedXml(xml); + } + } + + [Test] + [Repeat(2)] + public void WriteEdge() + { + { + TestAdjacencyGraph g = new TestAdjacencyGraph(); + TestVertex v1 = new TestVertex( + "v1", + "string", + 1, + 2, + 3.0, + 4.0F, + true, + new Dummy() + ); + TestVertex v2 = new TestVertex( + "v2", + "string2", + 5, + 6, + 7.0, + 8.0F, + true, + new Dummy() + ); + + g.AddVertex(v1); + g.AddVertex(v2); + + TestEdge edge = new TestEdge( + v1,v2, + "e1", + "string", + 9, + 10, + 11.0, + 12.0F, + true, + new Dummy() + ); + g.AddEdge(edge); + VerifySerialization(g); + } + } + + public class Dummy { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs.meta new file mode 100644 index 0000000..c0bbe0a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/Serialization/GraphMLSerializerWithArgumentsTest.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 85c757df60dd2462f8e9b15ddb95ca70 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs new file mode 100755 index 0000000..a4808ab --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs @@ -0,0 +1,72 @@ +using System; +using QuickGraph.Unit; + +namespace QuickGraph +{ + public sealed class UndirectedGraphFactory + { + private static UndirectedGraph> CreateGraph() + { + return new UndirectedGraph>(false); + } + + [Factory] + public UndirectedGraph> Empty() + { + return CreateGraph(); + } + + [Factory] + public UndirectedGraph> NoEdges() + { + UndirectedGraph> g = CreateGraph(); + g.AddVertex("x"); + g.AddVertex("y"); + g.AddVertex("z"); + return g; + } + + [Factory] + public UndirectedGraph> Loop() + { + UndirectedGraph> g = CreateGraph(); + g.AddVertex("x"); + g.AddVertex("y"); + g.AddVertex("z"); + g.AddEdge(new Edge("x", "y")); + g.AddEdge(new Edge("y", "z")); + g.AddEdge(new Edge("z", "x")); + return g; + } + + [Factory] + public UndirectedGraph> LoopDouble() + { + UndirectedGraph> g = CreateGraph(); + g.AddVertex("x"); + g.AddVertex("y"); + g.AddVertex("z"); + + g.AddEdge(new Edge("x", "y")); + g.AddEdge(new Edge("y", "z")); + g.AddEdge(new Edge("z", "x")); + + g.AddEdge(new Edge("x", "y")); + g.AddEdge(new Edge("y", "z")); + g.AddEdge(new Edge("z", "x")); + return g; + } + + [Factory] + public UndirectedGraph> Simple() + { + UndirectedGraph> g = CreateGraph(); + g.AddVertex("x"); + g.AddVertex("y"); + g.AddVertex("z"); + g.AddEdge(new Edge("x", "y")); + g.AddEdge(new Edge("y", "z")); + return g; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs.meta new file mode 100644 index 0000000..caa30fb --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d619fee2f2734c289385943df4a07ef +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs new file mode 100755 index 0000000..c3baf51 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph +{ + [TestFixture, PexClass] + public partial class UndirectedGraphTest where E : IEdge + { + [PexMethod] + public static void IsAdjacentEdgesEmpty([PexAssumeUnderTest]IUndirectedGraph g) + { + foreach (T v in g.Vertices) + { + Assert.AreEqual( + g.IsAdjacentEdgesEmpty(v), + g.AdjacentDegree(v) == 0); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs.meta new file mode 100644 index 0000000..c676db5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/UndirectedGraphInvariant.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ad243900acf95458e9802ea3facf3e71 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs new file mode 100755 index 0000000..47522b3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs @@ -0,0 +1,20 @@ +using System; +using QuickGraph.Unit; +using Microsoft.Pex.Framework; + +namespace QuickGraph +{ + [TestFixture, PexClass] + public static class VertexListGraphTest + where E : IEdge + { + [PexMethod] + public static void Iteration([PexAssumeUnderTest]IVertexListGraph g) + { + int i = 0; + foreach (T v in PexSymbolicValue.IgnoreEnumeration(g.Vertices)) + ++i; + Assert.AreEqual(g.VertexCount, i); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs.meta new file mode 100644 index 0000000..9c85b65 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/VertexListGraphInvariant.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 660c88f2c292e4d33ba1c5b3300bd52d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs new file mode 100755 index 0000000..5d34d37 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs @@ -0,0 +1,2055 @@ +#if PEX_NOT_AVAILABLE +namespace Microsoft.Pex.Framework +{ + + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class PexSequenceTestAttribute : System.Attribute + { + + public bool IgnoreFieldAccesses; + + public bool IgnoreStates; + + public bool IgnoreWeight; + + public bool MatchUncoveredBranches; + + public int MaxSuggestions; + + public string Categories; + + public int MaxBranches; + + public int MaxRounds; + + public int MaxRuns; + + public int MaxRunsWithUniqueBranchHits; + + public int MaxRunsWithUniquePaths; + + public int MaxCalls; + + public int MaxConditions; + + public int MaxBranchHits; + + public int MaxExceptions; + + public int ConstraintSolverTimeout; + + public int Timeout; + + public string CoverageFileFormat; + + public string TouchMyCode; + + public string TestClassName; + + public bool TestExcludeNonTermination; + + public bool TestDisableNonTermination; + + public Microsoft.Pex.Framework.PexTestEmissionFilter TestEmissionFilter; + + public bool PruneExceptions; + + public bool Joins; + + public bool NoSoftSubstitutions; + + public bool SymbolicCalls; + + public Microsoft.Pex.Framework.Strategies.PexSearchFrontier SearchFrontier; + + public string CustomSolver; + + public Microsoft.Pex.Framework.Strategies.PexCoverageGoal CoverageGoal; + + public string CssProjectStructure; + + public string CssIteration; + + public bool ContainsSettings; + + public System.Collections.Generic.IEnumerable ActiveSettings; + + public object TypeId; + + static PexSequenceTestAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatableByMethodAndSettersAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static PexCreatableByMethodAndSettersAttribute() + { + } + + static PexCreatableByMethodAndSettersAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatableByConstructorAndSettersAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static PexCreatableByConstructorAndSettersAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatableAsWebDataAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static PexCreatableAsWebDataAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + public class PexUseGenericArgumentsAttribute : System.Attribute + { + + public object TypeId; + + static PexUseGenericArgumentsAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class PexTestAttribute : System.Attribute + { + + public string Categories; + + public int MaxBranches; + + public int MaxRounds; + + public int MaxRuns; + + public int MaxRunsWithUniqueBranchHits; + + public int MaxRunsWithUniquePaths; + + public int MaxCalls; + + public int MaxConditions; + + public int MaxBranchHits; + + public int MaxExceptions; + + public int ConstraintSolverTimeout; + + public int Timeout; + + public string CoverageFileFormat; + + public string TouchMyCode; + + public string TestClassName; + + public bool TestExcludeNonTermination; + + public bool TestDisableNonTermination; + + public Microsoft.Pex.Framework.PexTestEmissionFilter TestEmissionFilter; + + public bool PruneExceptions; + + public bool Joins; + + public bool NoSoftSubstitutions; + + public bool SymbolicCalls; + + public Microsoft.Pex.Framework.Strategies.PexSearchFrontier SearchFrontier; + + public string CustomSolver; + + public Microsoft.Pex.Framework.Strategies.PexCoverageGoal CoverageGoal; + + public string CssProjectStructure; + + public string CssIteration; + + public bool ContainsSettings; + + public System.Collections.Generic.IEnumerable ActiveSettings; + + public object TypeId; + + static PexTestAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexWorkItemAttribute : System.Attribute + { + + public int Id; + + public object TypeId; + + static PexWorkItemAttribute() + { + } + } + + [System.AttributeUsageAttribute((System.AttributeTargets.Class | System.AttributeTargets.Method), AllowMultiple = false, Inherited = true)] + public class PexIgnoreAttribute : System.Attribute + { + + public string Message; + + public int WorkItemId; + + public object TypeId; + + static PexIgnoreAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class PexFactoryAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx FactoredType; + + public object TypeId; + + static PexFactoryAttribute() + { + } + + static PexFactoryAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexExpectedCoverageAttribute : System.Attribute + { + + public double ExpectedCoverage; + + public Microsoft.Pex.Framework.PexExpectedCoverageAttribute.CoverageOperator Operator; + + public Microsoft.Pex.Framework.PexCoverageUnit Unit; + + public bool DebugOnly; + + public bool ReleaseOnly; + + public object TypeId; + + static PexExpectedCoverageAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFocusOnAssemblyAttribute : System.Attribute + { + + public Microsoft.Pex.Framework.PexSearchPriority SearchPriority; + + public bool DoNotReportCoverage; + + public object TypeId; + + static PexFocusOnAssemblyAttribute() + { + } + + static PexFocusOnAssemblyAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = false, Inherited = true)] + public class PexCrossProductExplorableStrategyAttribute : System.Attribute + { + + public object TypeId; + + static PexCrossProductExplorableStrategyAttribute() + { + } + } + + [System.AttributeUsageAttribute((((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method) + | System.AttributeTargets.Parameter), AllowMultiple = true, Inherited = true)] + public class PexUseValuesAttribute : System.Attribute + { + + public object TypeId; + + static PexUseValuesAttribute() + { + } + + static PexUseValuesAttribute() + { + } + + static PexUseValuesAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatableByMethodAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static PexCreatableByMethodAttribute() + { + } + + static PexCreatableByMethodAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = true, Inherited = true)] + public class PexAssumeIsNotSharedAttribute : System.Attribute + { + + public object TypeId; + + static PexAssumeIsNotSharedAttribute() + { + } + + static PexAssumeIsNotSharedAttribute() + { + } + + static PexAssumeIsNotSharedAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFocusOnNamespaceAttribute : System.Attribute + { + + public string NamespacePrefix; + + public bool Strict; + + public Microsoft.Pex.Framework.PexSearchPriority SearchPriority; + + public bool DoNotReportCoverage; + + public object TypeId; + + static PexFocusOnNamespaceAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInvariantAssemblyAttribute : System.Attribute + { + + public System.Reflection.AssemblyName TargetAssembly; + + public Microsoft.ExtendedReflection.Metadata.TypeEx InvariantClassAttributeType; + + public Microsoft.ExtendedReflection.Metadata.TypeEx InvariantMethodAttributeType; + + public Microsoft.ExtendedReflection.Metadata.TypeEx ValidationType; + + public object TypeId; + + static PexInvariantAssemblyAttribute() + { + } + + static PexInvariantAssemblyAttribute() + { + } + + static PexInvariantAssemblyAttribute() + { + } + + static PexInvariantAssemblyAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public class PexFieldBindingAttribute : System.Attribute + { + + public string FieldName; + + public object TypeId; + + static PexFieldBindingAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatableByClassFactoryAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx FactoryType; + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static PexCreatableByClassFactoryAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexAllowedExceptionAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeDefinition AllowedExceptionTypeDefinition; + + public string Description; + + public string UserAssemblies; + + public bool AcceptExceptionSubtypes; + + public bool AcceptInnerException; + + public object TypeId; + + static PexAllowedExceptionAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class PexClassAttribute : System.Attribute + { + + public string Suite; + + public string Categories; + + public int MaxBranches; + + public int MaxRounds; + + public int MaxRuns; + + public int MaxRunsWithUniqueBranchHits; + + public int MaxRunsWithUniquePaths; + + public int MaxCalls; + + public int MaxConditions; + + public int MaxBranchHits; + + public int MaxExceptions; + + public int ConstraintSolverTimeout; + + public int Timeout; + + public string CoverageFileFormat; + + public string TouchMyCode; + + public string TestClassName; + + public bool TestExcludeNonTermination; + + public bool TestDisableNonTermination; + + public Microsoft.Pex.Framework.PexTestEmissionFilter TestEmissionFilter; + + public bool PruneExceptions; + + public bool Joins; + + public bool NoSoftSubstitutions; + + public bool SymbolicCalls; + + public Microsoft.Pex.Framework.Strategies.PexSearchFrontier SearchFrontier; + + public string CustomSolver; + + public Microsoft.Pex.Framework.Strategies.PexCoverageGoal CoverageGoal; + + public string CssProjectStructure; + + public string CssIteration; + + public bool ContainsSettings; + + public System.Collections.Generic.IEnumerable ActiveSettings; + + public object TypeId; + + static PexClassAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatableAsSingletonAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static PexCreatableAsSingletonAttribute() + { + } + + static PexCreatableAsSingletonAttribute() + { + } + + static PexCreatableAsSingletonAttribute() + { + } + + static PexCreatableAsSingletonAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = true, Inherited = true)] + public class PexAssumeIsAcyclicAttribute : System.Attribute + { + + public object TypeId; + + static PexAssumeIsAcyclicAttribute() + { + } + + static PexAssumeIsAcyclicAttribute() + { + } + + static PexAssumeIsAcyclicAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexExplorableFromConstructorAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExplorableType; + + public Microsoft.ExtendedReflection.Metadata.Method ExplorationMethod; + + public object TypeId; + + static PexExplorableFromConstructorAttribute() + { + } + + static PexExplorableFromConstructorAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexExplorableFromMethodAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExplorableType; + + public Microsoft.ExtendedReflection.Metadata.Method ExplorationMethod; + + public object TypeId; + + static PexExplorableFromMethodAttribute() + { + } + + static PexExplorableFromMethodAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = false, Inherited = true)] + public class PexInvariantControllerAttribute : System.Attribute + { + + public System.Type ControllerType; + + public object TypeId; + + static PexInvariantControllerAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class PexNotCompilableAttribute : System.Attribute + { + + public object TypeId; + + static PexNotCompilableAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + public class PexInjectedExceptionAttribute : System.Attribute + { + + public System.Type ExceptionType; + + public string Reason; + + public object TypeId; + + static PexInjectedExceptionAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public class PexUnexpectedExceptionAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExceptionType; + + public object TypeId; + + static PexUnexpectedExceptionAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCoverageFilterAssemblyAttribute : System.Attribute + { + + public System.Reflection.AssemblyName TargetAssemblyName; + + public Microsoft.Pex.Framework.PexCoverageDomain CoverageDomain; + + public object TypeId; + + static PexCoverageFilterAssemblyAttribute() + { + } + + static PexCoverageFilterAssemblyAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCoverageFilterNamespaceAttribute : System.Attribute + { + + public string NamespaceSuffix; + + public Microsoft.Pex.Framework.PexCoverageDomain CoverageDomain; + + public object TypeId; + + static PexCoverageFilterNamespaceAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCoverageFilterTypeAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeDefinition TargetType; + + public Microsoft.Pex.Framework.PexCoverageDomain CoverageDomain; + + public object TypeId; + + static PexCoverageFilterTypeAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCoverageFilterTypesAttribute : System.Attribute + { + + public string NameSuffix; + + public Microsoft.Pex.Framework.PexCoverageDomain CoverageDomain; + + public object TypeId; + + static PexCoverageFilterTypesAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCoverageFilterMarkedByAttribute : System.Attribute + { + + public System.Type AttributeType; + + public Microsoft.Pex.Framework.PexCoverageDomain CoverageDomain; + + public object TypeId; + + static PexCoverageFilterMarkedByAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCoverageFilterMethodAttribute : System.Attribute + { + + public Microsoft.Pex.Framework.PexCoverageDomain CoverageDomain; + + public object TypeId; + + static PexCoverageFilterMethodAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = true, Inherited = true)] + public class PexAssumeEnumRangeAttribute : System.Attribute + { + + public object TypeId; + + static PexAssumeEnumRangeAttribute() + { + } + + static PexAssumeEnumRangeAttribute() + { + } + + static PexAssumeEnumRangeAttribute() + { + } + } + + [System.AttributeUsageAttribute((System.AttributeTargets.Class | System.AttributeTargets.Method), AllowMultiple = false, Inherited = true)] + public class PexExplicitAttribute : System.Attribute + { + + public object TypeId; + + static PexExplicitAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class PexInvariantAttribute : System.Attribute + { + + public object TypeId; + + static PexInvariantAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class DecimalExplorableAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExplorableType; + + public Microsoft.ExtendedReflection.Metadata.Method ExplorationMethod; + + public object TypeId; + + static DecimalExplorableAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class DateTimeCreatableAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static DateTimeCreatableAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class ArrayListExplorableAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExplorableType; + + public Microsoft.ExtendedReflection.Metadata.Method ExplorationMethod; + + public object TypeId; + + static ArrayListExplorableAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class QueueExplorableAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExplorableType; + + public Microsoft.ExtendedReflection.Metadata.Method ExplorationMethod; + + public object TypeId; + + static QueueExplorableAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class StackExplorableAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExplorableType; + + public Microsoft.ExtendedReflection.Metadata.Method ExplorationMethod; + + public object TypeId; + + static StackExplorableAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = false, Inherited = true)] + public class PexAssemblySettingsAttribute : System.Attribute + { + + public string TestFramework; + + public string TestLanguage; + + public bool TestNoPartialClasses; + + public bool TestNoClassAttribute; + + public bool TestOverrideReadonly; + + public bool TestGenerateDuplicates; + + public string TestRootNamespace; + + public bool TestForceFixtureSetupTeardown; + + public string TestCopyright; + + public int RequiredCoveragePercentile; + + public bool NoSeparateAppDomain; + + public bool UseNoImplicitMocks; + + public string Categories; + + public int MaxBranches; + + public int MaxRounds; + + public int MaxRuns; + + public int MaxRunsWithUniqueBranchHits; + + public int MaxRunsWithUniquePaths; + + public int MaxCalls; + + public int MaxConditions; + + public int MaxBranchHits; + + public int MaxExceptions; + + public int ConstraintSolverTimeout; + + public int Timeout; + + public string CoverageFileFormat; + + public string TouchMyCode; + + public string TestClassName; + + public bool TestExcludeNonTermination; + + public bool TestDisableNonTermination; + + public Microsoft.Pex.Framework.PexTestEmissionFilter TestEmissionFilter; + + public bool PruneExceptions; + + public bool Joins; + + public bool NoSoftSubstitutions; + + public bool SymbolicCalls; + + public Microsoft.Pex.Framework.Strategies.PexSearchFrontier SearchFrontier; + + public string CustomSolver; + + public Microsoft.Pex.Framework.Strategies.PexCoverageGoal CoverageGoal; + + public string CssProjectStructure; + + public string CssIteration; + + public bool ContainsSettings; + + public System.Collections.Generic.IEnumerable ActiveSettings; + + public object TypeId; + + static PexAssemblySettingsAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexSettingsMixAttribute : System.Attribute + { + + public string MixName; + + public int MixReportOrder; + + public string Categories; + + public int MaxBranches; + + public int MaxRounds; + + public int MaxRuns; + + public int MaxRunsWithUniqueBranchHits; + + public int MaxRunsWithUniquePaths; + + public int MaxCalls; + + public int MaxConditions; + + public int MaxBranchHits; + + public int MaxExceptions; + + public int ConstraintSolverTimeout; + + public int Timeout; + + public string CoverageFileFormat; + + public string TouchMyCode; + + public string TestClassName; + + public bool TestExcludeNonTermination; + + public bool TestDisableNonTermination; + + public Microsoft.Pex.Framework.PexTestEmissionFilter TestEmissionFilter; + + public bool PruneExceptions; + + public bool Joins; + + public bool NoSoftSubstitutions; + + public bool SymbolicCalls; + + public Microsoft.Pex.Framework.Strategies.PexSearchFrontier SearchFrontier; + + public string CustomSolver; + + public Microsoft.Pex.Framework.Strategies.PexCoverageGoal CoverageGoal; + + public string CssProjectStructure; + + public string CssIteration; + + public bool ContainsSettings; + + public System.Collections.Generic.IEnumerable ActiveSettings; + + public object TypeId; + + static PexSettingsMixAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseTypeAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx TargetType; + + public object TypeId; + + static PexUseTypeAttribute() + { + } + + static PexUseTypeAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseTypesFromFactoryAttribute : System.Attribute + { + + public object TypeId; + + static PexUseTypesFromFactoryAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseAssemblyAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.AssemblyEx TargetAssembly; + + public object TypeId; + + static PexUseAssemblyAttribute() + { + } + + static PexUseAssemblyAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseImplementationsOfAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx TargetType; + + public Microsoft.ExtendedReflection.Metadata.AssemblyEx TargetAssembly; + + public object TypeId; + + static PexUseImplementationsOfAttribute() + { + } + + static PexUseImplementationsOfAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseNamespaceAttribute : System.Attribute + { + + public string NamespaceName; + + public bool Strict; + + public Microsoft.ExtendedReflection.Metadata.AssemblyEx TargetAssembly; + + public object TypeId; + + static PexUseNamespaceAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseMarkedByAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx AttributeType; + + public Microsoft.ExtendedReflection.Metadata.AssemblyEx TargetAssembly; + + public object TypeId; + + static PexUseMarkedByAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatableByConstructorAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx CreatableType; + + public object TypeId; + + static PexCreatableByConstructorAttribute() + { + } + } + + [System.AttributeUsageAttribute((((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method) + | System.AttributeTargets.Parameter), AllowMultiple = true, Inherited = true)] + public class PexExplorableFromFactoryAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx FactoryType; + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExplorableType; + + public Microsoft.ExtendedReflection.Metadata.Method ExplorationMethod; + + public object TypeId; + + static PexExplorableFromFactoryAttribute() + { + } + + static PexExplorableFromFactoryAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexCreatablesAsWebDataFromXmlNamespaceAttribute : System.Attribute + { + + public string XmlNamespace; + + public object TypeId; + + static PexCreatablesAsWebDataFromXmlNamespaceAttribute() + { + } + + static PexCreatablesAsWebDataFromXmlNamespaceAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFromAssemblyAttribute : System.Attribute + { + + public System.Reflection.AssemblyName TargetAssembly; + + public bool DeriveSubtypes; + + public Microsoft.Pex.Framework.PexFromAction Action; + + public object TypeId; + + static PexFromAssemblyAttribute() + { + } + + static PexFromAssemblyAttribute() + { + } + + static PexFromAssemblyAttribute() + { + } + + static PexFromAssemblyAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFromNamespaceAttribute : System.Attribute + { + + public string Namespace; + + public System.Reflection.AssemblyName TargetAssembly; + + public bool DeriveSubtypes; + + public Microsoft.Pex.Framework.PexFromAction Action; + + public object TypeId; + + static PexFromNamespaceAttribute() + { + } + + static PexFromNamespaceAttribute() + { + } + + static PexFromNamespaceAttribute() + { + } + + static PexFromNamespaceAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFromTypeAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeDefinition Type; + + public bool DeriveSubtypes; + + public Microsoft.Pex.Framework.PexFromAction Action; + + public object TypeId; + + static PexFromTypeAttribute() + { + } + + static PexFromTypeAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFromMarkedByAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx AttributeType; + + public System.Reflection.AssemblyName TargetAssembly; + + public bool DeriveSubtypes; + + public Microsoft.Pex.Framework.PexFromAction Action; + + public object TypeId; + + static PexFromMarkedByAttribute() + { + } + + static PexFromMarkedByAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFromFieldAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.Field Field; + + public Microsoft.Pex.Framework.PexFromAction Action; + + public object TypeId; + + static PexFromFieldAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFromConstructorAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.Method Constructor; + + public Microsoft.Pex.Framework.PexFromAction Action; + + public object TypeId; + + static PexFromConstructorAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFromMethodAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.Method Method; + + public Microsoft.Pex.Framework.PexFromAction Action; + + public object TypeId; + + static PexFromMethodAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class PexAttributeFamilyAttribute : System.Attribute + { + + public Microsoft.Pex.Framework.PexAttributeFamily Family; + + public object TypeId; + + static PexAttributeFamilyAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexInvariantCheckAttribute : System.Attribute + { + + public object TypeId; + + static PexInvariantCheckAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class PexKeepMeAttribute : System.Attribute + { + + public object TypeId; + + static PexKeepMeAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexInjectExceptionsOnWriteAttribute : System.Attribute + { + + public object TypeId; + + static PexInjectExceptionsOnWriteAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexFixItEmitterFactoryAttribute : System.Attribute + { + + public System.Type FixItEmitterFactoryType; + + public object TypeId; + + static PexFixItEmitterFactoryAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = true, Inherited = true)] + public class PexUseRangeAttribute : System.Attribute + { + + public object TypeId; + + static PexUseRangeAttribute() + { + } + + static PexUseRangeAttribute() + { + } + + static PexUseRangeAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple = false, Inherited = false)] + public class PexInstrumentedAttribute : System.Attribute + { + + public object TypeId; + + static PexInstrumentedAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple = false, Inherited = false)] + public class PexMockAttribute : System.Attribute + { + + public object TypeId; + + static PexMockAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInstrumentMarkedByAttribute : System.Attribute + { + + public System.Reflection.Assembly TargetAssembly; + + public System.Type AttributeType; + + public Microsoft.Pex.Framework.PexInstrumentationLevel InstrumentationLevel; + + public bool NoNestedTypes; + + public object TypeId; + + static PexInstrumentMarkedByAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInstrumentMocksAttribute : System.Attribute + { + + public System.Reflection.Assembly TargetAssembly; + + public System.Type AttributeType; + + public Microsoft.Pex.Framework.PexInstrumentationLevel InstrumentationLevel; + + public bool NoNestedTypes; + + public object TypeId; + + static PexInstrumentMocksAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseMocksAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx AttributeType; + + public Microsoft.ExtendedReflection.Metadata.AssemblyEx TargetAssembly; + + public object TypeId; + + static PexUseMocksAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInstrumentAssemblyAttribute : System.Attribute + { + + public string TargetAssemblyName; + + public Microsoft.Pex.Framework.PexInstrumentationLevel InstrumentationLevel; + + public object TypeId; + + static PexInstrumentAssemblyAttribute() + { + } + + static PexInstrumentAssemblyAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInstrumentAssembliesFromAttribute : System.Attribute + { + + public string Path; + + public string SearchPattern; + + public Microsoft.Pex.Framework.PexInstrumentationLevel InstrumentationLevel; + + public object TypeId; + + static PexInstrumentAssembliesFromAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = true, Inherited = true)] + public class PexUseUnicodeStringsAttribute : System.Attribute + { + + public object TypeId; + + static PexUseUnicodeStringsAttribute() + { + } + + static PexUseUnicodeStringsAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexRollbackAttribute : System.Attribute + { + + public object TypeId; + + static PexRollbackAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexExpectedExceptionAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx ExpectedExceptionType; + + public string Description; + + public string UserAssemblies; + + public bool AcceptExceptionSubtypes; + + public bool AcceptInnerException; + + public object TypeId; + + static PexExpectedExceptionAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = true, Inherited = true)] + public class PexAssumeIsNotNullAttribute : System.Attribute + { + + public object TypeId; + + static PexAssumeIsNotNullAttribute() + { + } + + static PexAssumeIsNotNullAttribute() + { + } + + static PexAssumeIsNotNullAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInstrumentTypesByNameAttribute : System.Attribute + { + + public Microsoft.Pex.Framework.PexInstrumentationLevel InstrumentationLevel; + + public bool NoNestedTypes; + + public object TypeId; + + static PexInstrumentTypesByNameAttribute() + { + } + + static PexInstrumentTypesByNameAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInstrumentTypeAttribute : System.Attribute + { + + public System.Type TargetType; + + public Microsoft.Pex.Framework.PexInstrumentationLevel InstrumentationLevel; + + public bool NoNestedTypes; + + public object TypeId; + + static PexInstrumentTypeAttribute() + { + } + + static PexInstrumentTypeAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexInstrumentNamespaceAttribute : System.Attribute + { + + public System.Reflection.Assembly TargetAssembly; + + public string Namespace; + + public bool IgnoreSubNamespaces; + + public Microsoft.Pex.Framework.PexInstrumentationLevel InstrumentationLevel; + + public bool NoNestedTypes; + + public object TypeId; + + static PexInstrumentNamespaceAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] + public class PexTestFrameworkAttribute : System.Attribute + { + + public System.Type TestFrameworkType; + + public object TypeId; + + static PexTestFrameworkAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = false, Inherited = true)] + public class PexGeneratedByAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx FixtureType; + + public string ExplorationName; + + public object TypeId; + + static PexGeneratedByAttribute() + { + } + } + + [System.AttributeUsageAttribute((((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method) + | System.AttributeTargets.Parameter), AllowMultiple = true, Inherited = true)] + public class PexUseValuesFromFactoryAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeEx FactoryType; + + public object TypeId; + + static PexUseValuesFromFactoryAttribute() + { + } + + static PexUseValuesFromFactoryAttribute() + { + } + + static PexUseValuesFromFactoryAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexExpectedTestsAttribute : System.Attribute + { + + public int TotalCount; + + public int DuplicateCount; + + public int FailureCount; + + public int NewCount; + + public object TypeId; + + static PexExpectedTestsAttribute() + { + } + } + + [System.AttributeUsageAttribute(((((((((((((((System.AttributeTargets.Assembly | System.AttributeTargets.Module) + | System.AttributeTargets.Class) + | System.AttributeTargets.Struct) + | System.AttributeTargets.Enum) + | System.AttributeTargets.Constructor) + | System.AttributeTargets.Method) + | System.AttributeTargets.Property) + | System.AttributeTargets.Field) + | System.AttributeTargets.Event) + | System.AttributeTargets.Interface) + | System.AttributeTargets.Parameter) + | System.AttributeTargets.Delegate) + | System.AttributeTargets.ReturnValue) + | System.AttributeTargets.GenericParameter), AllowMultiple = true, Inherited = true)] + public class PexAssumeRangeAttribute : System.Attribute + { + + public object TypeId; + + static PexAssumeRangeAttribute() + { + } + + static PexAssumeRangeAttribute() + { + } + + static PexAssumeRangeAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexInjectValuesAttribute : System.Attribute + { + + public object TypeId; + + static PexInjectValuesAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexInjectExceptionsOnXmlDocumentedCallAttribute : System.Attribute + { + + public bool IgnoreUncreatableExceptionTypes; + + public bool AllowExceptionSubtypes; + + public object TypeId; + + static PexInjectExceptionsOnXmlDocumentedCallAttribute() + { + } + + static PexInjectExceptionsOnXmlDocumentedCallAttribute() + { + } + + static PexInjectExceptionsOnXmlDocumentedCallAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class PexInvariantClassAttribute : System.Attribute + { + + public object TypeId; + + static PexInvariantClassAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class PexNotReproducibleAttribute : System.Attribute + { + + public object TypeId; + + static PexNotReproducibleAttribute() + { + } + } + + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + public class PexInjectedValueAttribute : System.Attribute + { + + public string Value; + + public string Reason; + + public object TypeId; + + static PexInjectedValueAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexInjectExceptionsOnUnverifiableUnsafeMemoryAccessAttribute : System.Attribute + { + + public System.Type ExceptionType; + + public object TypeId; + + static PexInjectExceptionsOnUnverifiableUnsafeMemoryAccessAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexFocusOnTypeAttribute : System.Attribute + { + + public Microsoft.ExtendedReflection.Metadata.TypeDefinition TargetTypeDefinition; + + public bool NoNestedTypes; + + public Microsoft.Pex.Framework.PexSearchPriority SearchPriority; + + public bool DoNotReportCoverage; + + public object TypeId; + + static PexFocusOnTypeAttribute() + { + } + + static PexFocusOnTypeAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexExplorablesFromMocksAttribute : System.Attribute + { + + public object TypeId; + + static PexExplorablesFromMocksAttribute() + { + } + + static PexExplorablesFromMocksAttribute() + { + } + } + + [System.AttributeUsageAttribute(((System.AttributeTargets.Assembly | System.AttributeTargets.Class) + | System.AttributeTargets.Method), AllowMultiple = true, Inherited = true)] + public class PexUseMaxInstancesAttribute : System.Attribute + { + + public object TypeId; + + static PexUseMaxInstancesAttribute() + { + } + + static PexUseMaxInstancesAttribute() + { + } + } + + public sealed class AssertionViolationException : System.Exception + { + + public AssertionViolationException(string message) + : + base(message) + { + } + } +} +#endif \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs.meta new file mode 100644 index 0000000..f30eb86 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Tests/testframework.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 64c1952446fe74d3ca2783e043d7ce74 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit.meta new file mode 100644 index 0000000..839e463 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 1213fe9297e2e44858bf9d01801280e7 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs new file mode 100755 index 0000000..a03b5ef --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false)] + public sealed class AssemblySetUpAndTearDownAttribute : Attribute + { + private Type targetType; + public AssemblySetUpAndTearDownAttribute( + Type targetType + ) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + this.targetType = targetType; + } + + public Type TargetType + { + get { return this.targetType; } + set { this.targetType = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs.meta new file mode 100644 index 0000000..bc5e4b2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAndTearDownAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55c59a74b8f2d4de28d1618135ac1449 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs new file mode 100755 index 0000000..8eaa15c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=false)] + public sealed class AssemblySetUpAttribute : Attribute + {} +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs.meta new file mode 100644 index 0000000..8530363 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblySetUpAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48a02254a2535404193a4ba33eb36081 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs new file mode 100755 index 0000000..d517f20 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=false)] + public sealed class AssemblyTearDownAttribute : Attribute + {} +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs.meta new file mode 100644 index 0000000..630bbd0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/AssemblyTearDownAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 59291871ef1634f3e885bcb94e38e393 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs new file mode 100755 index 0000000..2a8c35f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs @@ -0,0 +1,435 @@ +using System; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; +using QuickGraph.Unit.Exceptions; + +namespace QuickGraph.Unit +{ + public static class Assert + { + #region Synching + private static volatile object syncRoot = new object(); + public static object SyncRoot + { + get { return syncRoot; } + } + #endregion + + #region Log + private static IServiceProvider serviceProvider = null; + public static IServiceProvider ServiceProvider + { + get + { + lock (syncRoot) + { + return serviceProvider; + } + } + set + { + lock (syncRoot) + { + serviceProvider = value; + } + } + } + public static ILoggerService Logger + { + get + { + return + ServiceProvider.GetService(typeof(ILoggerService)) + as ILoggerService; + } + } + #endregion + + #region IsLower, Greater + public static void IsLowerEqual(object left, object right, IComparer comparer) + { + if (comparer.Compare(left, right) > 0) + Fail("{0} must be lower or equal than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsLowerEqual(T left, T right, IComparer comparer) + { + if (comparer.Compare(left, right) > 0) + Fail("{0} must be lower or equal than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsLowerEqual(IComparable left, T right) + { + Assert.IsTrue(left.CompareTo(right)<=0, "{0} must be lower or equal to {1}", left, right); + } + public static void IsLowerEqual(IComparable left, IComparable right) + { + Assert.IsTrue(left.CompareTo(right) <= 0, "{0} must be lower or equal to {1}", left, right); + } + + public static void IsLower(object left, object right, IComparer comparer) + { + if (comparer.Compare(left, right) >= 0) + Fail("{0} must be lower than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsLower(T left, T right, IComparer comparer) + { + if (comparer.Compare(left, right) >= 0) + Fail("{0} must be lower than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsLower(IComparable left, T right) + { + Assert.IsTrue(left.CompareTo(right) < 0, "{0} must be lower to {1}", left, right); + } + public static void IsLower(IComparable left, IComparable right) + { + Assert.IsTrue(left.CompareTo(right) < 0, "{0} must be lower to {1}", left, right); + } + + public static void IsGreaterEqual(object left, object right, IComparer comparer) + { + if (comparer.Compare(left, right) < 0) + Fail("{0} must be greater or equal than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsGreaterEqual(T left, T right, IComparer comparer) + { + if (comparer.Compare(left, right) < 0) + Fail("{0} must be greater or equal than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsGreaterEqual(IComparable left, T right) + { + Assert.IsTrue(left.CompareTo(right) >= 0, "{0} must be greater or equal to {1}", left, right); + } + public static void IsGreaterEqual(IComparable left, IComparable right) + { + Assert.IsTrue(left.CompareTo(right) >= 0, "{0} must be greater or equal to {1}", left, right); + } + + public static void IsGreater(object left, object right, IComparer comparer) + { + if (comparer.Compare(left, right) <= 0) + Fail("{0} must be greater than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsGreater(T left, T right, IComparer comparer) + { + if (comparer.Compare(left, right) <= 0) + Fail("{0} must be greater than {1} (comparing with {2})", + left, right, + comparer); + } + + public static void IsGreater(IComparable left, T right) + { + Assert.IsTrue(left.CompareTo(right) > 0, "{0} must be greater to {1}", left, right); + } + public static void IsGreater(IComparable left, IComparable right) + { + Assert.IsTrue(left.CompareTo(right) > 0, "{0} must be greater to {1}", left, right); + } + #endregion + + #region AreSame + public static void AreSame(object actual, object expected) + { + Assert.AreEqual(actual, expected); + } + + public static void AreSame(object actual, object expected, string message) + { + Assert.AreEqual(actual, expected, message); + } + + public static void AreSame(object actual, object expected, string format, params object[] args) + { + Assert.AreEqual(actual, expected, format, args); + } + #endregion + + #region AreNotEqual + public static void AreNotEqual(T left, T right, string format, params object[] args) + { + string message = String.Format(format,args); + AreNotEqual(left, right, message); + } + public static void AreNotEqual(T left, T right) + { + AreNotEqual(left, right, ""); + } + public static void AreNotEqual(T left, T right, string message) + { + if (left == null && right == null) + throw new AssertionException(String.Format("Objects are both nulls, {0}",message)); + if (left == null && right != null) + return; + if (right == null && left != null) + return; + + if (left.Equals(right)) + throw new AssertionException( + String.Format("[{0}]==[{1}], {2}", left, right, message) + ); + + } + #endregion + + #region AreEqual + public static void AreEqual(object left, object right, IComparer comparer) + { + if (comparer.Compare(left, right) != 0) + Fail("[{0}]!=[{1}] (comparing with {2})", + left, right, + comparer); + } + + public static void AreEqual(T left, T right, IComparer comparer) + { + if (comparer.Compare(left, right) != 0) + Fail("[{0}]!=[{1}] (comparing with {2})", + left, right, + comparer); + } + + public static void AreEqual(T left, T right, string message) + { + if (left == null && right == null) + return; + if (left == null && right != null) + throw new AssertionException( + String.Format("[{0}]!=[null], {1}", left, message) + ); + if (right == null && left != null) + throw new AssertionException( + String.Format("[{0}]!=null, {1}", right, message) + ); + + + if (!left.Equals(right)) + throw new AssertionException( + String.Format("[{0}]!=[{1}], {2}", left, right, message) + ); + } + + public static void AreEqual(T left, T right) + { + AreEqual(left, right, + "[{0}]!=[{1}]", left, right + ); + } + + public static void AreEqual(T left, T right, string format, params object[] args) + { + string message = String.Format(format, args); + AreEqual(left, right, message); + } +#endregion + + #region AreEqualNumeric + public static void AreEqual(double a, double b, double tolerance) + { + if (Math.Abs(a - b) > tolerance) + Assert.Fail("{0} not equal to {1} (tolerance {2})", + a, b, tolerance); + } + public static void AreEqual(float a, float b, float tolerance) + { + if (Math.Abs(a - b) > tolerance) + Assert.Fail("{0} not equal to {1} (tolerance {2})", + a, b, tolerance); + } + #endregion + + #region IsNull, IsNotNull + public static void IsNull(T o, string message) + { + if (o != null) + throw new AssertionException( + String.Format("{0} is not a null reference, {1}", o, message) + ); + } + + public static void IsNotNull(T o, string message) + { + if (o == null) + throw new AssertionException( + String.Format("{0} is a null reference", o, message) + ); + } + + public static void IsNull(T o) + { + IsNull(o,""); + } + + public static void IsNotNull(T o) + { + IsNotNull(o, ""); + } + + + public static void IsNull(T o, string format, params object[] args) + { + string message = String.Format(format, args); + IsNull(o, message); + } + + public static void IsNotNull(T o, string format, params object[] args) + { + string message = String.Format(format, args); + IsNotNull(o, message); + } +#endregion + + #region True, false + public static void IsTrue(bool value, string message) + { + if (!value) + throw new AssertionException( + String.Format("Expected true got false, {0}", message) + ); + } + + public static void IsFalse(bool value, string message) + { + if (value) + throw new AssertionException( + String.Format("Expected false, got true, {0}", message) + ); + } + + public static void IsTrue(bool o) + { + IsTrue(o, ""); + } + + public static void IsFalse(bool o) + { + IsFalse(o, ""); + } + + + public static void IsTrue(bool o, string format, params object[] args) + { + string message = String.Format(format, args); + IsTrue(o, message); + } + + public static void IsFalse(bool o, string format, params object[] args) + { + string message = String.Format(format, args); + IsFalse(o, message); + } + #endregion + + #region Lower, etc... + public static void LowerEqualThan(T left, T right) + where T : IComparable + { + LowerEqualThan(left, right, ""); + } + public static void LowerEqualThan(T left, T right, string format, params object[] args) + where T : IComparable + { + string message = String.Format(format, args); + LowerEqualThan(left, right, message); + } + public static void LowerEqualThan(T left, T right, string message) + where T : IComparable + { + if (left.CompareTo(right) > 0) + throw new AssertionException( + String.Format("[{0}]>[{1}], {2}", + left, right, message) + ); + } + #endregion + + #region Fail + public static void Fail() + { + throw new AssertionException(); + } + + public static void Fail(string message) + { + throw new AssertionException(message); + } + + public static void Fail(string format, params object[] args) + { + string message = String.Format(format, args); + Fail(message); + } + #endregion + + #region Ignore + public static void Ignore(string message) + { + throw new IgnoreException(message); + } + + public static void Ignore(string format, params object[] parameters) + { + Ignore(String.Format(format, parameters)); + } + #endregion + + #region Warning + public static void Warning(string message) + { + throw new NotImplementedException(); + } + + public static void Warning(string format, params object[] parameters) + { + Warning(String.Format(format, parameters)); + } + #endregion + + #region + public static void ExpectedException( + Type expectedException, Delegate test, params object[] args) + { + try + { + test.DynamicInvoke(args); + throw new ExceptionNotThrowedException(expectedException); + } + catch (Exception ex) + { + Exception current = ex; + // check if current expection is expecetd or ignored + while (current != null) + { + if (current.GetType() == expectedException) + return; + current = current.InnerException; + } + current = ex; + if (current is TargetInvocationException) + current = current.InnerException; + throw new ExceptionTypeMistmatchException(expectedException, current); + } + } + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs.meta new file mode 100644 index 0000000..6865267 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: abb9be8e37f0f4b7b99384514c2b505a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs new file mode 100755 index 0000000..ab800d3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs @@ -0,0 +1,20 @@ +using System; +using QuickGraph.Unit.Exceptions; + +namespace QuickGraph.Unit +{ + public static class Assume + { + public static void IsTrue(bool value) + { + if (!value) + throw new AssumptionFailureException(); + } + + public static void IsFalse(bool value) + { + if (value) + throw new AssumptionFailureException(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs.meta new file mode 100644 index 0000000..7ba48d8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Assume.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bfa076b39e5fd426391a6d28a525637a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs new file mode 100755 index 0000000..6162307 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace QuickGraph.Unit +{ + public static class CollectionAssert + { + public static void DoesNotContainKey(IDictionary dictionary, object key) + { + Assert.IsFalse(dictionary.Contains(key), + "Collection contains {0}", key); + } + + public static void DoesNotContainKey(IDictionary dictionary, K value) + { + Assert.IsFalse(dictionary.ContainsKey(value), + "Collection contains {0}", value); + } + + public static void ContainsKey(IDictionary dictionary, object key) + { + Assert.IsTrue(dictionary.Contains(key), + "Collection does not contain {0}", key); + } + + public static void ContainsKey(IDictionary dictionary, K value) + { + Assert.IsTrue(dictionary.ContainsKey(value), + "Collection does not contain {0}", value); + } + + public static void DoesNotContain(IEnumerable collection, object value) + { + foreach(object item in collection) + { + Assert.AreNotEqual(item, value,"Collection contains {0}", value); + } + } + + public static void DoesNotContain(ICollection collection, T value) + { + Assert.IsFalse(collection.Contains(value), + "Collection contains {0}", value); + } + + public static void Contains(ICollection collection, object value) + { + foreach(object item in collection) + { + if (item.Equals(value)) + return; + } + Assert.Fail("Collection does not contains {0}", value); + } + + public static void Contains(ICollection collection, T value) + { + Assert.IsTrue(collection.Contains(value), + "Collection does not contain {0}",value); + } + + public static void AreEqual(ICollection left, ICollection right) + { + AreCountEqual(left, right); + AreElementEqual(left, right); + } + + public static void AreEqual(ICollection left, ICollection right) + { + AreCountEqual(left, right); + AreElementEqual(left, right); + } + + public static void AreCountEqual(ICollection left, ICollection right) + { + Assert.AreEqual(left.Count, right.Count, + "Count is not equal"); + } + + public static void AreCountEqual(ICollection left, ICollection right) + { + Assert.AreEqual(left.Count, right.Count, + "Count is not equal"); + } + + public static void IsCountEqual(int count, ICollection collection) + { + Assert.AreEqual(count, collection.Count, + "collection.Count ({0}) is not equal to {1}", count, collection.Count); + } + + public static void IsCountEqual(int count, ICollection collection) + { + Assert.AreEqual(count, collection.Count, + "collection.Count ({0}) is not equal to {1}", count, collection.Count); + } + + public static void AreElementEqual(IEnumerable left, IEnumerable right) + { + IEnumerator leftEnumerator = left.GetEnumerator(); + IEnumerator rightEnumerator = right.GetEnumerator(); + try + { + int i = 0; + bool moveNext; + do + { + moveNext = leftEnumerator.MoveNext(); + Assert.AreEqual(moveNext, rightEnumerator.MoveNext(), + "Collection have not the same size"); + if (moveNext) + { + Assert.AreEqual(leftEnumerator.Current, rightEnumerator.Current, + "Element {0} is not equal", i); + } + i++; + } while (moveNext); + } + finally + { + IDisposable disposable = leftEnumerator as IDisposable; + if (disposable != null) + disposable.Dispose(); + disposable = rightEnumerator as IDisposable; + if (disposable != null) + disposable.Dispose(); + } + } + + public static void AreElementEqual(IEnumerable left, IEnumerable right) + { + using (IEnumerator leftEnumerator = left.GetEnumerator()) + using (IEnumerator rightEnumerator = right.GetEnumerator()) + { + int i=0; + bool moveNext; + do + { + moveNext = leftEnumerator.MoveNext(); + Assert.AreEqual(moveNext, rightEnumerator.MoveNext(), + "Collection have not the same size"); + if (moveNext) + { + Assert.AreEqual(leftEnumerator.Current, rightEnumerator.Current, + "Element {0} is not equal", i); + } + i++; + } while (moveNext); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs.meta new file mode 100644 index 0000000..1b6de65 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CollectionAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 849a7a1694b924f4bbf684099d76eb1c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs new file mode 100755 index 0000000..39faeed --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Operations; +using System.IO; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple =false, Inherited =true)] + public sealed class CombinatorialTestAttribute : TestAttributeBase + { + private CombinationType combination = CombinationType.PairWize; + + public CombinatorialTestAttribute() { } + public CombinatorialTestAttribute(CombinationType combination) + { + this.Combination = combination; + } + + public CombinationType Combination + { + get { return this.combination; } + set { this.combination = value; } + } + + public override IEnumerable CreateTests( + IFixture fixture, + MethodInfo method + ) + { + // check parameters + ParameterInfo[] parameters = method.GetParameters(); + if (parameters.Length < 1) + throw new InvalidOperationException("Method "+method.Name+" has not enough parameters"); + + // create the domains for each parameter + List domains = new List(); + Type[] parameterTypes = new Type[parameters.Length]; + for (int index = 0; index < parameters.Length; ++index) + { + ParameterInfo parameter = parameters[index]; + parameterTypes[index] = parameter.ParameterType; + + // get domains for parameter + List pdomains = new List(); + foreach (IParameterDomainFactory parameterDomainFactory + in parameter.GetCustomAttributes(typeof(UsingAttributeBase), true)) + { + try + { + parameterDomainFactory.CreateDomains(pdomains, parameter, fixture); + } + catch (Exception ex) + { + throw new ApplicationException("Failed while loading domains from parameter " + parameter.Name,ex); + } + } + if (pdomains.Count == 0) + throw new ApplicationException("Could not find domain for argument " + parameter.Name); + + domains.Add(Domains.ToDomain(pdomains)); + } + + // we make a cartesian product of all those + foreach (ITuple tuple in Products.Cartesian(domains)) + { + // create data domains + List tdomains = new List(); + for (int i = 0; i < tuple.Count; ++i) + { + IDomain dm = (IDomain)tuple[i]; + tdomains.Add(dm); + } + + // computing the pairwize product + IEnumerable ptproducts = Products.ComputeTupleProducts(tdomains, this.Combination); + + foreach (ITuple ptuple in ptproducts) + { + // tuple is valid, adding test + CombinatorialMethodTestCase test = + new CombinatorialMethodTestCase( + fixture.Name, + method, + tuple, + ptuple); + + yield return test; + } + } + } + + private sealed class CombinatorialMethodTestCase : MethodTestCase + { + private ITuple tupleDomains; + private ITuple tuple; + + public CombinatorialMethodTestCase( + string fixtureName, + MethodInfo method, + ITuple tupleDomains, + ITuple tuple + ) + : base(fixtureName, method) + { + if (tupleDomains == null) + throw new ArgumentNullException("tupleDomains"); + if (tuple == null) + throw new ArgumentNullException("tuple"); + + this.tupleDomains = tupleDomains; + this.tuple = tuple; + + foreach (Object parameter in tuple) + this.Parameters.Add(new TestCaseParameter(parameter)); + } + + public override string Name + { + get + { + StringWriter sw = new StringWriter(); + for (int i = 0; i < this.tupleDomains.Count; ++i) + { + IDomain dm = (IDomain)this.tupleDomains[i]; + if (dm.Name != null) + sw.Write("{0}({1}),", dm.Name, this.tuple[i]); + else + sw.Write("{0},", this.tuple[i]); + } + return String.Format("{0}({1})", this.Method.Name, sw.ToString().TrimEnd(',')); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs.meta new file mode 100644 index 0000000..ad867a5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CombinatorialTestAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6a97e1f14437841fbb2c8261816622f5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine.meta new file mode 100644 index 0000000..f9f2922 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 53420897a3fa04aff97e2d3a3bfa7736 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs new file mode 100755 index 0000000..b20dcac --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs @@ -0,0 +1,49 @@ +using System; +using System.Xml.Serialization; +namespace QuickGraph.CommandLine +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public class ArgumentAttribute : Attribute + { + private string longName; + private string shortName; + private string description = ""; + + public ArgumentAttribute() + { } + + public ArgumentAttribute( + string longName, + string shortName, + string description + ) + { + this.longName = longName; + this.shortName = shortName; + this.description = description; + } + + public virtual bool IsDefault + { + get { return false; } + } + + public string LongName + { + get { return this.longName; } + set { this.longName = value; } + } + + public string ShortName + { + get { return this.shortName; } + set { this.shortName = value; } + } + + public string Description + { + get { return this.description; } + set { this.description = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs.meta new file mode 100644 index 0000000..05f8bfa --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fff70d57a547a4587ae078413968c87a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs new file mode 100755 index 0000000..b9edd13 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; + +namespace QuickGraph.CommandLine +{ + internal abstract class ArgumentParserBase : IArgumentParser + { + private string flags = "/-"; + private IMember member; + private ArgumentAttribute argument; + private bool isMultiple; + + public ArgumentParserBase( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + { + if (member == null) + throw new ArgumentNullException("member"); + if (argument==null) + throw new ArgumentNullException("argument"); + this.member = member; + this.argument = argument; + this.isMultiple = isMultiple; + } + + public IMember Member + { + get { return this.member; } + } + public ArgumentAttribute Argument + { + get { return this.argument; } + } + + public bool IsMultiple + { + get { return this.isMultiple; } + } + + public Type ElementType + { + get + { + if (!this.IsMultiple) + return Member.MemberType; + else + return Member.MemberType.GetGenericArguments()[0]; + } + } + + public bool IsFlag(Char c) + { + return this.flags.IndexOf(c) > 0; + } + + public abstract bool Parse(object instance, string arg); + + protected string ExtractValue(string data) + { + if (IsFlag(data[0])) + { + if (this.Argument.IsDefault) + return data; + else + return null; + } + + int index = data.IndexOf(':'); + if (index < 0) + return null; + // check name is correct + string arg = data.Substring(1, index-1); + if (arg != this.Argument.LongName && + arg != this.Argument.ShortName) + return null; + + return data.Substring(index+1); + } + + protected void AssignValue(object instance, object value) + { + if (this.IsMultiple) + this.AddToList(instance, value); + else + this.Member.SetValue(instance, value); + } + + private void AddToList(object instance, object value) + { + MethodInfo addMethod = this.Member.MemberType.GetMethod( + "Add", new Type[] { this.ElementType } + ); + if (addMethod == null) + throw new ArgumentException("Could not find add method for field " + this.Member.Name); + addMethod.Invoke(this.Member.GetValue(instance), new object[] { value }); + } + + + public override string ToString() + { + return String.Format("P[{0}.{1}]", + this.Member.DeclaringType.FullName,this.Member.Name + ); + } + + public virtual void ShowHelp(TextWriter writer) + { + if (this.Argument.IsDefault) + { + writer.WriteLine("{0} (default)\n\tn: {1}\n\t{2}", + this.GetValidValues(), + (this.IsMultiple) ? "multiple" : "once", + this.Argument.Description + ); + } + else + { + writer.WriteLine("/{0}{2}\n/{1}{2}\n\tn: {3}\n\t{4}", + this.Argument.LongName, + this.Argument.ShortName, + this.GetValidValues(), + (this.IsMultiple) ? "multiple" : "once", + this.Argument.Description + ); + } + writer.WriteLine(); + } + + protected virtual string GetValidValues() + { + return String.Format(":<{0}>",this.Member.Name); + } + + public virtual void ShowData(object instance, TextWriter writer) + { + if (this.IsMultiple) + { + writer.WriteLine("{0}:", this.Member.Name); + foreach (object o in this.Member.GetValue(instance) as System.Collections.IEnumerable) + { + writer.WriteLine("\t{0}", o); + } + } + else + writer.WriteLine("{0}:\t{1}", + this.Member.Name, + this.Member.GetValue(instance) + ); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs.meta new file mode 100644 index 0000000..2cd99a1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c42a08566901842e090feaf0beaa8907 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs new file mode 100755 index 0000000..f078dde --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.CommandLine +{ + internal class ArgumentParserCollection : List + { + public IArgumentParser GetParserFromShortName(string name) + { + foreach (IArgumentParser parser in this) + { + if (parser.Argument.ShortName == name || + parser.Argument.LongName == name) + return parser; + } + return null; + } + + public IArgumentParser GetDefaultParser() + { + foreach (IArgumentParser parser in this) + { + if (parser.Argument.IsDefault) + return parser; + } + return null; + } + + public bool VerifyParsers() + { + Dictionary namedParsers = new Dictionary(); + IArgumentParser defaultParser = null; + int errorCount = 0; + foreach (IArgumentParser parser in this) + { + if (defaultParser!=null && parser.Argument.IsDefault) + { + Console.WriteLine("Duplicate default argument ({0}, {1})", + defaultParser.Member.Name, + parser.Member.Name); + errorCount++; + continue; + } + + if (parser.Argument.IsDefault) + { + defaultParser = parser; + continue; + } + + if (namedParsers.ContainsKey(parser.Argument.ShortName)) + { + Console.WriteLine("Short name {0} of {1} is a duplicate of {2}", + parser.Argument.ShortName, + parser.Member.Name, + namedParsers[parser.Argument.ShortName].Member.Name + ); + errorCount++; + continue; + } + + if (namedParsers.ContainsKey(parser.Argument.LongName)) + { + Console.WriteLine("Long name {0} of {1} is a duplicate of {2}", + parser.Argument.LongName, + parser.Member.Name, + namedParsers[parser.Argument.ShortName].Member.Name + ); + errorCount++; + continue; + } + } + + if (errorCount != 0) + Console.WriteLine("Found {0} errors", errorCount); + return errorCount == 0; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs.meta new file mode 100644 index 0000000..a1a3bd9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a7abacea9096d46c0910b48f266f6d6a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs new file mode 100755 index 0000000..5738d4b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal static class ArgumentParserFactory + { + public static IArgumentParser Create( + PropertyInfo property, + ArgumentAttribute argument + ) + { + bool isMultiple = property.PropertyType.GetGenericArguments().Length != 0; + if (!isMultiple) + return CreateFromType(property, argument, property.PropertyType, isMultiple); + else + return CreateFromType(property, argument, + property.PropertyType.GetGenericArguments()[0], + isMultiple); + } + + private static IArgumentParser CreateFromType( + PropertyInfo property, + ArgumentAttribute argument, + Type propertyType, + bool isMultiple + ) + { + // is the field type an enum + if (propertyType.IsEnum) + return new EnumArgumentParser(new PropertyMember(property), argument, isMultiple); + if (propertyType == typeof(bool)) + return new BoolArgumentParser(new PropertyMember(property), argument, isMultiple); + if (propertyType == typeof(string)) + return new StringArgumentParser(new PropertyMember(property), argument, isMultiple); + if (propertyType == typeof(int)) + return new IntArgumentParser(new PropertyMember(property), argument, isMultiple); + if (propertyType == typeof(float)) + return new FloatArgumentParser(new PropertyMember(property), argument, isMultiple); + if (propertyType == typeof(long)) + return new LongArgumentParser(new PropertyMember(property), argument, isMultiple); + if (propertyType == typeof(DateTime)) + return new DateTimeArgumentParser(new PropertyMember(property), argument, isMultiple); + + Console.WriteLine("Type {0} is not supported", propertyType); + return null; + } + + public static IArgumentParser Create( + FieldInfo field, + ArgumentAttribute argument + ) + { + bool isMultiple = field.FieldType.GetGenericArguments().Length != 0; + if (!isMultiple) + return CreateFromType(field, argument, field.FieldType, isMultiple); + else + return CreateFromType(field, argument, + field.FieldType.GetGenericArguments()[0], + isMultiple); + } + + private static IArgumentParser CreateFromType( + FieldInfo field, + ArgumentAttribute argument, + Type fieldType, + bool isMultiple + ) + { + // is the field type an enum + if (fieldType.IsEnum) + return new EnumArgumentParser(new FieldMember(field), argument, isMultiple); + if (fieldType == typeof(bool)) + return new BoolArgumentParser(new FieldMember(field), argument, isMultiple); + if (fieldType == typeof(string)) + return new StringArgumentParser(new FieldMember(field), argument, isMultiple); + if (fieldType == typeof(int)) + return new IntArgumentParser(new FieldMember(field), argument, isMultiple); + if (fieldType == typeof(float)) + return new FloatArgumentParser(new FieldMember(field), argument, isMultiple); + if (fieldType == typeof(long)) + return new LongArgumentParser(new FieldMember(field), argument, isMultiple); + if (fieldType == typeof(DateTime)) + return new DateTimeArgumentParser(new FieldMember(field), argument, isMultiple); + + Console.WriteLine("Type {0} is not supported", fieldType); + return null; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs.meta new file mode 100644 index 0000000..330f1e4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentParserFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 353a0b08f58914e3bb3b7b86457c5bf2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs new file mode 100755 index 0000000..bffdcae --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs @@ -0,0 +1,19 @@ +using System; + +namespace QuickGraph.CommandLine +{ + public abstract class ArgumentsBase + { + [Argument( + ShortName="h", + LongName="help", + Description="display this message")] + public bool Help = false; + + [Argument( + ShortName="sd", + LongName="show-data", + Description="displays the parsed data")] + public bool ShowData = false; + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs.meta new file mode 100644 index 0000000..7ac73ff --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ArgumentsBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0e375a3538ab64a0d91d20ae3e921e15 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs new file mode 100755 index 0000000..0cb37b9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs @@ -0,0 +1,53 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class BoolArgumentParser : ArgumentParserBase + { + public BoolArgumentParser( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + :base(member,argument,isMultiple) + { } + + public override bool Parse(object instance, string arg) + { + if (IsFlag(arg[0])) + return false; + + bool value = true; + int index = -1; + switch (arg[arg.Length - 1]) + { + case '+': + value = true; + index = arg.Length - 1; + break; + case '-': + value = false; + index = arg.Length - 1; + break; + default: + index = arg.Length; + break; + } + + // check name is correct + string name = arg.Substring(1, index - 1); + if (name != this.Argument.LongName && + name != this.Argument.ShortName) + return false; + + // assign value + this.AssignValue(instance, value); + return true; + } + + protected override string GetValidValues() + { + return "[+-]"; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs.meta new file mode 100644 index 0000000..cc562fa --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/BoolArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4bf7e7b294dde49d4b4ccd9d9621ca55 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs new file mode 100755 index 0000000..663e7b4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs @@ -0,0 +1,144 @@ +using System; +using System.Reflection; +using System.Collections.Generic; +using System.IO; + +namespace QuickGraph.CommandLine +{ + public sealed class CommandLineParser + where T : new() + { + private ArgumentParserCollection argumentParsers = new ArgumentParserCollection(); + + public static CommandLineParser Create() + { + CommandLineParser parser = new CommandLineParser(); + if (parser.ArgumentParsers.VerifyParsers()) + return parser; + else + return null; + } + + private CommandLineParser() + { + this.ReflectCommandLineType(); + } + + public Type CommandLineType + { + get { return typeof(T); } + } + + internal ArgumentParserCollection ArgumentParsers + { + get { return this.argumentParsers; } + } + + private static ArgumentAttribute GetAttribute(ICustomAttributeProvider t) + { + if (t == null) + throw new ArgumentNullException("t"); + + // Gets the attributes for the property. + Object[] attributes = + t.GetCustomAttributes(typeof(ArgumentAttribute), true); + + if (attributes.Length == 0) + return null; + if (attributes.Length == 1) + return (ArgumentAttribute)attributes[0]; + + throw new ArgumentException("Attribute type must be AllowMultiple = false", typeof(T).FullName); + } + + private void ReflectCommandLineType() + { + // get fields + foreach (FieldInfo field in typeof(T).GetFields()) + { + ArgumentAttribute attribute = GetAttribute(field); + if (attribute == null) + continue; + IArgumentParser parser = ArgumentParserFactory.Create(field, attribute); + if (parser == null) + throw new ArgumentException("Could not reflect " + field.Name); + this.ArgumentParsers.Add(parser); + } + + foreach (PropertyInfo property in typeof(T).GetProperties()) + { + ArgumentAttribute attribute = GetAttribute(property); + if (attribute == null) + continue; + IArgumentParser parser = ArgumentParserFactory.Create(property, attribute); + if (parser == null) + throw new ArgumentException("Could not reflect " + property.Name); + this.ArgumentParsers.Add(parser); + } + } + + public void ShowHelp() + { + ShowHelp(Console.Out); + } + + public void ShowHelp(TextWriter writer) + { + foreach (IArgumentParser parser in this.ArgumentParsers) + parser.ShowHelp(writer); + } + + public bool Parse(T arguments, IEnumerable args) + { + if (arguments == null) + throw new ArgumentNullException("arguments"); + + Dictionary touchedParsers = new Dictionary(); + foreach (string arg in args) + { + bool foundparser = false; + foreach (IArgumentParser parser in this.ArgumentParsers) + { + if (parser.Parse(arguments, arg)) + { + foundparser = true; + if (!parser.IsMultiple) + { + // did we already see this value + if (touchedParsers.ContainsKey(parser)) + { + // we found twice a non multiple value + throw new ArgumentException("Multiple value found", arg); + } + else + { + touchedParsers.Add(parser, null); + } + } + break; + } + } + if (!foundparser) + { + Console.WriteLine("Could not interpret {0}", arg); + return false; + } + } + + return true; + } + + public void ShowData(T arguments) + { + ShowData(arguments, Console.Out); + } + + public void ShowData(T arguments, TextWriter writer) + { + if (arguments == null) + throw new ArgumentNullException("arguments"); + foreach (IArgumentParser parser in this.ArgumentParsers) + parser.ShowData(arguments, writer); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs.meta new file mode 100644 index 0000000..91880f6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/CommandLineParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4ecc8ab8cb4b34c30a6d754be3542d10 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs new file mode 100755 index 0000000..2c30c45 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs @@ -0,0 +1,97 @@ +using System; + +namespace QuickGraph.CommandLine +{ + public static class ConsoleLog + { + private static ConsoleColor warningColor = ConsoleColor.Yellow; + private static ConsoleColor errorColor = ConsoleColor.Red; + private static ConsoleColor commentColor = ConsoleColor.DarkGray; + + public static ConsoleColor WarningColor + { + get { return warningColor; } + set { warningColor = value; } + } + + public static ConsoleColor ErrorColor + { + get { return errorColor; } + set { errorColor = value; } + } + + public static ConsoleColor CommentColor + { + get { return commentColor; } + set { commentColor = value; } + } + + public static void Message(string message) + { + Console.WriteLine(message); + } + + public static void Message(string format, params object[] args) + { + Console.WriteLine(format, args); + } + + public static void Warning(string message) + { + Log(WarningColor, message); + } + + public static void Warning(string format, params object[] args) + { + Log(WarningColor, format, args); + } + + public static void Error(string message) + { + Log(ErrorColor, message); + } + + public static void Error(string format, params object[] args) + { + Log(ErrorColor, format, args); + } + + public static void Comment(string message) + { + Log(CommentColor, message); + } + + public static void Comment(string format, params object[] args) + { + Log(CommentColor, format, args); + } + + public static void Log(ConsoleColor color, string message) + { + ConsoleColor currentColor = Console.ForegroundColor; + try + { + Console.ForegroundColor = color; + Console.WriteLine(message); + } + finally + { + Console.ForegroundColor = currentColor; + } + } + + public static void Log(ConsoleColor color, string format, params object[] args) + { + ConsoleColor currentColor = Console.ForegroundColor; + try + { + Console.ForegroundColor = color; + Console.WriteLine(format, args); + } + finally + { + Console.ForegroundColor = currentColor; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs.meta new file mode 100644 index 0000000..d9a44b3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/ConsoleLog.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d15ab477532774213895bea9c80fa6d7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs new file mode 100755 index 0000000..98286ea --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs @@ -0,0 +1,24 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class DateTimeArgumentParser : ArgumentParserBase + { + public DateTimeArgumentParser( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + : base(member, argument, isMultiple) + { } + + public override bool Parse(object instance, string arg) + { + string value = this.ExtractValue(arg); + if (value == null) + return false; + this.AssignValue(instance, DateTime.Parse(value)); + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs.meta new file mode 100644 index 0000000..c16876b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DateTimeArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c2b39b3a0154f49bd9815c7ef0c3fdb2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs new file mode 100755 index 0000000..870848b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs @@ -0,0 +1,18 @@ +using System; + +namespace QuickGraph.CommandLine +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public sealed class DefaultArgumentAttribute : ArgumentAttribute + { + public DefaultArgumentAttribute(string description) + { + this.Description = description; + } + + public override bool IsDefault + { + get { return true; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs.meta new file mode 100644 index 0000000..1c53de8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/DefaultArgumentAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d3bd340d70bfb44658aab46496cfa49c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs new file mode 100755 index 0000000..5b60546 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs @@ -0,0 +1,44 @@ +using System; +using System.Reflection; +using System.IO; + +namespace QuickGraph.CommandLine +{ + internal sealed class EnumArgumentParser : ArgumentParserBase + { + public EnumArgumentParser( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + :base(member,argument,isMultiple) + {} + + public override bool Parse(object instance, string arg) + { + string value = this.ExtractValue(arg); + if (value==null) + return false; + this.AssignValue(instance, Enum.Parse(this.ElementType,value,true)); + return true; + } + + protected override string GetValidValues() + { + StringWriter sw = new StringWriter(); + sw.Write(":["); + bool first = true; + foreach (Object value in Enum.GetValues(this.ElementType)) + { + if (!first) + sw.Write(",{0}",value); + else + { + sw.Write("{0}", value); + first = false; + } + } + sw.Write("]"); + return sw.ToString(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs.meta new file mode 100644 index 0000000..a34fa9a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/EnumArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9317e72c7f7a4399aec2aad9e80eec7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs new file mode 100755 index 0000000..caa1b24 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs @@ -0,0 +1,39 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class FieldMember : IMember + { + private FieldInfo field; + public FieldMember(FieldInfo field) + { + this.field = field; + } + + public string Name + { + get { return this.field.Name; } + } + + public Type DeclaringType + { + get { return this.field.DeclaringType; } + } + + public Type MemberType + { + get { return this.field.FieldType; } + } + + public object GetValue(object instance) + { + return this.field.GetValue(instance); + } + + public void SetValue(object instance, object value) + { + this.field.SetValue(instance, value); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs.meta new file mode 100644 index 0000000..319677f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FieldMember.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2ce5eeaf95f274564b0c6feb3afcd00a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs new file mode 100755 index 0000000..e2ee515 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs @@ -0,0 +1,24 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class FloatArgumentParser : ArgumentParserBase + { + public FloatArgumentParser( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + : base(member, argument, isMultiple) + { } + + public override bool Parse(object instance, string arg) + { + string value = this.ExtractValue(arg); + if (value == null) + return false; + this.AssignValue(instance, float.Parse(value)); + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs.meta new file mode 100644 index 0000000..664ab9d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/FloatArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b6a2f2a3f80ff4e9d928af31e89ba7ce +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs new file mode 100755 index 0000000..c41a2ef --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; + +namespace QuickGraph.CommandLine +{ + internal interface IArgumentParser + { + IMember Member { get;} + ArgumentAttribute Argument { get;} + bool IsMultiple { get;} + + bool Parse(object instance, string arg); + void ShowHelp(TextWriter writer); + void ShowData(object instance, TextWriter writer); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs.meta new file mode 100644 index 0000000..8bcc511 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 392fbf36ef3f643b09fb86a08f56baa3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs new file mode 100755 index 0000000..fc96c62 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.CommandLine +{ + internal interface IMember + { + string Name { get;} + Type DeclaringType { get;} + Type MemberType { get;} + object GetValue(object instance); + void SetValue(object instance, object value); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs.meta new file mode 100644 index 0000000..c2110f7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IMember.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1065426ca804440d9bc6019238d9cb0a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs new file mode 100755 index 0000000..8a20cbf --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs @@ -0,0 +1,24 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class IntArgumentParser : ArgumentParserBase + { + public IntArgumentParser( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + :base(member,argument,isMultiple) + {} + + public override bool Parse(object instance, string arg) + { + string value = this.ExtractValue(arg); + if (value == null) + return false; + this.AssignValue(instance, int.Parse(value)); + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs.meta new file mode 100644 index 0000000..8e605b4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/IntArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 440a5cb6ed71f4526a89add7981ffea7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs new file mode 100755 index 0000000..0642714 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs @@ -0,0 +1,24 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class LongArgumentParser : ArgumentParserBase + { + public LongArgumentParser( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + : base(member, argument, isMultiple) + { } + + public override bool Parse(object instance, string arg) + { + string value = this.ExtractValue(arg); + if (value == null) + return false; + this.AssignValue(instance, long.Parse(value)); + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs.meta new file mode 100644 index 0000000..e65afcd --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/LongArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3ab7f555275b437db245c0280b4f324 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs new file mode 100755 index 0000000..e1f77fb --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs @@ -0,0 +1,40 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class PropertyMember : IMember + { + private PropertyInfo property; + + public PropertyMember(PropertyInfo property) + { + this.property = property; + } + + public string Name + { + get { return this.property.Name; } + } + + public Type DeclaringType + { + get { return this.property.DeclaringType; } + } + + public Type MemberType + { + get { return this.property.PropertyType; } + } + + public object GetValue(object instance) + { + return this.property.GetValue(instance, null); + } + + public void SetValue(object instance, object value) + { + this.property.SetValue(instance, value, null); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs.meta new file mode 100644 index 0000000..4557ec5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/PropertyMember.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 145275698c3cb4a04957adb72233eb5e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs new file mode 100755 index 0000000..cf61820 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs @@ -0,0 +1,25 @@ +using System; +using System.Reflection; + +namespace QuickGraph.CommandLine +{ + internal sealed class StringArgumentParser : ArgumentParserBase + { + public StringArgumentParser( + IMember member, + ArgumentAttribute argument, + bool isMultiple) + :base(member,argument,isMultiple) + {} + + public override bool Parse(object instance, string arg) + { + string value = this.ExtractValue(arg); + if (value == null) + return false; + value = value.Trim('"'); + this.AssignValue(instance, value); + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs.meta new file mode 100644 index 0000000..4eff3c3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CommandLine/StringArgumentParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8351c8205e2444b64a5fe701257f3cbb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs new file mode 100755 index 0000000..9966f61 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs @@ -0,0 +1,365 @@ +using System; +using System.Collections; +using System.CodeDom.Compiler; +using System.IO; +using System.Collections.Specialized; +using System.Text.RegularExpressions; +using Microsoft.CSharp; +using Microsoft.VisualBasic; +using QuickGraph.Unit.Exceptions; + +namespace QuickGraph.Unit +{ + public static class CompilerAssert + { + #region Compilers + private static CodeDomProvider csharp; + private static CodeDomProvider vb; + /// + /// Gets the C# compiler from . + /// + /// + /// C# compiler. + /// + public static CodeDomProvider CSharpProvider + { + get + { + if (csharp==null) + csharp = new CSharpCodeProvider(); + return csharp; + } + } + + /// + /// Gets the VB.NET compiler from . + /// + /// + /// VB.NET compiler. + /// + public static CodeDomProvider VBProvider + { + get + { + if (vb==null) + vb = new VBCodeProvider(); + return vb; + } + } + #endregion + + /// + /// Verifies that compiles using the provided compiler. + /// + /// Compiler instance + /// Source code to compile + public static CompilerResults Compiles(CodeDomProvider provider, string source) + { + Assert.IsNotNull(provider); + Assert.IsNotNull(source); + CompilerParameters ps = new CompilerParameters(); + ps.GenerateInMemory = true; + return Compiles(provider, ps, source); + } + + /// + /// Verifies that compiles using the provided compiler. + /// + /// Compiler instance + /// Source code to compile + public static CompilerResults Compiles(CodeDomProvider provider, Stream source) + { + Assert.IsNotNull(provider); + Assert.IsNotNull(source); + CompilerParameters ps = new CompilerParameters(); + return Compiles(provider, ps, source); + } + + /// + /// Verifies that compiles using the provided compiler. + /// + /// Compiler instance + /// Referenced assemblies + /// Source code to compile + public static CompilerResults Compiles(CodeDomProvider provider, StringCollection references, string source) + { + Assert.IsNotNull(provider); + Assert.IsNotNull(references); + Assert.IsNotNull(source); + CompilerParameters ps = new CompilerParameters(); + foreach (string ra in references) + ps.ReferencedAssemblies.Add(ra); + + return Compiles(provider, ps, source); + } + + /// + /// Verifies that compiles using the provided compiler. + /// + /// + /// instance. + /// Compilation options + /// source to compile + public static CompilerResults Compiles(CodeDomProvider provider, CompilerParameters options, string source) + { + Assert.IsNotNull(provider); + Assert.IsNotNull(options); + Assert.IsNotNull(source); + return Compiles(provider, options, source, false); + } + + /// + /// Verifies that compiles using the provided compiler. + /// + /// + /// instance. + /// Compilation options + /// Source to compile + /// + /// true if assertion should throw if any warning. + /// + public static CompilerResults Compiles(CodeDomProvider provider, CompilerParameters options, string source, bool throwOnWarning) + { + Assert.IsNotNull(provider); + Assert.IsNotNull(options); + CompilerResults results = provider.CompileAssemblyFromSource(options, source); + if (results.Errors.HasErrors) + { + DisplaySource(source); + DisplayErrors(results, Console.Out); + throw new CompilationException(provider, options, results, source); + } + if (throwOnWarning && results.Errors.HasWarnings) + { + DisplaySource(source); + DisplayErrors(results, Console.Out); + throw new CompilationException(provider, options, results, source); + } + return results; + } + + /// + /// Verifies that compiles using the provided compiler. + /// + /// + /// instance. + /// Compilation options + /// Stream containing the source to compile + public static CompilerResults Compiles(CodeDomProvider provider, CompilerParameters options, Stream source) + { + return Compiles(provider, options, source, false); + } + + /// + /// Verifies that compiles using the provided compiler. + /// + /// + /// instance. + /// Compilation options + /// Stream containing the source to compile + /// + /// true if assertion should throw if any warning. + /// + public static CompilerResults Compiles(CodeDomProvider provider, CompilerParameters options, Stream source, bool throwOnWarning) + { + using (StreamReader sr = new StreamReader(source)) + { + return Compiles(provider, options, sr.ReadToEnd(), throwOnWarning); + } + } + + private static void RunResults(CompilerResults results, int expectedExitCode) + { + System.Reflection.MethodInfo main = results.CompiledAssembly.EntryPoint; + Assert.IsNotNull(main, + "Could not find entry point method"); + + int exitCode = (int)main.Invoke(null, new Object[] { new string[0] }); + Assert.AreEqual(expectedExitCode, exitCode); + } + + public static void CompilesAndRun( + CodeDomProvider provider, + CompilerParameters options, + string source, + int expectedExitCode + ) + { + options.GenerateInMemory = true; + options.GenerateExecutable = true; + CompilerResults results = Compiles(provider, options, source); + RunResults(results, expectedExitCode); + } + + + + public static void CompilesAndRun( + CodeDomProvider provider, + CompilerParameters options, + Stream source, + int expectedExitCode + ) + { + options.GenerateInMemory = true; + options.GenerateExecutable = true; + CompilerResults results = Compiles(provider, options, source); + RunResults(results, expectedExitCode); + } + + public static void CompilesAndRun( + CodeDomProvider provider, + string source, + int expectedExitCode + ) + { + CompilerParameters options = new CompilerParameters(); + options.GenerateInMemory = true; + options.GenerateExecutable = true; + + CompilerResults results = Compiles(provider, options, source); + RunResults(results,expectedExitCode); + } + + public static string InsertLineNumbers(string source) + { + Regex regex = new Regex("\n"); + LineCounter counter = new LineCounter(); + return "000 "+regex.Replace(source, new MatchEvaluator(counter.AddLineCount)); + } + + private sealed class LineCounter + { + public int lineCount = 0; + public string AddLineCount(Match m) + { + lineCount++; + return String.Format("{1}{0:000} ", lineCount, m); + } + } + + /// + /// Verifies that does not compile using the provided compiler. + /// + /// + /// instance. + /// Source to compile + public static void NotCompiles( + CodeDomProvider provider, + string source) + { + CompilerParameters options = new CompilerParameters(); + options.GenerateInMemory = false; + NotCompiles(provider, options, source); + } + + /// + /// Verifies that does not compile using the provided compiler. + /// + /// + /// instance. + /// Source to compile + public static void NotCompiles( + CodeDomProvider provider, + Stream source) + { + CompilerParameters options = new CompilerParameters(); + options.GenerateInMemory = false; + NotCompiles(provider, options, source); + } + + /// + /// Verifies that does not compile using the provided compiler. + /// + /// + /// instance. + /// Collection of referenced assemblies + /// Source to compile + public static void NotCompiles( + CodeDomProvider provider, + StringCollection referencedAssemblies, + string source) + { + CompilerParameters options = new CompilerParameters(); + CompilerParameters ps = new CompilerParameters(); + foreach (string ra in referencedAssemblies) + ps.ReferencedAssemblies.Add(ra); + NotCompiles(provider, options, source); + } + + /// + /// Verifies that does not compile using the provided compiler. + /// + /// + /// instance. + /// Compilation options + /// Source to compile + public static void NotCompiles( + CodeDomProvider provider, + CompilerParameters options, + string source) + { + if (provider == null) + throw new ArgumentNullException("provider"); + if (options == null) + throw new ArgumentNullException("options"); + CompilerResults results = provider.CompileAssemblyFromSource(options, source); + if (!results.Errors.HasErrors) + throw new CompilationException(provider, options, results, source); + } + + /// + /// Verifies that does not compile using the provided compiler. + /// + /// + /// instance. + /// Compilation options + /// Source to compile + public static void NotCompiles( + CodeDomProvider provider, + CompilerParameters options, + Stream source) + { + using (StreamReader sr = new StreamReader(source)) + { + NotCompiles(provider, options, sr.ReadToEnd()); + } + } + + public static void DisplaySource(string source) + { + Console.WriteLine(InsertLineNumbers(source)); + } + + public static void DisplayErrors(CompilerResults results, TextWriter writer) + { + Console.WriteLine("Errors"); + foreach (CompilerError error in results.Errors) + { + if (error.IsWarning) + continue; + writer.WriteLine( + "{0} ({1},{2}): {3} {4}", + error.FileName, + error.Line, + error.Column, + error.ErrorNumber, + error.ErrorText); + } + + Console.WriteLine(); + Console.WriteLine("Warnings"); + foreach (CompilerError error in results.Errors) + { + if (!error.IsWarning) + continue; + writer.WriteLine( + "{0} ({1},{2}): {3} {4}", + error.FileName, + error.Line, + error.Column, + error.ErrorNumber, + error.ErrorText); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs.meta new file mode 100644 index 0000000..9733873 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CompilerAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a5f10e41e70b5486faeadcb53451bf59 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core.meta new file mode 100644 index 0000000..c2c2333 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 4613df6d389584e4f9337fdecc1930cc +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs new file mode 100755 index 0000000..9587567 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Core +{ + public sealed class BadFixture : FixtureBase + { + private string name; + private string message; + private Exception exception; + + public BadFixture(string name, Exception exception) + : this(name, exception.Message) + { + this.exception = exception; + } + + public BadFixture(string name, string message) + : base(System.Threading.ApartmentState.Unknown,1, message) + { + this.name = name; + this.message = message; + } + + public override object CreateInstance() + { + return null; + } + + public override string Name + { + get { return this.name; } + } + + public string Message + { + get { return this.message; } + } + + public Exception Exception + { + get { return this.exception; } + } + + public override IEnumerable CreateTestCases() + { + yield return new BadTestCase( + this.Name, + "ErrorLoadingFixture", + this.message, + this.Exception + ); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs.meta new file mode 100644 index 0000000..b81b369 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadFixture.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 096e4cd287f5a4086b249243e91ae1f5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs new file mode 100755 index 0000000..9799ba8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Core +{ + public sealed class BadTestCase : ITestCase + { + private string fixtureName; + private string name; + private string message; + private Exception exception; + private List parameters = new List(); + + public BadTestCase( + string fixtureName, + string name, + string message, + Exception exception + ) + { + this.fixtureName = fixtureName; + this.name = name; + this.message = message; + this.exception = exception; + } + + public string FixtureName + { + get { return this.fixtureName; } + } + public string Name + { + get { return this.name; } + } + public string FullName + { + get { return String.Format("{0}.{1}", this.FixtureName, this.Name); } + } + public IList Parameters + { + get { return this.parameters; } + } + + public void Run(Object fixture) + { + if (this.exception!=null) + throw new Exceptions.FixtureReflectionFailedException( + this.message, + this.exception); + else + throw new Exceptions.FixtureReflectionFailedException( + this.message); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs.meta new file mode 100644 index 0000000..454ff34 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/BadTestCase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 11a92178e0b214e51b8b1d59dc80d08f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs new file mode 100755 index 0000000..4d0351c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.Xml.XPath; + +namespace QuickGraph.Unit.Core +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=true)] + public abstract class DataProviderAttributeBase : Attribute, + IDataProvider + { + public abstract IXPathNavigable GetData(); + public abstract string Name { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs.meta new file mode 100644 index 0000000..92c00d2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataProviderAttributeBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b0579e06b46bf4b1b9e3980a905cb27a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs new file mode 100755 index 0000000..266f771 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs @@ -0,0 +1,21 @@ +using System; +using System.Reflection; +using System.Xml.XPath; +using System.IO; + +namespace QuickGraph.Unit.Core +{ + public sealed class DataTestCase :MethodTestCase + { + public DataTestCase( + string fixtureName, + MethodInfo method, + XPathNavigator node, + string nodeName + ) + : base(fixtureName, method) + { + this.Parameters.Add(new TestCaseParameter(nodeName, node)); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs.meta new file mode 100644 index 0000000..4d79df1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DataTestCase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dd1a243edf64a4f1fa1a61ba11a632ac +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs new file mode 100755 index 0000000..273461a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Core +{ + public abstract class DecoratorTestCaseBase : ITestCase + { + private ITestCase testCase; + public DecoratorTestCaseBase(ITestCase testCase) + { + if (testCase == null) + throw new ArgumentNullException("testCase"); + this.testCase = testCase; + } + + public ITestCase TestCase + { + get { return this.testCase; } + } + + public string FullName + { + get { return String.Format("{0}.{1}", this.FixtureName, this.Name); } + } + + public virtual string Name + { + get { return this.TestCase.Name; } + } + + public string FixtureName + { + get { return this.testCase.FixtureName; } + } + + public IList Parameters + { + get { return this.TestCase.Parameters; } + } + + public abstract void Run(Object fixture); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs.meta new file mode 100644 index 0000000..172437c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DecoratorTestCaseBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a0bdc3867069a4c6a94eb86538c478d8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs new file mode 100755 index 0000000..1e95407 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace QuickGraph.Unit.Core +{ + public class DelegateTestCase : TestCaseBase + { + private Delegate testDelegate; + + public DelegateTestCase(string fixtureName, Delegate testDelegate, params object[] args) + : base(fixtureName) + { + this.testDelegate = testDelegate; + foreach (Object arg in args) + this.Parameters.Add(new TestCaseParameter(arg)); + } + + public Delegate TestDelegate + { + get { return this.testDelegate; } + } + + public override string UndecoratedName + { + get { return this.testDelegate.Method.Name; } + } + + public override void Run(Object fixture) + { + this.testDelegate.DynamicInvoke(TestCaseParameter.GetValues(this.Parameters)); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs.meta new file mode 100644 index 0000000..f3a8565 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/DelegateTestCase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f956b616c48e443e38801c62ef43144c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs new file mode 100755 index 0000000..7a3cf2d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; + +namespace QuickGraph.Unit.Core +{ + public abstract class FixtureBase : IFixture + { + private ApartmentState apartment; + private int timeOut; + private string description = null; + private bool isCurrent = false; + private List testCaseDecorators = new List(); + private List categories = new List(); + private MethodInfo fixtureSetup; + private MethodInfo fixtureTearDown; + private MethodInfo setUp; + private MethodInfo tearDown; + + public FixtureBase(ApartmentState apartment, int timeOut, string description) + { + this.apartment = apartment; + this.timeOut = timeOut; + this.description = description; + } + + public ApartmentState Apartment + { + get { return this.apartment; } + } + + public int TimeOut + { + get { return this.timeOut; } + } + + public string Description + { + get { return this.description; } + set { this.description = value; } + } + + public bool IsCurrent + { + get { return this.isCurrent; } + set { this.isCurrent = value; } + } + + public IList Categories + { + get { return this.categories; } + } + + public IList TestCaseDecorators + { + get { return this.testCaseDecorators; } + } + + public MethodInfo FixtureSetUp + { + get { return this.fixtureSetup; } + set { this.fixtureSetup = value; } + } + public MethodInfo SetUp + { + get { return this.setUp; } + set { this.setUp = value; } + } + public MethodInfo TearDown + { + get { return this.tearDown; } + set { this.tearDown = value; } + } + public MethodInfo FixtureTearDown + { + get { return this.fixtureTearDown; } + set { this.fixtureTearDown = value; } + } + + public abstract string Name {get;} + public abstract Object CreateInstance(); + public abstract IEnumerable CreateTestCases(); + + public override string ToString() + { + return this.Name; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs.meta new file mode 100644 index 0000000..fbd8728 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cabd14386a9bc4ee3b376ad6a513fb59 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs new file mode 100755 index 0000000..8e65f59 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs @@ -0,0 +1,388 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.CodeDom.Compiler; +using QuickGraph.Unit.Exceptions; +using QuickGraph.Unit.Logging; +using System.Threading; + +namespace QuickGraph.Unit.Core +{ + public sealed class FixtureRunner : IDisposable + { + private ITestListener listener; + + private IFixture fixture; + private ICollection testCases; + + private Thread workerThread = null; + + public FixtureRunner( + IFixture fixture, + ICollection testCases, + ITestListener listener) + { + if (fixture == null) + throw new ArgumentNullException("fixture"); + if (testCases == null) + throw new ArgumentNullException("testCases"); + if (listener == null) + throw new ArgumentNullException("listener"); + + this.fixture = fixture; + this.testCases = testCases; + this.listener = listener; + } + + public ITestListener TestListener + { + get { return this.listener; } + } + + public IFixture Fixture + { + get { return this.fixture; } + } + + public ICollection TestCases + { + get { return this.testCases; } + } + + [System.Diagnostics.DebuggerStepThrough] + public void Run() + { + workerThread = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + using (FixtureWorker worker = new FixtureWorker(this)) + { + workerThread = new Thread(new ThreadStart(worker.RunAsync)); + workerThread.SetApartmentState(this.Fixture.Apartment); + workerThread.IsBackground = true; + workerThread.Priority = ThreadPriority.Lowest; + + int timeOut = + (this.Fixture.TimeOut==int.MaxValue) + ? int.MaxValue : 60 * 1000 * this.Fixture.TimeOut; + // if a debugger is attached, no time out + if (System.Diagnostics.Debugger.IsAttached) + timeOut = int.MaxValue; + + workerThread.Start(); + if (!workerThread.Join(timeOut)) + { + // cancel and wait for 10 sec + worker.CancelAsync(); + if (!workerThread.Join(10 * 1000)) + this.AbortWorkerThread(); + + // store result + TestResult result = new TestResult(Fixture.Name, "FixtureTimedOut"); + result.Start(); + result.Fail(new FixtureTimedOutException(this.Fixture.Name)); + this.TestListener.FixtureTearDown(result); + } + else + { + if (worker.UnhandledException != null) + throw new ApplicationException("Exception is runner", worker.UnhandledException); + } + } + } + finally + { + this.AbortWorkerThread(); + } + } + + private void AbortWorkerThread() + { + if (this.workerThread == null) + return; + + workerThread.Abort(); + workerThread = null; + } + + public void Dispose() + { + this.AbortWorkerThread(); + } + + private sealed class FixtureWorker : IDisposable + { + private int isCancelPending = 0; + private Object fixtureInstance; + private FixtureRunner owner; + private Exception unhandledException = null; + + public FixtureWorker(FixtureRunner owner) + { + this.owner = owner; + } + + public bool IsCancelPending + { + get + { + return this.isCancelPending > 0; + } + } + + public void CancelAsync() + { + Interlocked.Increment(ref this.isCancelPending); + } + + public FixtureRunner Owner + { + get { return this.owner; } + } + + public Exception UnhandledException + { + get { return this.unhandledException; } + } + + [System.Diagnostics.DebuggerStepThrough] + public void RunAsync() + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.Owner.TestListener.BeforeFixture(this.Owner.Fixture, this.Owner.TestCases.Count); + + // fixture setup + if (!this.RunTestFixtureSetUp()) + return; + + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + foreach (ITestCase test in this.Owner.TestCases) + { + if (this.IsCancelPending) + return; + if (test == null) + continue; + + this.Owner.TestListener.BeforeTestCase(test); + + // create instance + if (this.CreateFixtureInstance()) + { + if (this.RunSetUp()) + { + this.RunTest(test); + this.RunTearDown(); + } + // disposeinstance + this.DisposeFixtureInstance(); + } + + this.Owner.TestListener.AfterTestCase(test); + } + } + finally + { + this.RunTestFixtureTearDown(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + this.Owner.TestListener.AfterFixture(this.Owner.Fixture); + } + } + catch (Exception ex) + { + this.unhandledException = ex; + } + } + + public void Dispose() + { + this.DisposeFixtureInstance(); + } + + private void DisposeFixtureInstance() + { + if (this.fixtureInstance != null) + { + IDisposable disposable = this.fixtureInstance as IDisposable; + if (disposable != null) + disposable.Dispose(); + this.fixtureInstance = null; + } + } + + private bool CreateFixtureInstance() + { + TestResult result = new TestResult(this.Owner.Fixture.Name, "Create"); + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.fixtureInstance = this.Owner.Fixture.CreateInstance(); + return true; + } + catch (Exception ex) + { + Exception current = ex; + if (current is TargetInvocationException) + current = ex.InnerException; + result.Fail(current); + this.Owner.TestListener.SetUp(result); + return false; + } + } + + [System.Diagnostics.DebuggerStepThrough] + private bool RunTestFixtureSetUp() + { + TestResult result = null; ; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + if (this.Owner.Fixture.FixtureSetUp == null) + return true; + + result = new TestResult(this.Owner.Fixture.Name, this.Owner.Fixture.FixtureSetUp); + result.Start(); + this.Owner.Fixture.FixtureSetUp.Invoke(null, null); + result.Success(); + this.Owner.TestListener.FixtureSetUp(result); + + return true; + } + catch (Exception ex) + { + if (result != null) + { + Exception current = ex; + if (current is TargetInvocationException) + current = ex.InnerException; + result.Fail(current); + this.Owner.TestListener.FixtureSetUp(result); + } + return false; + } + } + + + [System.Diagnostics.DebuggerStepThrough] + private bool RunTestFixtureTearDown() + { + TestResult result = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + if (this.Owner.Fixture.FixtureTearDown == null) + return true; + + result = new TestResult(this.Owner.Fixture.Name, this.Owner.Fixture.FixtureTearDown); + result.Start(); + this.Owner.Fixture.FixtureTearDown.Invoke(null, null); + result.Success(); + return true; + } + catch (Exception ex) + { + if (result != null) + { + Exception current = ex; + if (current is TargetInvocationException) + current = ex.InnerException; + result.Fail(current); + this.Owner.TestListener.FixtureTearDown(result); + } + return false; + } + } + + [System.Diagnostics.DebuggerStepThrough] + private bool RunSetUp() + { + TestResult result = null; + try + { + if (this.Owner.Fixture.SetUp == null) + return true; + + result = new TestResult(this.Owner.Fixture.Name, this.Owner.Fixture.SetUp); + result.Start(); + this.Owner.Fixture.SetUp.Invoke(this.fixtureInstance,null); + result.Success(); + this.Owner.TestListener.SetUp(result); + + return true; + } + catch (Exception ex) + { + if (result != null) + { + Exception current = ex; + if (current is TargetInvocationException) + current = ex.InnerException; + result.Fail(current); + this.Owner.TestListener.SetUp(result); + } + return false; + } + } + + [System.Diagnostics.DebuggerStepThrough] + private void RunTearDown() + { + TestResult result = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + if (this.Owner.Fixture.TearDown == null) + return; + + result = new TestResult(this.Owner.Fixture.Name, this.Owner.Fixture.TearDown); + result.Start(); + this.Owner.Fixture.TearDown.Invoke(this.fixtureInstance,null); + result.Success(); + } + catch (Exception ex) + { + if (result != null) + { + Exception current = ex; + if (current is TargetInvocationException) + current = ex.InnerException; + result.Fail(current); + this.Owner.TestListener.TearDown(result); + } + } + } + + [System.Diagnostics.DebuggerStepThrough] + private void RunTest(ITestCase test) + { + TestResult result = new TestResult(test); + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + result.Start(); + test.Run(this.fixtureInstance); + result.Success(); + } + catch (Exception ex) + { + Exception current = ex; + if (current is TargetInvocationException) + current = current.InnerException; + if (current is IgnoreException) + result.Ignore(); + else if (current is AssumptionFailureException) + result.Success(); + else + result.Fail(current); + } + this.Owner.TestListener.Test(result); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs.meta new file mode 100644 index 0000000..6585b2e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/FixtureRunner.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7262a30eafa86471dbbfce68287202fa +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs new file mode 100755 index 0000000..3fd6e9e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs @@ -0,0 +1,331 @@ +using System; +using System.Reflection; +using System.Reflection.Emit; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Core +{ + public delegate void EmptyInvoker(); + public delegate T CoVariantInvoker(); + public delegate void ContraVariantInvoker(T value); + + public static class LightweightReflection + { + #region CreatePropertySetData + private static object syncPropertySetDataRoot = new object(); + private static Dictionary propertySetDatas = new Dictionary(); + + public static T CreateSetData(PropertyInfo property) + { + return (T)(Object)CreateSetData(property).CreateDelegate(typeof(T)); + } + + public static T CreateSetData(PropertyInfo property, object target) + { + return (T)(Object)CreateSetData(property).CreateDelegate(typeof(T), target); + } + + public static DynamicMethod CreateSetData(PropertyInfo property) + { + if (property == null) + throw new ArgumentNullException("property"); + if (!property.CanWrite) + throw new ArgumentException("property cannot set data"); + + DynamicMethod dynamicMethod; + lock (syncPropertySetDataRoot) + { + if (propertySetDatas.TryGetValue(property, out dynamicMethod)) + return dynamicMethod; + + string name = "Set" + property.MetadataToken.ToString(); + Module module = property.Module; + Type[] parameterTypes = GetParameterTypes(property.GetSetMethod()); + dynamicMethod = new DynamicMethod( + name, + null, + parameterTypes, + module); + GenerateInvokeBody(property.GetSetMethod(), + dynamicMethod.GetILGenerator(), + parameterTypes); + propertySetDatas.Add(property, dynamicMethod); + return dynamicMethod; + } + } + + private static void GeneratePropertySetDataBody( + PropertyInfo property, + ILGenerator gen, + Type[] parameters + ) + { + MethodInfo setMethod = property.GetSetMethod(); + + for (int i = 0; i < parameters.Length; ++i) + gen.Emit(OpCodes.Ldarg, i); + + OpCode callCode; + if (setMethod.IsVirtual) + callCode = OpCodes.Callvirt; + else + callCode = OpCodes.Call; + gen.Emit(callCode, setMethod); + gen.Emit(OpCodes.Ret); + } + #endregion + + #region CreatePropertyGetData + private static object syncPropertyGetDataRoot = new object(); + private static Dictionary propertyGetDatas = new Dictionary(); + + public static T CreateGetData(PropertyInfo property) + { + return (T)(Object)CreateGetData(property).CreateDelegate(typeof(T)); + } + + public static T CreateGetData(PropertyInfo property, object target) + { + return (T)(Object)CreateGetData(property).CreateDelegate(typeof(T), target); + } + + public static DynamicMethod CreateGetData(PropertyInfo property) + { + if (property == null) + throw new ArgumentNullException("property"); + if (!property.CanRead) + throw new ArgumentException("property cannot read"); + + DynamicMethod dynamicMethod; + lock (syncPropertyGetDataRoot) + { + if (propertyGetDatas.TryGetValue(property, out dynamicMethod)) + return dynamicMethod; + + string name = "Get" + property.MetadataToken.ToString(); + Module module = property.DeclaringType.Module; + Type returnType = property.PropertyType; + Type[] parameterTypes = GetParameterTypes(property.GetGetMethod()); + + dynamicMethod = new DynamicMethod( + name, + returnType, + parameterTypes, + module); + GenerateInvokeBody(property.GetGetMethod(), + dynamicMethod.GetILGenerator(), + parameterTypes); + propertyGetDatas.Add(property, dynamicMethod); + return dynamicMethod; + } + + } + #endregion + + #region CreateFieldSetData + private static object syncFieldSetDataRoot = new object(); + private static Dictionary fieldSetDatas = new Dictionary(); + + public static T CreateSetData(FieldInfo field) + { + return (T)(Object)CreateSetData(field).CreateDelegate(typeof(T)); + } + + public static T CreateSetData(FieldInfo field, object target) + { + return (T)(Object)CreateSetData(field).CreateDelegate(typeof(T), target); + } + + public static DynamicMethod CreateSetData(FieldInfo field) + { + if (field == null) + throw new ArgumentNullException("field"); + DynamicMethod dynamicMethod; + lock (syncFieldSetDataRoot) + { + if (fieldSetDatas.TryGetValue(field, out dynamicMethod)) + return dynamicMethod; + + string name = "Set" + field.MetadataToken.ToString(); + Module module = field.DeclaringType.Module; + Type[] parameterTypes = + (field.IsStatic) ? new Type[] { field.FieldType } + : new Type[] { field.DeclaringType, field.FieldType }; + + dynamicMethod = new DynamicMethod( + name, + null, + parameterTypes, + module); + GenerateFieldSetDataBody( + field, + dynamicMethod.GetILGenerator()); + fieldSetDatas.Add(field, dynamicMethod); + return dynamicMethod; + } + } + + private static void GenerateFieldSetDataBody( + FieldInfo field, + ILGenerator gen + ) + { + gen.Emit(OpCodes.Ldarg_0); + if (field.IsStatic) + { + gen.Emit(OpCodes.Stsfld, field); + } + else + { + gen.Emit(OpCodes.Ldarg_1); + gen.Emit(OpCodes.Stfld, field); + } + gen.Emit(OpCodes.Ret); + } + #endregion + + #region CreateFieldGetData + private static object syncFieldGetDataRoot = new object(); + private static Dictionary fieldGetDatas = new Dictionary(); + + public static T CreateGetData(FieldInfo field) + { + return (T)(Object)CreateGetData(field).CreateDelegate(typeof(T)); + } + + public static T CreateGetData(FieldInfo field, object target) + { + return (T)(Object)CreateGetData(field).CreateDelegate(typeof(T), target); + } + + public static DynamicMethod CreateGetData(FieldInfo field) + { + if (field == null) + throw new ArgumentNullException("field"); + DynamicMethod dynamicMethod; + lock (syncFieldGetDataRoot) + { + if (fieldGetDatas.TryGetValue(field, out dynamicMethod)) + return dynamicMethod; + + string name = "Get" + field.MetadataToken.ToString(); + Module module = field.DeclaringType.Module; + Type returnType = field.FieldType; + Type[] parameterTypes = (field.IsStatic) ? null : + new Type[] { field.DeclaringType }; + + dynamicMethod = new DynamicMethod( + name, + returnType, + parameterTypes, + module); + GenerateFieldGetDataBody( + field, + dynamicMethod.GetILGenerator()); + fieldGetDatas.Add(field, dynamicMethod); + return dynamicMethod; + } + + } + + private static void GenerateFieldGetDataBody( + FieldInfo field, + ILGenerator gen + ) + { + if (!field.IsStatic) + { + gen.Emit(OpCodes.Ldarg_0); + gen.Emit(OpCodes.Ldfld, field); + } + else + { + gen.Emit(OpCodes.Ldsfld, field); + } + gen.Emit(OpCodes.Ret); + } + + #endregion + + #region CreateInvoke + private static object syncMethodRoot = new object(); + private static Dictionary methods = new Dictionary(); + + public static T CreateInvoke(MethodInfo method) + { + return (T)(object)CreateInvoke(method).CreateDelegate(typeof(T)); + } + + public static T CreateInvoke(MethodInfo method, object target) + { + return (T)(object)CreateInvoke(method).CreateDelegate(typeof(T), target); + } + + public static DynamicMethod CreateInvoke(MethodInfo method) + { + if (method == null) + throw new ArgumentNullException("method"); + DynamicMethod dynamicMethod; + lock (syncMethodRoot) + { + if (methods.TryGetValue(method, out dynamicMethod)) + return dynamicMethod; + string name = method.Name+method.MetadataToken.ToString(); + Module module = method.DeclaringType.Module; + Type returnType = method.ReturnType; + Type[] parameterTypes = GetParameterTypes(method); + + dynamicMethod = new DynamicMethod( + name, + returnType, + parameterTypes, + module); + GenerateInvokeBody(method, dynamicMethod.GetILGenerator(), parameterTypes); + methods.Add(method, dynamicMethod); + return dynamicMethod; + } + } + + private static void GenerateInvokeBody( + MethodInfo method, + ILGenerator gen, + Type[] parameterTypes + ) + { + for (int i = 0; i < parameterTypes.Length; ++i) + gen.Emit(OpCodes.Ldarg, i); + + OpCode callCode; + if (method.IsVirtual) + callCode = OpCodes.Callvirt; + else + callCode = OpCodes.Call; + + gen.EmitCall(callCode, method, null); + + gen.Emit(OpCodes.Ret); + } + + private static Type[] GetParameterTypes(MethodInfo method) + { + ParameterInfo[] parameters = method.GetParameters(); + Type[] types; + if (method.IsStatic) + { + types = new Type[parameters.Length]; + for (int i = 0; i < parameters.Length; ++i) + types[i] = parameters[i].ParameterType; + } + else + { + types = new Type[parameters.Length + 1]; + types[0] = method.DeclaringType; + for (int i = 0; i < parameters.Length; ++i) + types[i + 1] = parameters[i].ParameterType; + } + + return types; + } + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs.meta new file mode 100644 index 0000000..dec40c1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/LightweightReflection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1fa381a0e40fe4036af78f48bc1b6cf9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs new file mode 100755 index 0000000..23592f4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; + +namespace QuickGraph.Unit.Core +{ + public class MethodTestCase : TestCaseBase + { + private MethodInfo method; + + public MethodTestCase(string fixtureName, MethodInfo method) + :base(fixtureName) + { + if (method == null) + throw new ArgumentNullException("method"); + this.method = method; + } + + public MethodInfo Method + { + get { return this.method; } + } + + public override string UndecoratedName + { + get { return this.Method.Name; } + } + + [System.Diagnostics.DebuggerStepThrough] + public override void Run(Object fixture) + { + if (this.Parameters.Count == 0) + this.method.Invoke(fixture, null); + else + { + Object[] array = TestCaseParameter.GetValues(this.Parameters); + this.method.Invoke(fixture, array); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs.meta new file mode 100644 index 0000000..7267049 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/MethodTestCase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ca008e6445eeb404d832e4f2b42807f9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs new file mode 100755 index 0000000..b70a86c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs @@ -0,0 +1,152 @@ +using System; +using System.Reflection; +using System.Collections.Generic; +using System.ComponentModel; + +namespace QuickGraph.Unit.Core +{ + public static class ReflectionHelper + { + public static Object[] ToArray(ICollection parameters) + { + Object[] array = new object[parameters.Count]; + parameters.CopyTo(array, 0); + return array; + } + + public static T GetAttribute(ICustomAttributeProvider t) + where T : Attribute + { + if (t == null) + throw new ArgumentNullException("t"); + + // Gets the attributes for the property. + Object[] attributes = + t.GetCustomAttributes(typeof(T), true); + + if (attributes.Length == 0) + return null; + if (attributes.Length==1) + return (T)attributes[0]; + + throw new ArgumentException("Attribute type must be AllowMultiple = false",typeof(T).FullName); + } + + public static string GetCategory(ICustomAttributeProvider t) + { + if (t == null) + throw new ArgumentNullException("t"); + + System.ComponentModel.CategoryAttribute cat = ReflectionHelper.GetAttribute < System.ComponentModel.CategoryAttribute>(t); + if (cat == null) + return ""; + return cat.Category; + } + + public static MethodInfo GetMethod(Type t, string methodName,params Object[] parameters) + { + if (t == null) + throw new ArgumentNullException("t"); + if (methodName == null) + throw new ArgumentNullException("methodName"); + if (methodName.Length == 0) + throw new ArgumentException("Length is zero", "methodName"); + + Type[] types = new Type[parameters.Length]; + for (int i = 0; i < parameters.Length; ++i) + { + if (parameters[i] == null) + throw new ArgumentNullException("paramer[" + i.ToString() + "]"); + types[i] = parameters[i].GetType(); + } + + return t.GetMethod(methodName, + BindingFlags.Instance | + BindingFlags.Public | + BindingFlags.NonPublic, + null, + types, + null + ); + } + + public static MethodInfo GetMethod(Type t, Type customAttributeType, BindingFlags flags) + { + MethodInfo[] methods = GetMethods(t, customAttributeType, flags); + if (methods.Length == 0) + return null; + if (methods.Length > 1) + throw new ArgumentException("More that one method found"); + return methods[0]; + } + + public static MethodInfo[] GetMethods(Type t, Type customAttributeType) + { + return GetMethods(t, customAttributeType, BindingFlags.Public | BindingFlags.Instance); + } + + public static MethodInfo[] GetMethods(Type t, Type customAttributeType, BindingFlags flags) + { + if (t == null) + throw new ArgumentNullException("t"); + if (customAttributeType == null) + throw new ArgumentNullException("customAttributeType"); + + List list = new List(); + foreach (MethodInfo mi in t.GetMethods(flags)) + { + if (mi.GetCustomAttributes(customAttributeType, true).Length != 0) + list.Add(mi); + } + + MethodInfo[] methods = new MethodInfo[list.Count]; + list.CopyTo(methods); + return methods; + } + + + public static void VerifySignature(MethodInfo method, params Type[] argumentAssignableTypes) + { + if (method == null) + throw new ArgumentNullException("method"); + + ParameterInfo[] parameters = method.GetParameters(); + Assert.AreEqual( + argumentAssignableTypes.Length, + parameters.Length, + "Method {0} has not the right number of arguments ({1})", + method.Name, argumentAssignableTypes.Length); + + for (int i = 0; i < parameters.Length; ++i) + { + Assert.IsTrue(argumentAssignableTypes[i].IsAssignableFrom(parameters[i].ParameterType), + "Argument {0} is not assignable from {1}", + argumentAssignableTypes[i], + parameters[i] + ); + } + } + + public static void VerifySignature(MethodInfo method, params Object[] arguments) + { + if (method == null) + throw new ArgumentNullException("method"); + + if (arguments == null) + { + VerifySignature(method, new Type[]{}); + return; + } + Type[] types = new Type[arguments.Length]; + for (int i = 0; i < arguments.Length; ++i) + { + if (arguments[i] == null) + types[i] = typeof(object); + else + types[i] = arguments[i].GetType(); + } + + VerifySignature(method, types); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs.meta new file mode 100644 index 0000000..6220c10 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReflectionHelper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 137bfd0a06e204d6d930829f905e3adf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs new file mode 100755 index 0000000..9f6d901 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs @@ -0,0 +1,9 @@ +namespace QuickGraph.Unit.Core +{ + public enum ReportGenerationScenario + { + None, + OnFailure, + Always + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs.meta new file mode 100644 index 0000000..e3dd907 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/ReportGenerationScenario.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d9f3fb2357f734efbbf5d11acc94a871 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs new file mode 100755 index 0000000..2bf0fcc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs @@ -0,0 +1,103 @@ +using System; +using System.Diagnostics; +using QuickGraph.Unit.Monitoring; + +namespace QuickGraph.Unit.Core +{ + [Serializable] + public class Result + { + private TestState state = TestState.NotRun; + private string name; + private Exception exception = null; + private TestMonitor monitor; + + public Result(string name) + { + if (name == null) + throw new ArgumentNullException("name"); + this.name = name; + this.monitor = new TestMonitor(); + } + + public TestState State + { + get { return this.state; } + } + + public string Name + { + get { return this.name; } + } + + public virtual string FullName + { + get { return this.Name; } + } + + public string Out + { + get { return this.monitor.Console.Out; } + } + public string Error + { + get { return this.monitor.Console.Error; } + } + public double Duration + { + get { return this.monitor.Timer.Duration; } + } + public Exception Exception + { + get { return this.exception; } + } + public DateTime StartTime + { + get { return this.Monitor.Timer.StartTime; } + } + public DateTime StopTime + { + get { return this.Monitor.Timer.EndTime; } + } + + public TestMonitor Monitor + { + get { return this.monitor; } + } + + public void Start() + { + this.Monitor.Start(); + } + + private void Stop() + { + this.Monitor.Stop(); + + } + + [DebuggerStepThrough] + public void Fail(Exception exception) + { + if (exception == null) + throw new ArgumentNullException("exception"); + this.Stop(); + this.state = TestState.Failure; + this.exception = exception; + } + + [DebuggerStepThrough] + public void Success() + { + this.Stop(); + this.state = TestState.Success; + } + + [DebuggerStepThrough] + public void Ignore() + { + this.Stop(); + this.state = TestState.Ignore; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs.meta new file mode 100644 index 0000000..86e2dc3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/Result.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0686047603e1d4c3698820629f8c451e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs new file mode 100755 index 0000000..fcdae27 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs @@ -0,0 +1,27 @@ +using System; + +namespace QuickGraph.Unit.Core +{ + public class SynchronizedTestCase : DecoratorTestCaseBase + { + private TestSynchronizer synchronizer; + public SynchronizedTestCase(ITestCase testCase, TestSynchronizer synchronizer) + : base(testCase) + { + this.synchronizer = synchronizer; + } + + public TestSynchronizer Synchronizer + { + get { return this.synchronizer; } + } + + public override void Run(object fixture) + { + // wait for barrier opening + this.Synchronizer.Synchronize(); + // run test + this.TestCase.Run(fixture); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs.meta new file mode 100644 index 0000000..de7201f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/SynchronizedTestCase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2b0c8e266dcfc4741b663a125309d175 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs new file mode 100755 index 0000000..4cf75ec --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit.Filters; + +namespace QuickGraph.Unit.Core +{ + public sealed class TestAssembly + { + private Assembly assembly; + private MethodInfo assemblySetUp; + private MethodInfo assemblyTearDown; + private Dictionary> fixtureTestCases = new Dictionary>(); + + public TestAssembly( + Assembly assembly + ) + { + this.assembly = assembly; + } + + public Assembly Assembly + { + get { return this.assembly; } + } + + public MethodInfo AssemblySetUp + { + get { return this.assemblySetUp; } + set { this.assemblySetUp = value; } + } + + public MethodInfo AssemblyTearDown + { + get { return this.assemblyTearDown; } + set { this.assemblyTearDown = value; } + } + + public ICollection Fixtures + { + get { return this.fixtureTestCases.Keys; } + } + + public ICollection GetTestCasesFromFixture(IFixture fixture) + { + return this.fixtureTestCases[fixture]; + } + + public void AddFixture(IFixture fixture, ICollection testCases) + { + if (fixture == null) + throw new ArgumentNullException("fixture"); + if (testCases == null) + throw new ArgumentNullException("testCases"); + this.fixtureTestCases.Add(fixture, testCases); + } + + public int GetTestCount() + { + int count = 0; + foreach (ICollection tests in this.fixtureTestCases.Values) + count += tests.Count; + return count; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs.meta new file mode 100644 index 0000000..4666209 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAssembly.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 429ecc37e75a440a09f37ae6245607ff +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs new file mode 100755 index 0000000..2afdc26 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace QuickGraph.Unit.Core +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public abstract class TestAttributeBase : Attribute, ITestCaseFactory + { + public abstract IEnumerable CreateTests( + IFixture fixture, + MethodInfo method + ); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs.meta new file mode 100644 index 0000000..e6c0044 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestAttributeBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 046214bc686af44d2934c2c60a147755 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs new file mode 100755 index 0000000..3756477 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit.Filters; + +namespace QuickGraph.Unit.Core +{ + public sealed class TestBatch + { + private List testAssemblies = new List(); + + public TestBatch() + {} + + public ICollection TestAssemblies + { + get { return this.testAssemblies; } + } + + public TestAssembly MainTestAssembly + { + get + { + if (this.TestAssemblies.Count > 0) + return this.testAssemblies[0]; + else + return null; + } + } + + public int GetFixtureCount() + { + int count = 0; + foreach (TestAssembly testAssembly in this.TestAssemblies) + count += testAssembly.Fixtures.Count; + return count; + } + + public int GetTestCount() + { + int count = 0; + foreach (TestAssembly testAssembly in this.TestAssemblies) + count+=testAssembly.GetTestCount(); + return count; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs.meta new file mode 100644 index 0000000..8d373de --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatch.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: de2ea3038e59a4bc1a7bbac35739881c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs new file mode 100755 index 0000000..9fbdc1c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.CodeDom.Compiler; +using QuickGraph.Unit.Exceptions; +using QuickGraph.Unit.Filters; +using System.ComponentModel; + +namespace QuickGraph.Unit.Core +{ + public sealed class TestBatchFactory + { + private List testAssemblies = new List(); + private TestBatch batch; + private IFixtureFilter fixtureFilter = new AnyFixtureFilter(); + private ITestCaseFilter testCaseFilter = new AnyTestCaseFilter(); + + public TestBatch Batch + { + get { return this.batch; } + } + + public IList TestAssemblies + { + get { return this.testAssemblies; } + } + + public string MainAssembly + { + get + { + if (this.testAssemblies.Count == 0) + return "NoAssemblies"; + else + return this.testAssemblies[0].GetName().Name; + } + } + + public IFixtureFilter FixtureFilter + { + get { return this.fixtureFilter; } + set { this.fixtureFilter = value; } + } + + public ITestCaseFilter TestCaseFilter + { + get { return this.testCaseFilter; } + set { this.testCaseFilter = value; } + } + + public TestBatch Create() + { + this.batch = new TestBatch(); + foreach (Assembly assembly in this.TestAssemblies) + { + TestAssembly testAssembly = CreateTestAssembly(assembly); + this.batch.TestAssemblies.Add(testAssembly); + } + return this.batch; + } + + public TestAssembly CreateTestAssembly(Assembly assembly) + { + if (assembly == null) + throw new ArgumentNullException("assembly"); + + TestAssembly testAssembly = new TestAssembly(assembly); + this.ReflectAssemblySetUpAndTearDown(testAssembly); + + foreach (Type type in assembly.GetExportedTypes()) + { + if (type.IsAbstract || type.IsInterface) + continue; + foreach (IFixture fixture in this.ReflectFixtures(type)) + AddFixture(testAssembly, fixture); + } + + return testAssembly; + } + + private void AddFixture(TestAssembly testAssembly, IFixture fixture) + { + List tests = new List(); + + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + foreach (ITestCase test in fixture.CreateTestCases()) + { + if (test == null) + continue; + if (!testCaseFilter.Filter(fixture,test)) + continue; + ITestCase decoratedTest = DecorateTest(fixture, test); + tests.Add(decoratedTest); + } + testAssembly.AddFixture(fixture, tests); + } + catch (Exception ex) + { + BadFixture badFixture = new BadFixture(fixture.Name, ex); + tests.Clear(); + testAssembly.AddFixture(badFixture, tests); + } + } + + private static ITestCase DecorateTest(IFixture fixture, ITestCase test) + { + ITestCase current = test; + foreach (ITestCaseDecorator decorator in fixture.TestCaseDecorators) + current = decorator.Decorate(current); + return current; + } + + private IEnumerable ReflectFixtures(Type fixtureType) + { + foreach(TestFixtureAttributeBase fixtureAttribute in fixtureType.GetCustomAttributes(typeof(TestFixtureAttributeBase),true)) + { + foreach (IFixture fixture in fixtureAttribute.CreateFixtures(fixtureType)) + { + if (fixture == null) + continue; + if (!this.FixtureFilter.Filter(fixture)) + continue; + + BadFixture badFixture = VerifyFixture(fixtureType); + if (badFixture != null) + { + yield return badFixture; + continue; + } + + ReflectSetUpAndTearDown(fixtureType, fixture); + ReflectDecorators(fixtureType, fixture); + ReflectCategories(fixtureType, fixture); + + yield return fixture; + } + } + } + + private static BadFixture VerifyFixture(Type fixtureType) + { + foreach (MethodInfo method in fixtureType.GetMethods(BindingFlags.Instance | BindingFlags.Public)) + { + MethodInfo ms = FilterMethod(method, typeof(TestFixtureSetUpAttribute)); + if (ms != null) + return new BadFixture(fixtureType.FullName, "TestFixtureSetupAttribute must tag static methods"); + MethodInfo mt = FilterMethod(method, typeof(TestFixtureTearDownAttribute)); + if (mt != null) + return new BadFixture(fixtureType.FullName, "TestFixtureTearDownAttribute must tag static methods"); + } + return null; + } + + private void ReflectAssemblySetUpAndTearDown(TestAssembly testAssembly) + { + AssemblySetUpAndTearDownAttribute assemblySetUpAndTearDown = + ReflectionHelper.GetAttribute(testAssembly.Assembly); + if (assemblySetUpAndTearDown != null) + { + testAssembly.AssemblySetUp = ReflectionHelper.GetMethod( + assemblySetUpAndTearDown.TargetType, + typeof(AssemblySetUpAttribute), + BindingFlags.Static | BindingFlags.Public + ); + testAssembly.AssemblyTearDown = ReflectionHelper.GetMethod( + assemblySetUpAndTearDown.TargetType, + typeof(AssemblyTearDownAttribute), + BindingFlags.Static | BindingFlags.Public + ); + } + + } + + private void ReflectDecorators(Type fixtureType, IFixture fixture) + { + foreach (TestDecoratorAttributeBase attribute in fixtureType.GetCustomAttributes(typeof(TestDecoratorAttributeBase), true)) + fixture.TestCaseDecorators.Add(attribute); + } + + private void ReflectCategories(Type fixtureType, IFixture fixture) + { + CategoryAttribute category = ReflectionHelper.GetAttribute(fixtureType); + if (category != null) + { + foreach (string cat in category.Category.Split('.')) + fixture.Categories.Add(cat); + } + } + + private static void ReflectSetUpAndTearDown(Type fixtureType, IFixture fixture) + { + foreach (MethodInfo method in fixtureType.GetMethods(BindingFlags.Public | BindingFlags.Static)) + { + if (fixture.FixtureSetUp == null) + { + fixture.FixtureSetUp = FilterMethod(method, typeof(TestFixtureSetUpAttribute)); + if (fixture.FixtureSetUp != null) + continue; + } + if (fixture.FixtureTearDown == null) + { + fixture.FixtureTearDown = FilterMethod(method, typeof(TestFixtureTearDownAttribute)); + if (fixture.FixtureTearDown != null) + continue; + } + } + + // getting setup and teardown + foreach (MethodInfo method in fixtureType.GetMethods(BindingFlags.Instance | BindingFlags.Public)) + { + if (fixture.SetUp == null) + { + fixture.SetUp = FilterMethod(method, typeof(SetUpAttribute)); + if (fixture.SetUp != null) + continue; + } + if (fixture.TearDown == null) + { + fixture.TearDown = FilterMethod(method, typeof(TearDownAttribute)); + if (fixture.TearDown != null) + continue; + } + } + } + + private static MethodInfo FilterMethod(MethodInfo method, Type attributeType) + { + Object[] attributes = method.GetCustomAttributes(attributeType, true); + if (attributes.Length == 0) + return null; + + return method; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs.meta new file mode 100644 index 0000000..d4d436a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestBatchFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 66493cf232b8743dd9b1fdd2541a8bb0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs new file mode 100755 index 0000000..52b3ae8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; + +namespace QuickGraph.Unit.Core +{ + public abstract class TestCaseBase : ITestCase + { + private string fixtureName; + private List parameters = new List(); + + public TestCaseBase(string fixtureName) + { + if (fixtureName == null) + throw new ArgumentNullException("fixtureName"); + this.fixtureName = fixtureName; + } + + public string FixtureName + { + get { return this.fixtureName; } + } + + public virtual string Name + { + get + { + if (this.Parameters.Count == 0) + { + return this.UndecoratedName; + } + else + { + using (StringWriter writer = new StringWriter()) + { + writer.Write(this.UndecoratedName); + writer.Write('('); + bool first = true; + foreach (TestCaseParameter parameter in this.Parameters) + { + if (first) + first = false; + else + writer.Write(", "); + writer.Write(parameter.Name); + } + writer.Write(')'); + return writer.ToString(); + } + } + } + } + + public abstract string UndecoratedName + { + get; + } + + public virtual string FullName + { + get { return String.Format("{0}.{1}", this.FixtureName, this.Name); } + } + + public IList Parameters + { + get { return this.parameters; } + } + + public abstract void Run(Object fixture); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs.meta new file mode 100644 index 0000000..8b68de4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c60dc61ee2445429096787076f45b071 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs new file mode 100755 index 0000000..c2a9c3f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Reflection; + +namespace QuickGraph.Unit.Core +{ + [Serializable] + public class TestCaseWorker + { + private ITestCase testCase; + private int index; + private Exception throwedException = null; + + public TestCaseWorker(ITestCase testCase, int index) + { + if (testCase == null) + throw new ArgumentNullException("testCase"); + this.testCase = testCase; + this.index = index; + } + + public ITestCase TestCase + { + get { return this.testCase; } + } + + public int Index + { + get { return this.index;} + } + + public Exception ThrowedException + { + get { return this.throwedException; } + } + + public string Name + { + get { return String.Format("{0}{1}", this.TestCase.Name, this.Index);} + } + + protected void Log(string format, params object[] args) + { + string message = String.Format(format, args); + Console.WriteLine("{0}: {1}", this.Name, message); + } + + public void Start(object fixture) + { + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.RunTestCase(fixture); + } + catch (Exception ex) + { + Exception current = ex; + if (current is TargetInvocationException) + current = current.InnerException; + this.throwedException = current; + Log("Exception {0}, {1}", current.GetType().Name, current.Message); + } + finally + { + CleanTestCase(fixture); + } + } + + protected virtual void RunTestCase(object fixture) + { + this.TestCase.Run(fixture); + } + + protected virtual void CleanTestCase(object fixture) + { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs.meta new file mode 100644 index 0000000..f004b39 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorker.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55e1fca8cce7d43968c2fc17c0aea14e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs new file mode 100755 index 0000000..9e440a5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +namespace QuickGraph.Unit.Core +{ + public sealed class TestCaseWorkerCollection : IEnumerable + { + private List workerPairs = new List(); + + private class WorkerPair + { + public TestCaseWorker Worker; + public Thread WorkerThread; + public void SetWorkerThread(Thread thread) + { + this.WorkerThread = thread; + } + } + + public void Add(TestCaseWorker worker) + { + WorkerPair pair = new WorkerPair(); + pair.Worker = worker; + this.workerPairs.Add(pair); + } + + public void StartAll(object fixture) + { + // creating threads + foreach (WorkerPair pair in this.workerPairs) + { + if (pair.WorkerThread != null) + throw new InvalidOperationException("Thread were not terminated before starting"); + pair.SetWorkerThread(new Thread(new ParameterizedThreadStart(pair.Worker.Start))); + pair.WorkerThread.Name = pair.Worker.Name; + } + + // starting threads + foreach (WorkerPair pair in this.workerPairs) + { + pair.WorkerThread.Start(fixture); + } + } + + public void WaitAll() + { + while (IsAnyAlive()) + { + Thread.Sleep(1000); + } + } + + public bool IsAnyAlive() + { + bool isAlive = false; + foreach (WorkerPair pair in this.workerPairs) + { + if (pair.WorkerThread != null) + { + if (pair.WorkerThread.IsAlive) + isAlive = true; + else + pair.SetWorkerThread(null); + } + } + + return isAlive; + } + + public bool ContainsAll(ICollection threadNames) + { + // let's make sure not worker died + foreach (WorkerPair pair in this.workerPairs) + { + // did the thread fail ? + if (pair.Worker.ThrowedException!=null) + return true; + } + + foreach (WorkerPair pair in this.workerPairs) + { + if (!threadNames.Contains(pair.WorkerThread.Name)) + return false; + } + + return true; + } + + public void CloseAll() + { + foreach (WorkerPair pair in this.workerPairs) + { + if (pair.WorkerThread != null) + { + if (pair.WorkerThread.IsAlive) + pair.WorkerThread.Abort(); + pair.SetWorkerThread(null); + } + } + } + + public void Verify() + { + int exceptionCount = 0; + foreach (TestCaseWorker worker in this) + { + if (worker.ThrowedException != null) + { + exceptionCount++; + Console.WriteLine("Error in worker {0}",worker.Name); + Console.WriteLine(worker.ThrowedException); + } + } + + if (exceptionCount > 0) + Assert.Fail("There were {0} exceptions during the run.", exceptionCount); + } + + public IEnumerator GetEnumerator() + { + foreach (WorkerPair pair in this.workerPairs) + yield return pair.Worker; + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs.meta new file mode 100644 index 0000000..2ed7326 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCaseWorkerCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dba35fe63c2d146a7b7f45a276b24629 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs new file mode 100755 index 0000000..878db5a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs @@ -0,0 +1,116 @@ +using System; + +namespace QuickGraph.Unit.Core +{ + [Serializable] + public sealed class TestCounter + { + private int totalCount=0; + private int successCount; + private int failureCount; + private int ignoreCount; + + public TestCounter(int testCount) + { + this.totalCount = testCount; + } + + public int TotalCount + { + get { return this.totalCount; } + } + + public int RunCount + { + get { return this.successCount + this.failureCount + this.ignoreCount; } + } + + public int SuccessCount + { + get { return this.successCount; } + set { this.successCount = value; } + } + public int FailureCount + { + get { return this.failureCount; } + set { this.failureCount = value; } + } + public int IgnoreCount + { + get { return this.ignoreCount; } + set { this.ignoreCount = value; } + } + public bool HasFailures + { + get { return this.FailureCount>0; } + } + public bool Succeeded + { + get { return this.SuccessCount == this.TotalCount; } + } + + public void Success() + { + this.successCount++; + } + public void Failure() + { + this.failureCount++; + } + public void Ignore() + { + this.ignoreCount++; + } + public double PercentRun + { + get + { + if (this.TotalCount == 0) + return 0; + return (double)this.RunCount / this.TotalCount * 100; + } + } + + public double PercentSuccess + { + get + { + if (this.TotalCount == 0) + return 0; + return (double)this.SuccessCount / this.TotalCount * 100; + } + } + + + public void RollbackResults(TestCounter counter) + { + this.failureCount -= counter.FailureCount; + this.successCount -= counter.SuccessCount; + this.ignoreCount -= counter.IgnoreCount; + } + + public static TestCounter Add(TestCounter a, TestCounter b) + { + TestCounter c = new TestCounter(a.totalCount + b.totalCount); + c.successCount = a.successCount + b.successCount; + c.failureCount = a.failureCount + b.failureCount; + c.ignoreCount = a.ignoreCount + b.ignoreCount; + return c; + } + + public static TestCounter operator +(TestCounter a, TestCounter b) + { + return Add(a, b); + } + + public override string ToString() + { + return String.Format("{0:0.00}% ({1},+{2},-{3},~{4})", + this.PercentRun, + this.RunCount, + this.SuccessCount, + this.FailureCount, + this.IgnoreCount); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs.meta new file mode 100644 index 0000000..015d562 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestCounter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec982c25ad1254287b7209a8c6338ced +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs new file mode 100755 index 0000000..d5ed12b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs @@ -0,0 +1,21 @@ +using System; +using System.Reflection; + +namespace QuickGraph.Unit.Core +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public abstract class TestDecoratorAttributeBase : Attribute, ITestCaseDecorator + { + public abstract ITestCase Decorate(ITestCase testCase); + + public static ITestCase DecorateTest(ITestCase testCase, MethodInfo method) + { + ITestCase test = testCase; + foreach (TestDecoratorAttributeBase attribute in method.GetCustomAttributes(typeof(TestDecoratorAttributeBase), true)) + { + test = attribute.Decorate(test); + } + return test; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs.meta new file mode 100644 index 0000000..1722b6e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestDecoratorAttributeBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b8f34889cdbb44182a8599388896a4f2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs new file mode 100755 index 0000000..ba809b2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +namespace QuickGraph.Unit.Core +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public abstract class TestFixtureAttributeBase : + Attribute, + IFixtureFactory + { + private ApartmentState apartment = ApartmentState.Unknown; + private int timeOut = 2; + private string description; + + public ApartmentState Apartment + { + get { return this.apartment; } + set { this.apartment = value; } + } + + public int TimeOut + { + get { return this.timeOut; } + set { this.timeOut = value; } + } + + public string Description + { + get { return this.description; } + set { this.description = value; } + } + + public abstract IEnumerable CreateFixtures(Type type); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs.meta new file mode 100644 index 0000000..3601a18 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestFixtureAttributeBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2b36e153fa339489dbbec6a757c97cd3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs new file mode 100755 index 0000000..0e177f0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs @@ -0,0 +1,38 @@ +using System; +using System.Reflection; + +namespace QuickGraph.Unit.Core +{ + [Serializable] + public class TestResult : Result + { + private string fixtureName; + + public TestResult(string fixtureName, MethodInfo method) + :this(fixtureName,method.Name) + {} + + public TestResult(string fixtureName, string name) + :base(name) + { + if (fixtureName == null) + throw new ArgumentNullException("fixtureName"); + this.fixtureName = fixtureName; + } + + public TestResult(ITestCase testCase) + : this(testCase.FixtureName, testCase.Name) + { + } + + public string FixtureName + { + get { return this.fixtureName; } + } + + public override string FullName + { + get { return String.Format("{0}.{1}", this.FixtureName, this.Name); } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs.meta new file mode 100644 index 0000000..61dcdd3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResult.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0c713b188d203448e8a5353f6611c745 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs new file mode 100755 index 0000000..695a977 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Core +{ + [Serializable] + public sealed class TestResultEventArgs : EventArgs + { + private TestResult result; + public TestResultEventArgs(TestResult result) + { + if (result == null) + throw new ArgumentNullException("result"); + this.result = result; + } + public TestResult Result + { + get { return this.result; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs.meta new file mode 100644 index 0000000..57e25f9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestResultEventArgs.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23d04fa908a5a42819d8dd00117062db +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs new file mode 100755 index 0000000..bdbb7a9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs @@ -0,0 +1,10 @@ +namespace QuickGraph.Unit.Core +{ + public enum TestState :short + { + NotRun = 0, + Success = 1, + Ignore = 2, + Failure = 3 + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs.meta new file mode 100644 index 0000000..41efdd7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TestState.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2782083ceba604489af5a89f27f1e646 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs new file mode 100755 index 0000000..d9013a5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs @@ -0,0 +1,23 @@ +using System; + +namespace QuickGraph.Unit.Core +{ + public abstract class TypeDecoratorTestCaseBase : DecoratorTestCaseBase + where A : Attribute + { + private A attribute; + + public TypeDecoratorTestCaseBase(ITestCase testCase, A attribute) + :base(testCase) + { + if (attribute == null) + throw new ArgumentNullException("attribute"); + this.attribute = attribute; + } + + public A Attribute + { + get { return this.attribute; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs.meta new file mode 100644 index 0000000..fd45823 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeDecoratorTestCaseBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f087d25c41fdb4b139abd1001c79c271 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs new file mode 100755 index 0000000..68a8c18 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; + +namespace QuickGraph.Unit.Core +{ + public abstract class TypeFixtureBase : FixtureBase + where A : TestFixtureAttributeBase + { + private A attribute; + private Type fixtureType; + public TypeFixtureBase(A attribute, Type fixtureType) + :base(attribute.Apartment, attribute.TimeOut, attribute.Description) + { + if (fixtureType == null) + throw new ArgumentNullException("fixtureType"); + + this.attribute = attribute; + this.fixtureType = fixtureType; + this.IsCurrent = ReflectionHelper.GetAttribute(this.FixtureType) != null; + } + + public A Attribute + { + get { return this.attribute; } + } + + public Type FixtureType + { + get { return this.fixtureType; } + } + + public override string Name + { + get { return this.FixtureType.FullName; } + } + + public override object CreateInstance() + { + return Activator.CreateInstance(fixtureType); + } + + protected ITestCase DecorateTest(Object[] decorators, ITestCase test) + { + ITestCase current= test; + foreach (ITestCaseDecorator decorator in decorators) + current = decorator.Decorate(current); + return current; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs.meta new file mode 100644 index 0000000..ec51fc4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeFixtureBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa728351ef8b14670a86d29b04d2b045 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs new file mode 100755 index 0000000..b60d22f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs @@ -0,0 +1,21 @@ +using System; + +namespace QuickGraph.Unit.Core +{ + public abstract class TypeTestCaseBase : TestCaseBase + where A : Attribute + { + private A attribute; + + public TypeTestCaseBase(string fixtureName, A attribute) + : base(fixtureName) + { + this.attribute = attribute; + } + + public A Attribute + { + get { return this.attribute; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs.meta new file mode 100644 index 0000000..6a5ae6d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/TypeTestCaseBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 274b79a4227194c9292e28840cfbc2f9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs new file mode 100755 index 0000000..5073453 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs @@ -0,0 +1,70 @@ +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using QuickGraph.Unit.Logging; + +namespace QuickGraph.Unit.Core +{ + public class UnitContainer : + Container, + IServiceContainer, + IUnitServices + { + private IServiceContainer services = new ServiceContainer(); + private ILoggerService loggerService = new LoggerService(); + + public UnitContainer() + { + this.AddService(typeof(ILoggerService), + this.loggerService + ); + Assert.ServiceProvider = this; + } + + public ILoggerService GetLoggerService() + { + return this.loggerService; + } + + #region IServiceContainer Members + public void AddService(Type serviceType, object serviceInstance) + { + this.services.AddService(serviceType, serviceInstance); + } + public void AddService(Type serviceType, ServiceCreatorCallback callback, bool promote) + { + this.services.AddService(serviceType, callback, promote); + } + public void AddService(Type serviceType, ServiceCreatorCallback callback) + { + this.services.AddService(serviceType, callback); + } + public void AddService(Type serviceType, object serviceInstance, bool promote) + { + this.services.AddService(serviceType, serviceInstance, promote); + } + public void RemoveService(Type serviceType, bool promote) + { + this.services.RemoveService(serviceType, promote); + } + public void RemoveService(Type serviceType) + { + this.services.RemoveService(serviceType); + } + #endregion + + #region IServiceProvider Members + protected override object GetService(Type serviceType) + { + object service = this.services.GetService(serviceType); + if (service != null) + return service; + return base.GetService(serviceType); + } + object IServiceProvider.GetService(Type serviceType) + { + return this.GetService(serviceType); + } + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs.meta new file mode 100644 index 0000000..ce0606c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitContainer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 67346a009a8b4444aa480f1f46ee4c5b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs new file mode 100755 index 0000000..e590165 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs @@ -0,0 +1,15 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; + +namespace QuickGraph.Unit.Core +{ + public enum UnitImages + { + Fixture, + TestCase, + LogMessage, + LogWarning, + LogError + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs.meta new file mode 100644 index 0000000..8e50ee2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitImages.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a39445d95478b45c394b88703ced4cdf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs new file mode 100755 index 0000000..2157b4a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections; +using System.Drawing; +using System.Drawing.Imaging; +using System.Reflection; +using System.IO; +using System.Xml; +using System.Xml.Xsl; +using System.Threading; + +namespace QuickGraph.Unit.Core +{ + public static class UnitResourceManager + { + private static volatile object syncRoot = new object(); + private static XslCompiledTransform htmlReport = null; + private static XslCompiledTransform htmlFixtureReport = null; + private static XslCompiledTransform htmlSummaryReport = null; + private static XslCompiledTransform htmlHistoryReport = null; + private static bool initialized = false; + private static DirectoryInfo directory; + + public static Object SyncRoot + { + get { return syncRoot; } + } + + public static XslCompiledTransform HtmlReport + { + get + { + lock (syncRoot) + { + if (htmlReport != null) + return htmlReport; + + htmlReport = new XslCompiledTransform(); + XsltSettings settings = new XsltSettings(); + settings.EnableScript = true; + htmlReport.Load( + Path.Combine(directory.FullName,"unittest.xslt"), + settings, + new XmlUrlResolver() + ); + return htmlReport; + } + } + } + + public static XslCompiledTransform HtmlFixtureReport + { + get + { + lock (syncRoot) + { + if (htmlFixtureReport != null) + return htmlFixtureReport; + + htmlFixtureReport = new XslCompiledTransform(); + XsltSettings settings = new XsltSettings(); + settings.EnableScript = true; + htmlFixtureReport.Load( + Path.Combine(directory.FullName,"fixturetest.xslt"), + settings, + new XmlUrlResolver() + ); + return htmlFixtureReport; + } + } + } + + public static XslCompiledTransform HtmlSummaryReport + { + get + { + lock (syncRoot) + { + if (htmlSummaryReport != null) + return htmlSummaryReport; + + htmlSummaryReport = new XslCompiledTransform(); + XsltSettings settings = new XsltSettings(); + settings.EnableScript = true; + htmlSummaryReport.Load( + Path.Combine(directory.FullName,"unittestframes.xslt"), + settings, + new XmlUrlResolver() + ); + return htmlSummaryReport; + } + } + } + + public static XslCompiledTransform HtmlHistoryReport + { + get + { + lock (syncRoot) + { + if (htmlHistoryReport != null) + return htmlHistoryReport; + + htmlHistoryReport = new XslCompiledTransform(); + htmlHistoryReport.Load( + Path.Combine(directory.FullName,"unittesthistory.xslt") + ); + return htmlHistoryReport; + } + } + } + + public static void DumpResources() + { + if (!initialized) + { + DumpResources(null); + initialized = true; + } + } + + public static void DumpResources(string path) + { + lock(syncRoot) + { + if (path == null) + path = "."; + + directory = new DirectoryInfo(path); + DumpResource("quickgraph.css", path); + DumpResource("common.xslt", path); + DumpResource("report.js", path); + DumpResource("unittest.xslt", path); + DumpResource("unittesthistory.xslt", path); + DumpResource("unittestframes.xslt", path); + DumpResource("fixturetest.xslt", path); + foreach (UnitImages ui in Enum.GetValues(typeof(UnitImages))) + DumpImage(ui.ToString(), path); + DumpImage("unit", path); + DumpImage("unit.banner", path); + QuickGraphResourceManager.DumpResources(path); + } + } + + private static void DumpResource(string resourceName, string path) + { + using (StreamWriter writer = new StreamWriter(Path.Combine(path, resourceName))) + { + string res = "QuickGraph.Unit." + resourceName; + Stream stream = typeof(UnitResourceManager).Assembly.GetManifestResourceStream(res); + if (stream == null) + throw new ApplicationException("Could not find resource " + res); + using (StreamReader reader = new StreamReader(stream)) + { + writer.Write(reader.ReadToEnd()); + } + } + } + + private static void DumpImage(string resourceName, string path) + { + using (Image image = GetImage(resourceName)) + { + string fileName = String.Format( + "{0}.png", Path.Combine(path, resourceName) + ); + image.Save(fileName, System.Drawing.Imaging.ImageFormat.Png); + } + } + + public static Image GetImage(string imageName) + { + string resource = String.Format("QuickGraph.Unit.{0}.png", imageName); + Stream stream = typeof(UnitResourceManager).Assembly + .GetManifestResourceStream(resource); + if (stream == null) + throw new ApplicationException("Could not find resource " + resource); + Image img = Image.FromStream(stream); + return img; + } + + public static Image GetLogo() + { + return GetImage("unit"); + } + + public static Image GetLogoBanner() + { + return GetImage("unit.banner"); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs.meta new file mode 100644 index 0000000..b3e97b4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Core/UnitResourceManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b04629b0600ff4a0bbdacb6f6ca8b9e0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs new file mode 100755 index 0000000..06538a7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading; +using System.Globalization; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=false, Inherited=true)] + public sealed class CulturesAttribute : TestDecoratorAttributeBase + { + private string cultures; + + public CulturesAttribute(string cultures) + { + if (String.IsNullOrEmpty(cultures)) + throw new ArgumentException("cultures"); + this.cultures = cultures; + } + + public string[] GetCultures() + { + return this.cultures.Split(';'); + } + + public override ITestCase Decorate(ITestCase testCase) + { + return new CulturesTestCase(testCase, this); + } + + private sealed class CulturesTestCase : TypeDecoratorTestCaseBase + { + public CulturesTestCase(ITestCase testCase, CulturesAttribute attribute) + : base(testCase, attribute) + { } + + public override void Run(object fixture) + { + CultureInfo oldCulture = Thread.CurrentThread.CurrentCulture; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + foreach (string cultureName in this.Attribute.GetCultures()) + { + Console.WriteLine("Setting culture: {0}", cultureName); + CultureInfo culture = new CultureInfo(cultureName); + Thread.CurrentThread.CurrentCulture = culture; + this.TestCase.Run(fixture); + } + } + finally + { + Thread.CurrentThread.CurrentCulture = oldCulture; + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs.meta new file mode 100644 index 0000000..8b0f040 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CulturesAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e23d2b4e1faf045a3a2adfacccaeb59b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs new file mode 100755 index 0000000..e57ea38 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class,AllowMultiple =false, Inherited =false)] + public sealed class CurrentFixtureAttribute : Attribute + {} +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs.meta new file mode 100644 index 0000000..bf98c06 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/CurrentFixtureAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65cd40d402d0e4b40901f5e63bb42439 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data.meta new file mode 100644 index 0000000..185a5a8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 6f1e855c6862b4ccc9b21758cf7532cc +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data/unit.sql b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data/unit.sql new file mode 100755 index 0000000..e69de29 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data/unit.sql.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data/unit.sql.meta new file mode 100644 index 0000000..77d2f7b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Data/unit.sql.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: fbaff356d117c41eda433f9bbe12bcc6 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs new file mode 100755 index 0000000..31b36cc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Xml.XPath; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)] + public sealed class DataFixtureAttribute : TestFixtureAttributeBase + { + public override IEnumerable CreateFixtures(Type fixtureType) + { + foreach(DataProviderAttributeBase dataProviderAttribute + in fixtureType.GetCustomAttributes(typeof(DataProviderAttributeBase),true)) + { + yield return new DataFixture( + this, + fixtureType, + dataProviderAttribute); + } + } + + private sealed class DataFixture : TypeFixtureBase + { + private IDataProvider dataProvider; + + public DataFixture( + DataFixtureAttribute attribute, + Type fixtureType, + IDataProvider dataProvider + ) + : base(attribute, fixtureType) + { + this.dataProvider = dataProvider; + } + + public IDataProvider DataProvider + { + get { return this.dataProvider; } + } + + public override IEnumerable CreateTestCases() + { + // load data + XPathNavigator navigator = this.DataProvider.GetData().CreateNavigator(); + + foreach(MethodInfo method in ReflectionHelper.GetMethods( + this.FixtureType, typeof(DataTestAttribute))) + { + foreach (DataTestAttribute dataTestAttribute in + method.GetCustomAttributes(typeof(DataTestAttribute), true)) + { + int i = 0; + foreach(XPathNavigator node in navigator.Select(dataTestAttribute.Select)) + { + DataTestCase test = new DataTestCase( + this.Name, + method, + node, + i.ToString() + ); + i++; + yield return test; + } + } + } + } + + public override String Name + { + get + { + return String.Format("{0}.{1}",base.Name, this.DataProvider.Name); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs.meta new file mode 100644 index 0000000..c5e2e16 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataFixtureAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b5493c6aada504b6684515d95b7ae91a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs new file mode 100755 index 0000000..b780686 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple=true, Inherited=true)] + public sealed class DataTestAttribute : TestAttributeBase + { + private string select = "//*"; + private Type dataType; + + public DataTestAttribute(string select) + { + if (String.IsNullOrEmpty(select)) + throw new ArgumentNullException("select"); + this.select = select; + } + + public string Select + { + get { return this.select; } + set { this.select = value; } + } + + public Type DataType + { + get { return this.dataType; } + set { this.dataType = value; } + } + + public override IEnumerable CreateTests( + IFixture fixture, + MethodInfo method) + { + yield return null; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs.meta new file mode 100644 index 0000000..2c7578d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DataTestAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1dbaee4dc3485456ea9d6f29625c72b7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs new file mode 100755 index 0000000..260b439 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs @@ -0,0 +1,45 @@ +using System; +using QuickGraph.Unit.Monitoring; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, + AllowMultiple=false, Inherited=true)] + public sealed class DurationAttribute : TestDecoratorAttributeBase + { + private double maxDuration; + + public DurationAttribute(double maxDuration) + { + this.maxDuration = maxDuration; + } + + public double MaxDuration + { + get { return this.maxDuration; } + } + + public override ITestCase Decorate(ITestCase test) + { + return new DurationTestCase(test, this); + } + + private sealed class DurationTestCase : TypeDecoratorTestCaseBase + { + public DurationTestCase(ITestCase testCase, DurationAttribute attribute) + :base(testCase, attribute) + {} + + public override void Run(object fixture) + { + TimeMonitor monitor = new TimeMonitor(); + monitor.Start(); + this.TestCase.Run(fixture); + monitor.Stop(); + + Assert.IsLowerEqual(monitor.Duration, this.Attribute.MaxDuration); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs.meta new file mode 100644 index 0000000..11a3f93 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DurationAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4d62be9b13fea4933ad7eb62311e3f84 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs new file mode 100755 index 0000000..0f3ceca --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] + public sealed class DynamicTestAttribute : TestAttributeBase + { + public override IEnumerable CreateTests( + IFixture fixture, + MethodInfo method) + { + if (!typeof(IEnumerable).IsAssignableFrom(method.ReturnType)) + { + List tests = new List(); + tests.Add(new BadTestCase( + fixture.Name, + method.Name, + "A method tagged with DynamicTest must return IEnumerable", + null + )); + return tests; + } + + // the fixture does not exist yet. + Object fixtureInstance = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + fixtureInstance = fixture.CreateInstance(); + return (IEnumerable)method.Invoke(fixtureInstance, null); + } + finally + { + IDisposable disposable = fixtureInstance as IDisposable; + if (disposable != null) + disposable.Dispose(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs.meta new file mode 100644 index 0000000..7b8b95f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/DynamicTestAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 53f9f4ab60f3c4000aed2373d86c4657 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions.meta new file mode 100644 index 0000000..1a7889d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: a273535e3f01d461180ce8b75eb711eb +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs new file mode 100755 index 0000000..09e00a3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs @@ -0,0 +1,23 @@ +using System; +using System.IO; +using System.Reflection; +using System.Collections; +using System.Diagnostics; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Xml; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public class AssertionException : ApplicationException + { + public AssertionException() { } + public AssertionException(string message) : base(message) { } + public AssertionException(string message, System.Exception inner) : base(message, inner) { } + public AssertionException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs.meta new file mode 100644 index 0000000..d6bd142 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssertionException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7c79525c41fc847848cba0b9a8b64296 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs new file mode 100755 index 0000000..8f48d56 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public class AssumptionFailureException : ApplicationException + { + public AssumptionFailureException() { } + public AssumptionFailureException(string message) : base(message) { } + public AssumptionFailureException(string message, Exception inner) : base(message, inner) { } + protected AssumptionFailureException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs.meta new file mode 100644 index 0000000..3d3f99b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/AssumptionFailedException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f511e320436f64e60bd98d0d3ac19e89 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs new file mode 100755 index 0000000..ce71434 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs @@ -0,0 +1,50 @@ +using System; +using System.Runtime.Serialization; +using System.IO; +using System.CodeDom.Compiler; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public class CompilationException : UnitException + { + private string body; + public CompilationException( + CodeDomProvider provider, + CompilerParameters parameters, + CompilerResults results, + params String[] sources + ) + { + StringWriter sw = new StringWriter(); + sw.WriteLine("Compilation: {0} errors", results.Errors.Count); + sw.WriteLine("Compiler: {0}", provider.FileExtension); + sw.WriteLine("CompilerParameters: {0}", parameters.ToString()); + foreach (CompilerError error in results.Errors) + { + sw.WriteLine(error.ToString()); + } + sw.WriteLine("Sources:"); + foreach (string source in sources) + sw.WriteLine(source); + + this.body = sw.ToString(); + } + + public override string Message + { + get + { + return "Compilation Error"; + } + } + + public override string ToString() + { + return String.Format("{0}\n{1}", + this.body, + base.ToString() + ); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs.meta new file mode 100644 index 0000000..2fd5ab9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/CompilationException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f5ec11007fa14740b6bf521e9b871fe +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs new file mode 100755 index 0000000..8ac20a5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs @@ -0,0 +1,15 @@ +using System; + +namespace QuickGraph.Unit.Exceptions +{ + [System.Serializable] + public sealed class DebugFailureException : System.ApplicationException + { + public DebugFailureException() { } + public DebugFailureException(string message) : base( message ) { } + public DebugFailureException(string message, System.Exception inner) : base( message, inner ) { } + public DebugFailureException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base( info, context ) { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs.meta new file mode 100644 index 0000000..5cbae23 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/DebugFailureException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b2af4a56731bc40a7a73f430748cf963 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs new file mode 100755 index 0000000..852badc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs @@ -0,0 +1,17 @@ +using System; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public sealed class ExceptionMessageDoesNotMatchException : Exception + { + public ExceptionMessageDoesNotMatchException( + INameMatcher matcher, + Exception innerException + ) + :base( + String.Format("Exception message {0} does not match {1}", innerException.Message, matcher), + innerException) + { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs.meta new file mode 100644 index 0000000..a8232df --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionMessageDoesNotMatchException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4c75b5036a6d74053b6cbf616a1451e4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs new file mode 100755 index 0000000..c1cd040 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public sealed class ExceptionNotThrowedException : UnitException + { + public ExceptionNotThrowedException(Type expectedException) + : base("Expected " + expectedException.FullName) + { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs.meta new file mode 100644 index 0000000..4a37e2b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionNotThrowedException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ba9806185f873466eb880ef80dc53606 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs new file mode 100755 index 0000000..ce63731 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs @@ -0,0 +1,18 @@ +using System; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public sealed class ExceptionTypeMistmatchException : UnitException + { + public ExceptionTypeMistmatchException(Type expectedExceptionType, Exception actualException) + : base( + String.Format("Expected {0}, got {1}: {2}", + expectedExceptionType.Name, + actualException.GetType().Name, + actualException.Message + ), + actualException) + { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs.meta new file mode 100644 index 0000000..7410aa0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/ExceptionTypeMistmatchException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7229fac9a9ce84be385f1906f460a8da +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs new file mode 100755 index 0000000..c523a95 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public sealed class FixtureReflectionFailedException : UnitException + { + public FixtureReflectionFailedException() { } + public FixtureReflectionFailedException(string message) : base(message) { } + public FixtureReflectionFailedException(string message, Exception inner) : base(message, inner) { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs.meta new file mode 100644 index 0000000..4f5c5ea --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureReflectionFailedException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4d06be5a23da84ee491d66b71502b230 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs new file mode 100755 index 0000000..7ba9900 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public sealed class FixtureTimedOutException : ApplicationException + { + public FixtureTimedOutException(string message) + : base(message) + { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs.meta new file mode 100644 index 0000000..03b5c04 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/FixtureTimedOutException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e6d46ce19b2d44a15aa8ff4afc042d20 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs new file mode 100755 index 0000000..ac0f93b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs @@ -0,0 +1,19 @@ +using System; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public sealed class IgnoreException : UnitException + { + // + // For guidelines regarding the creationg of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public IgnoreException() { } + public IgnoreException(string message) : base(message) { } + public IgnoreException(string message, Exception inner) : base(message, inner) { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs.meta new file mode 100644 index 0000000..1b977ee --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/IgnoreException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e5e510ca7ea6f484f849648e4598f184 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs new file mode 100755 index 0000000..f91d7e7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs @@ -0,0 +1,23 @@ +using System; +using System.IO; +using System.Reflection; +using System.Collections; +using System.Diagnostics; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Xml; + +namespace QuickGraph.Unit.Exceptions +{ + [Serializable] + public class UnitException : ApplicationException + { + public UnitException() { } + public UnitException(string message) : base(message) { } + public UnitException(string message, System.Exception inner) : base(message, inner) { } + public UnitException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs.meta new file mode 100644 index 0000000..1526122 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Exceptions/UnitException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 68c498fc9ddc546f99242871f8891119 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs new file mode 100755 index 0000000..1fec87f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple =false, Inherited =true)] + public sealed class ExpectedArgumentExceptionAttribute : ExpectedExceptionAttribute + { + public ExpectedArgumentExceptionAttribute() + :base(typeof(ArgumentException)) + {} + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs.meta new file mode 100644 index 0000000..0ce7ed0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentExceptionAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bf1a6bc0a6dcd4181bedecfa1d6dc764 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs new file mode 100755 index 0000000..4de5a0d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple =false, Inherited =true)] + public sealed class ExpectedArgumentNullExceptionAttribute : ExpectedExceptionAttribute + { + public ExpectedArgumentNullExceptionAttribute() + :base(typeof(ArgumentNullException)) + {} + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs.meta new file mode 100644 index 0000000..398fd22 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ExpectedArgumentNullExceptionAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2dfbb0a15324f4bcfae5340e0d4af947 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs new file mode 100755 index 0000000..cd27d86 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs @@ -0,0 +1,30 @@ +using System; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class FactoryAttribute : Attribute + { + private Type factoredType = null; + + public FactoryAttribute() { } + public FactoryAttribute(Type factoredType) + { + if (factoredType == null) + throw new ArgumentNullException("factoredType"); + this.factoredType = factoredType; + } + + public Type FactoredType + { + get + { + return this.factoredType; + } + set + { + this.factoredType = value; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs.meta new file mode 100644 index 0000000..0ee4598 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FactoryAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0b2abbc4e0f3241b0804fb88921adc7b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs new file mode 100755 index 0000000..8e5133a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; + +namespace QuickGraph.Unit +{ + public static class FileAssert + { + public static void Display(string fileName, bool showLineNumbers) + { + Exists(fileName); + using(StreamReader reader = new StreamReader(fileName)) + { + string source = reader.ReadToEnd(); + if (showLineNumbers) + source = CompilerAssert.InsertLineNumbers(source); + Console.WriteLine(source); + } + } + + public static void Exists(string fileName) + { + Assert.IsTrue(File.Exists(fileName), + "{0} does not exist", fileName); + } + + public static void AreEqual(string left, string right) + { + Exists(left); + Exists(right); + + FileInfo leftInfo = new FileInfo(left); + FileInfo rightInfo = new FileInfo(right); + + Assert.AreEqual(leftInfo.Length, rightInfo.Length, + "File lengths are not equal between [{0}] and [{1}]", + left, right); + + using (StreamReader leftReader = new StreamReader(left)) + using (StreamReader rightReader = new StreamReader(right)) + { + StreamAssert.AreEqual(leftReader, rightReader); + } + } + + + } +} + diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs.meta new file mode 100644 index 0000000..2fbdbdc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/FileAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7a29f01c860594df693a512423bace5b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters.meta new file mode 100644 index 0000000..5d23410 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 1f8784b6b1c4d495fa612e85e1b48fbb +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs new file mode 100755 index 0000000..1764122 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Filters +{ + public sealed class AndFixtureFilter : BinaryOperationFixtureFilterBase + { + public AndFixtureFilter( + IFixtureFilter left, + IFixtureFilter right) + : base(left, right) + { } + + public override bool Filter(IFixture fixture) + { + return this.Left.Filter(fixture) && this.Right.Filter(fixture); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs.meta new file mode 100644 index 0000000..37e4e85 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndFixtureFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9072b91d5ecb44717ab0c9bf44bdea43 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs new file mode 100755 index 0000000..f5e997a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs @@ -0,0 +1,16 @@ +using System; + +namespace QuickGraph.Unit.Filters +{ + public sealed class AndTestCaseFilter : BinaryOperationTestCaseBase + { + public AndTestCaseFilter(ITestCaseFilter left, ITestCaseFilter right) + : base(left, right) + { } + + public override bool Filter(IFixture fixture, ITestCase testCase) + { + return Left.Filter(fixture, testCase) && Right.Filter(fixture, testCase); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs.meta new file mode 100644 index 0000000..ce58bdd --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AndTestCaseFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bd1e55f8b942c4ed8a7ec1996d5936b5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs new file mode 100755 index 0000000..cfca514 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs @@ -0,0 +1,11 @@ +using System; +namespace QuickGraph.Unit.Filters +{ + public sealed class AnyFixtureFilter : IFixtureFilter + { + public bool Filter(IFixture fixture) + { + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs.meta new file mode 100644 index 0000000..18aaab4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyFixtureFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0fb1ed8c4d81d4db38c82e44bb5331ee +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs new file mode 100755 index 0000000..f6183e9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Unit.Filters +{ + public sealed class AnyTestCaseFilter : ITestCaseFilter + { + public bool Filter(IFixture fixture, ITestCase test) + { + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs.meta new file mode 100644 index 0000000..380309f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/AnyTestCaseFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8521a95299d864ac0b02bb133b37ff79 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs new file mode 100755 index 0000000..c8b3e33 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs @@ -0,0 +1,30 @@ +using System; + +namespace QuickGraph.Unit.Filters +{ + public abstract class BinaryOperationFixtureFilterBase : IFixtureFilter + { + private IFixtureFilter left; + private IFixtureFilter right; + + public BinaryOperationFixtureFilterBase( + IFixtureFilter left, + IFixtureFilter right) + { + this.left = left; + this.right = right; + } + + public IFixtureFilter Left + { + get { return this.left; } + } + + public IFixtureFilter Right + { + get { return this.right; } + } + + public abstract bool Filter(IFixture fixture); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs.meta new file mode 100644 index 0000000..62bebb1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationFixtureFilterBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f1c9554d3c6c4d4b9c13217cbfaaacf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs new file mode 100755 index 0000000..9bc52ae --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs @@ -0,0 +1,30 @@ +using System; + +namespace QuickGraph.Unit.Filters +{ + public abstract class BinaryOperationTestCaseBase : ITestCaseFilter + { + private ITestCaseFilter left; + private ITestCaseFilter right; + + public BinaryOperationTestCaseBase( + ITestCaseFilter left, + ITestCaseFilter right) + { + this.left = left; + this.right = right; + } + + public ITestCaseFilter Left + { + get { return this.left; } + } + + public ITestCaseFilter Right + { + get { return this.right; } + } + + public abstract bool Filter(IFixture fixture, ITestCase testCase); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs.meta new file mode 100644 index 0000000..73bf179 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/BinaryOperationTestCaseFilterBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6908200c889cc42e79d60dce488831f2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs new file mode 100755 index 0000000..74edf4a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Filters +{ + public sealed class CategoryFixtureFilter : IFixtureFilter + { + private string categories; + + public CategoryFixtureFilter(IEnumerable categories) + { + this.categories = ""; + foreach (string category in categories) + this.categories += ";"+category.ToLower(); + } + + public bool Filter(IFixture fixture) + { + foreach (string category in fixture.Categories) + { + if (this.categories.Contains(category.ToLower())) + return true; + } + + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs.meta new file mode 100644 index 0000000..bda12b1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CategoryFixtureFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: de898c1ace94e4a91b28db6450fbc345 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs new file mode 100755 index 0000000..e4c5efe --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Filters +{ + public sealed class CurrentFixtureFilter : IFixtureFilter + { + public bool Filter(IFixture fixture) + { + return fixture.IsCurrent; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs.meta new file mode 100644 index 0000000..b42063a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/CurrentFixtureFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 027bdc3686eb2425c8c286f60ac9648e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs new file mode 100755 index 0000000..9bad7ed --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs @@ -0,0 +1,42 @@ +using System; +using QuickGraph.Unit.Serialization; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Filters +{ + public sealed class FailureFilter : IFixtureFilter, ITestCaseFilter + { + private XmlTestBatchSearcher searcher; + + public FailureFilter(XmlTestBatch testBatch) + { + if (testBatch == null) + throw new ArgumentNullException("testBatch"); + this.searcher = new XmlTestBatchSearcher(testBatch); + } + + public XmlTestBatchSearcher Searcher + { + get { return this.searcher; } + } + + public bool Filter(IFixture fixture) + { + XmlFixture xfixture = this.Searcher.GetFixture(fixture.Name); + + if (xfixture == null) + return false; + else + return xfixture.Counter.FailureCount > 0; + } + + public bool Filter(IFixture fixture, ITestCase testCase) + { + XmlTestCase xtestCase = this.Searcher.GetTestCase(fixture.Name, testCase.Name); + if (xtestCase == null) + return false; + else + return xtestCase.State == TestState.Failure; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs.meta new file mode 100644 index 0000000..b6d3c0b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/FailureFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f0849321aa0b34088831f3e1c3e82cc6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs new file mode 100755 index 0000000..5901a84 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Filters +{ + public sealed class ScopeFixtureFilter : IFixtureFilter + { + private List scopes = new List(); + + public ScopeFixtureFilter(IEnumerable scopes) + { + this.scopes.AddRange(scopes); + } + + public IList Scopes + { + get { return this.scopes; } + } + + public bool Filter(IFixture fixture) + { + foreach (string scope in scopes) + if (fixture.Name.ToLower().StartsWith(scope.ToLower())) + return true; + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs.meta new file mode 100644 index 0000000..3137456 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeFixtureFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8d2088fb495b24265bb728bc49ec5b3d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs new file mode 100755 index 0000000..ce347c8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Filters +{ + public sealed class ScopeTestCaseFilter : ITestCaseFilter + { + private List scopes = new List(); + + public ScopeTestCaseFilter(IEnumerable scopes) + { + this.scopes.AddRange(scopes); + } + + public IList Scopes + { + get { return this.scopes; } + } + + public bool Filter(IFixture fixture, ITestCase test) + { + foreach (string scope in scopes) + if (test.Name.ToLower().StartsWith(scope.ToLower())) + return true; + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs.meta new file mode 100644 index 0000000..ff05d5b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Filters/ScopeTestCaseFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f8f9c5dc54f2e441b9face0b0455dc54 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Fixture.png b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Fixture.png new file mode 100755 index 0000000000000000000000000000000000000000..9af539a1f233dce208f3452391b84d50a308da7a GIT binary patch literal 461 zcmV;;0W$uHP)L}000SeMObu0Z*6U5Zgcf5^;Q0mdW?;z^a=>Q=4Ywa(niu{J@(X(%WI1r^E)n6aBz1=GF z_sw4*f|>wiAxxcl_W$E|KcITPJZ$?2HWQ%=$oY8M|NTCFpy5CSwCr}l9gtc7Q322p zgi&Y`K!mXH;VKa{6$}v3FW0h9%n(PB0E<mh<6&X=4%(kbf!lG7y0z=2h^$KVSkB z1v=?Q&dpyle)s71LX85-LBaw^LPQak!zF;>>atv*jg&@k|s6s0m CreateTestCases(); + IList TestCaseDecorators { get;} + IList Categories { get;} + + Object CreateInstance(); + + MethodInfo FixtureSetUp { get;set;} + MethodInfo SetUp { get;set;} + MethodInfo TearDown { get;set;} + MethodInfo FixtureTearDown { get;set;} + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixture.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixture.cs.meta new file mode 100644 index 0000000..fcf4296 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixture.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b972b7c7f0fc2472fb3466d2100689f3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs new file mode 100755 index 0000000..62bed3c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace QuickGraph.Unit +{ + public interface IFixtureFactory + { + IEnumerable CreateFixtures(Type type); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs.meta new file mode 100644 index 0000000..fadc9a0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 934c5da9a19ac4a3e9bd1251ea0021ba +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs new file mode 100755 index 0000000..99e3005 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs @@ -0,0 +1,9 @@ +using System; + +namespace QuickGraph.Unit +{ + public interface IFixtureFilter + { + bool Filter(IFixture fixture); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs.meta new file mode 100644 index 0000000..4793516 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IFixtureFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d2702fb4e167458d8202748f50433b1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs new file mode 100755 index 0000000..7655423 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Unit +{ + public interface ILoggerListener + { + void Log( + LogLevel level, + string message + ); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs.meta new file mode 100644 index 0000000..1633d70 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a899bb9762eb41d5937cc850158de94 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs new file mode 100755 index 0000000..aaacdad --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit +{ + public interface ILoggerService + { + IList Listeners { get;} + + void Log( + LogLevel level, + string message); + void Log( + LogLevel level, + string format, + params object[] args + ); + void LogMessage( + string message + ); + void LogMessage( + string format, + params object[] args + ); + void LogWarning( + string message + ); + void LogWarning( + string format, + params object[] args + ); + void LogError(Exception ex); + void LogError( + string message + ); + void LogError( + string format, + params object[] args + ); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs.meta new file mode 100644 index 0000000..cf0c78a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ILoggerService.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c413e15eb21234c46950c15f3cdf2ec8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs new file mode 100755 index 0000000..376b709 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Operations; + +namespace QuickGraph.Unit +{ + public interface IParameterDomainFactory + { + void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs.meta new file mode 100644 index 0000000..72e0569 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IParameterDomainFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 17a62bc83b2cf4dab8f7ce968a39490b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs new file mode 100755 index 0000000..b6c0157 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit +{ + public interface ITestCase + { + string FixtureName { get;} + string Name { get;} + string FullName { get;} + + IList Parameters { get;} + + void Run(Object fixture); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs.meta new file mode 100644 index 0000000..8ba782c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 604ee154bfeb3416eb953a649b30ba8e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs new file mode 100755 index 0000000..9e266a4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs @@ -0,0 +1,7 @@ +namespace QuickGraph.Unit +{ + public interface ITestCaseDecorator + { + ITestCase Decorate(ITestCase test); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs.meta new file mode 100644 index 0000000..40f7062 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseDecorator.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 019d032d9a84c4dd8abdd74a0792c0ab +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs new file mode 100755 index 0000000..a6662d7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace QuickGraph.Unit +{ + public interface ITestCaseFactory + { + IEnumerable CreateTests( + IFixture fixture, + MethodInfo method + ); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs.meta new file mode 100644 index 0000000..be6a5e4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 448614c4c568c4c2e9276a28617ec8f9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs new file mode 100755 index 0000000..2f09aff --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs @@ -0,0 +1,7 @@ +namespace QuickGraph.Unit +{ + public interface ITestCaseFilter + { + bool Filter(IFixture fixture, ITestCase test); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs.meta new file mode 100644 index 0000000..25197da --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 86b99a52088dc47a28be155a8b4251fc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs new file mode 100755 index 0000000..6a8177a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit +{ + public interface ITestCaseParameterFactory + { + IEnumerable CreateInstances(Type targetType); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs.meta new file mode 100644 index 0000000..c2ef348 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestCaseParameterFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec278b88757c64eb1a9cb5e52dee6bb1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs new file mode 100755 index 0000000..f7f327b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs @@ -0,0 +1,41 @@ +using System; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + public interface ITestListener + { + void Message(MessageImportance importance, string message); + void Warning(string message); + void Error(string message); + void Error(Exception ex); + void ReportsGenerated( + string historyXml, + string historyHtml, + string batchXml, + string batchHtml); + + void BeforeBatch(TestBatch batch); + void AfterBatch(TestBatch batch); + + void BeforeAssembly(TestAssembly testAssembly); + void AfterAssembly(TestAssembly testAssembly); + + void AssemblySetUp(Result result); + void AssemblyTearDown(Result result); + + void BeforeFixture(IFixture fixture, int testCaseCount); + void AfterFixture(IFixture fixture); + + void FixtureSetUp(TestResult result); + void FixtureTearDown(TestResult result); + + void BeforeTestCase(ITestCase testCase); + void AfterTestCase(ITestCase testCase); + + void SetUp(TestResult result); + void Test(TestResult result); + void TearDown(TestResult result); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs.meta new file mode 100644 index 0000000..3afce5d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ITestListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7bea5879d1394465d9b97717921f38e4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs new file mode 100755 index 0000000..da6696c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs @@ -0,0 +1,10 @@ +using System.Reflection; +using System.ComponentModel; + +namespace QuickGraph.Unit +{ + public interface IUnitServices + { + ILoggerService GetLoggerService(); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs.meta new file mode 100644 index 0000000..594dfcb --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IUnitServices.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 17c6c257a66e54b04a8ff74d9c85add3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs new file mode 100755 index 0000000..418e662 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs @@ -0,0 +1,44 @@ +using System; +using QuickGraph.Unit.Exceptions; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public sealed class IgnoreAttribute : TestDecoratorAttributeBase + { + private string message; + + public IgnoreAttribute(string message) + { + if (message == null) + throw new ArgumentNullException("message"); + this.message = message; + } + + public string Message + { + get { return this.message; } + } + + public override ITestCase Decorate(ITestCase testCase) + { + return new IgnoredTestCase(testCase, this.Message); + } + + private sealed class IgnoredTestCase : DecoratorTestCaseBase + { + private string message; + public IgnoredTestCase(ITestCase testCase, string message) + : base(testCase) + { + this.message = message; + } + + public override void Run(Object fixture) + { + throw new IgnoreException(this.message); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs.meta new file mode 100644 index 0000000..37ca4c1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/IgnoreAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78d3ea16a66864604b38b8cf67e41c2f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs new file mode 100755 index 0000000..ce8a657 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, + AllowMultiple=true, Inherited=true)] + public sealed class KillProcessAttribute : TestDecoratorAttributeBase + { + private string name; + private NameMatchType matchType = NameMatchType.Exact; + + public KillProcessAttribute(string name) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + this.name = name; + } + + public string Name + { + get { return this.name; } + set { this.name = value; } + } + + public NameMatchType MatchType + { + get { return this.matchType; } + set { this.matchType = value; } + } + + public override ITestCase Decorate(ITestCase testCase) + { + return new KillProcessDecoratorTestCase(testCase, this); + } + + private sealed class KillProcessDecoratorTestCase : TypeDecoratorTestCaseBase + { + public KillProcessDecoratorTestCase(ITestCase testCase, KillProcessAttribute attribute) + : base(testCase,attribute) + { } + + public override void Run(object fixture) + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.TestCase.Run(fixture); + } + finally + { + // looking for processes to kill + INameMatcher matcher = NameMatcherFactory.CreateMatcher(this.Attribute.MatchType, this.Attribute.Name); + foreach (Process p in Process.GetProcesses()) + { + if (matcher.IsMatch(p.ProcessName)) + { + Console.WriteLine("Killing {0} {1}", p.Id, p.ProcessName); + p.Kill(); + } + } + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs.meta new file mode 100644 index 0000000..f18601a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/KillProcessAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d2e1284d0e01e415fa6bc34090b3ccf1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners.meta new file mode 100644 index 0000000..67163c9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: c44958a027c214709b43acf86408e696 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs new file mode 100755 index 0000000..a0512cc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs @@ -0,0 +1,331 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Listeners +{ + public sealed class ConsoleTestListener : CounterTestListener + { + private bool silent = false; + private TextWriter _out; + private IFixture currentFixture = null; + private TestResult currentResult = null; + private bool useColors = true; + private bool usePosition = true; + private bool showProgress = true; + + public ConsoleTestListener() + : this(Console.Out) + { } + + public ConsoleTestListener(TextWriter writer) + { + if (writer==null) + throw new ArgumentNullException("writer"); + this._out = writer; + this.UsePosition = !System.Diagnostics.Debugger.IsAttached; + } + + public TextWriter Out + { + get { return this._out; } + } + + public bool Silent + { + get { return this.silent; } + set { this.silent = value; } + } + + public bool UseColors + { + get { return this.useColors; } + set { this.useColors = value; } + } + + public bool UsePosition + { + get { return this.usePosition; } + set { this.usePosition = value; } + } + + public bool ShowProgress + { + get { return this.showProgress; } + set { this.showProgress = value; } + } + + public override void Message(MessageImportance importance, string message) + { + base.Message(importance, message); + if (silent) + return; + if (importance== MessageImportance.Normal || !this.UseColors) + Console.WriteLine(message); + else + { + ConsoleColor color = Console.ForegroundColor; + try + { + if (importance == MessageImportance.Low) + Console.ForegroundColor = ConsoleColor.DarkGray; + else + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine(message); + } + finally + { + SetConsoleDefaultColor(); + } + } + } + + public override void Warning(string message) + { + base.Warning(message); + if (silent) + return; + try + { + SetConsoleColor(TestState.Ignore); + Console.WriteLine(message); + } + finally + { + SetConsoleDefaultColor(); + } + } + + public override void Error(string message) + { + base.Error(message); + if (silent) + return; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + SetConsoleColor(TestState.Failure); + Console.WriteLine(message); + } + finally + { + SetConsoleDefaultColor(); + } + } + + public override void Error(Exception ex) + { + base.Error(ex); + if (silent) + return; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + Console.WriteLine(ex); + } + finally + { + SetConsoleDefaultColor(); + } + } + + public override void BeforeBatch(TestBatch batch) + { + base.BeforeBatch(batch); + if (silent) + return; + this.Out.WriteLine("{0}: Starting tests", DateTime.Now.ToLongTimeString()); + this.Out.Flush(); + } + + public override void AfterBatch(TestBatch batch) + { + base.AfterBatch(batch); + if (silent) + return; + this.Out.WriteLine(); + this.Out.WriteLine("{0}: Tests finished", DateTime.Now.ToLongTimeString()); + this.Out.Flush(); + } + + public override void BeforeAssembly(TestAssembly testAssembly) + { + base.BeforeAssembly(testAssembly); + if (silent) + return; + } + + public override void AfterAssembly(TestAssembly testAssembly) + { + base.AfterAssembly(testAssembly); + } + + public override void AssemblySetUp(Result result) + { + base.AssemblySetUp(result); + if (silent) + return; + if (result.State == TestState.Success) + return; + + this.Out.WriteLine("AssemblySetUp FAILED!"); + this.Out.Flush(); + } + + public override void AssemblyTearDown(Result result) + { + base.AssemblyTearDown(result); + if (silent) + return; + if (result.State == TestState.Success) + return; + + this.Out.WriteLine("AssemblyTearDown FAILED!"); + this.Out.Flush(); + } + + public override void BeforeFixture(IFixture fixture, int testCaseCount) + { + base.BeforeFixture(fixture, testCaseCount); + this.currentFixture = fixture; + } + + public override void AfterFixture(IFixture fixture) + { + base.AfterFixture(fixture); + this.currentFixture = null; + } + + public override void FixtureSetUp(TestResult result) + { + base.FixtureSetUp(result); + } + + public override void FixtureTearDown(TestResult result) + { + base.FixtureTearDown(result); + } + + public override void SetUp(TestResult result) + { + base.SetUp(result); + this.currentResult = result; + } + + public override void Test(TestResult result) + { + base.Test(result); + if (this.currentResult==null || this.currentResult.State== TestState.Success) + this.currentResult = result; + } + + public override void TearDown(TestResult result) + { + base.TearDown(result); + if (this.currentResult.State== TestState.Success) + this.currentResult = result; + } + + public override void BeforeTestCase(ITestCase test) + { + base.BeforeTestCase(test); + if (silent) + return; + this.WriteCounter(test); + } + + + public override void AfterTestCase(ITestCase test) + { + base.AfterTestCase(test); + if (silent) + return; + this.WriteCounter(test); + } + + private void WriteLine(string category, Result result, string format, params object[] args) + { + SetConsoleColor(result.State); + string message = String.Format(format, args); + Out.WriteLine("[{0}][{1}] {2}", result.State, category, message); + this.Out.Flush(); + SetConsoleDefaultColor(); + } + + private void SetConsoleDefaultColor() + { + if (!this.UseColors) + return; + Console.ForegroundColor = ConsoleColor.Gray; + } + + private void SetConsoleColor(TestState state) + { + if (!this.UseColors) + return; + switch (state) + { + case TestState.Success: + Console.ForegroundColor = ConsoleColor.Gray; break; + case TestState.Failure: + Console.ForegroundColor = ConsoleColor.Red; break; + case TestState.Ignore: + Console.ForegroundColor = ConsoleColor.Yellow; break; + default: + Console.ForegroundColor = ConsoleColor.Gray; break; + } + } + + private void SetCounterColor() + { + if (!this.UseColors) + return; + + if (this.Counter.HasFailures) + Console.ForegroundColor = ConsoleColor.Red; + else + Console.ForegroundColor = ConsoleColor.Green; + } + + private void WriteCounter(ITestCase test) + { + if (silent) + return; + if (!this.ShowProgress) + return; + + if (this.UsePosition) + { + int position = Console.CursorLeft; + string white = new string(' ', position+1); + Console.SetCursorPosition(0, Console.CursorTop); + // write blanks + Out.Write(white); + } + + this.SetCounterColor(); + + if (this.UsePosition) + Console.SetCursorPosition(0, Console.CursorTop); + // write test name + string fixtureName = test.FixtureName; + int index = fixtureName.LastIndexOf('.'); + if (index > 0) + fixtureName = fixtureName.Substring(index + 1); + string name = String.Format("{0}.{1}",fixtureName, test.Name); + if (name.Length > 40) + name = name.Substring(0, 40) + "..."; + Out.Write("{0}: {1}, {2}", + DateTime.Now.ToLongTimeString(), + this.Counter, + name); + if (!this.UsePosition) + Console.WriteLine(); + this.Out.Flush(); + SetConsoleDefaultColor(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs.meta new file mode 100644 index 0000000..87c26c4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/ConsoleTestListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 932cea48a78e847a984269404fbfee73 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs new file mode 100755 index 0000000..5620f61 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Unit.Serialization; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Listeners +{ + public class CounterTestListener : ITestListener + { + private TestCounter counter; + private TestCounter assemblyCounter; + private TestCounter fixtureCounter; + private TestState testState; + + public TestCounter Counter + { + get { return this.counter; } + } + + public virtual void ReportsGenerated( + string historyXml, + string historyHtml, + string batchXml, + string batchHtml) + { } + + public virtual void Message(MessageImportance importance, string message) + { } + public virtual void Warning(string message) + { } + public virtual void Error(string message) + { } + public virtual void Error(Exception ex) + { } + + public virtual void BeforeBatch(TestBatch batch) + { + this.counter = new TestCounter(batch.GetTestCount()); + } + + public virtual void AfterBatch(TestBatch batch) + { + } + + public virtual void BeforeAssembly(TestAssembly testAssembly) + { + this.assemblyCounter = new TestCounter(testAssembly.GetTestCount()); + } + + public virtual void AfterAssembly(TestAssembly testAssembly) + { + this.assemblyCounter = null; + } + + public virtual void AssemblySetUp(Result result) + { + if (result.State == TestState.Success) + return; + + this.counter.FailureCount += this.assemblyCounter.TotalCount; + this.assemblyCounter = null; + } + + public virtual void AssemblyTearDown(Result result) + { + if (result.State == TestState.Success || this.assemblyCounter==null) + return; + + this.counter.RollbackResults(this.assemblyCounter); + this.counter.FailureCount += this.assemblyCounter.TotalCount; + this.assemblyCounter = null; + } + + public virtual void BeforeFixture(IFixture fixture, int testCaseCount) + { + this.fixtureCounter = new TestCounter(testCaseCount); + } + + public virtual void AfterFixture(IFixture fixture) + { + } + + public virtual void FixtureSetUp(TestResult result) + { + if (result.State == TestState.Success) + return; + + + this.counter.FailureCount += this.fixtureCounter.TotalCount; + this.assemblyCounter.FailureCount += this.fixtureCounter.TotalCount; + this.fixtureCounter = null; + } + + public virtual void FixtureTearDown(TestResult result) + { + if (result.State == TestState.Success || this.fixtureCounter==null) + return; + + this.counter.RollbackResults(this.fixtureCounter); + this.assemblyCounter.RollbackResults(this.fixtureCounter); + + this.counter.FailureCount += this.fixtureCounter.TotalCount; + this.assemblyCounter.FailureCount += this.fixtureCounter.TotalCount; + + this.fixtureCounter = null; + } + + public virtual void BeforeTestCase(ITestCase testCase) + { + this.testState = TestState.NotRun; + } + + public virtual void AfterTestCase(ITestCase testCase) + { + switch (this.testState) + { + case TestState.NotRun: + throw new InvalidProgramException(); + case TestState.Failure: + this.counter.FailureCount++; + this.assemblyCounter.FailureCount++; + this.fixtureCounter.FailureCount++; + break; + case TestState.Ignore: + this.counter.IgnoreCount++; + this.assemblyCounter.IgnoreCount++; + this.fixtureCounter.IgnoreCount++; + break; + case TestState.Success: + this.counter.SuccessCount++; + this.assemblyCounter.SuccessCount++; + this.fixtureCounter.SuccessCount++; + break; + default: + throw new NotSupportedException(); + } + } + + public virtual void SetUp(TestResult result) + { + testState = result.State; + } + + public virtual void Test(TestResult result) + { + if ((short)testState < (short)result.State) + testState = result.State; + } + + public virtual void TearDown(TestResult result) + { + if ((short)testState < (short)result.State) + testState = result.State; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs.meta new file mode 100644 index 0000000..fca7e19 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/CounterTestListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48ee4ba91c03f43ec977cbb20350f833 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs new file mode 100755 index 0000000..e2d3aa4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Listeners +{ + public sealed class TestListenerCollection : List, + ITestListener + { + public void ReportsGenerated( + string historyXml, + string historyHtml, + string batchXml, + string batchHtml) + { + foreach(ITestListener listener in this) + listener.ReportsGenerated(historyXml, historyHtml, batchXml, batchHtml); + } + + public void Message(string format, params object[] args) + { + Message(MessageImportance.Normal, format, args); + } + + public void Message(string message) + { + Message(MessageImportance.Normal, message); + } + + public void Message(MessageImportance importance, string format, params object[] args) + { + Message(importance, string.Format(format, args)); + } + + public void Message(MessageImportance importance, string message) + { + foreach (ITestListener testListener in this) + testListener.Message(importance, message); + } + + public void Warning(string format, params object[] args) + { + Warning(string.Format(format, args)); + } + + public void Warning(string message) + { + foreach (ITestListener testListener in this) + testListener.Warning(message); + } + + public void Error(string format, params object[] args) + { + Error(string.Format(format, args)); + } + + public void Error(string message) + { + foreach (ITestListener testListener in this) + testListener.Error(message); + } + + public void Error(Exception ex) + { + foreach (ITestListener testListener in this) + testListener.Error(ex); + } + + public void BeforeBatch(TestBatch batch) + { + foreach (ITestListener testListener in this) + testListener.BeforeBatch(batch); + } + + public void AfterBatch(TestBatch batch) + { + foreach (ITestListener testListener in this) + testListener.AfterBatch(batch); + } + + public void BeforeAssembly(TestAssembly testAssembly) + { + foreach (ITestListener testListener in this) + testListener.BeforeAssembly(testAssembly); + } + + public void AfterAssembly(TestAssembly testAssembly) + { + foreach (ITestListener testListener in this) + testListener.AfterAssembly(testAssembly); + } + + public void AssemblySetUp(Result result) + { + foreach (ITestListener testListener in this) + testListener.AssemblySetUp(result); + } + + public void AssemblyTearDown(Result result) + { + foreach (ITestListener testListener in this) + testListener.AssemblyTearDown(result); + } + + public void BeforeFixture(IFixture fixture, int testCaseCount) + { + foreach (ITestListener testListener in this) + testListener.BeforeFixture(fixture, testCaseCount); + } + + public void AfterFixture(IFixture fixture) + { + foreach (ITestListener testListener in this) + testListener.AfterFixture(fixture); + } + + public void FixtureSetUp(TestResult result) + { + foreach (ITestListener testListener in this) + testListener.FixtureSetUp(result); + } + public void FixtureTearDown(TestResult result) + { + foreach (ITestListener testListener in this) + testListener.FixtureTearDown(result); + } + + public void SetUp(TestResult result) + { + foreach (ITestListener testListener in this) + testListener.SetUp(result); + } + public void TearDown(TestResult result) + { + foreach (ITestListener testListener in this) + testListener.TearDown(result); + } + + public void Test(TestResult result) + { + foreach (ITestListener testListener in this) + testListener.Test(result); + } + + public void BeforeTestCase(ITestCase test) + { + foreach (ITestListener testListener in this) + testListener.BeforeTestCase(test); + } + + public void AfterTestCase(ITestCase test) + { + foreach (ITestListener testListener in this) + testListener.AfterTestCase(test); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs.meta new file mode 100644 index 0000000..4967427 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/TestListenerCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b6c6045d9939f49dd9bdace4e713dff6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs new file mode 100755 index 0000000..0725677 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +using QuickGraph.Unit.Serialization; +using QuickGraph.Unit.Reports; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Listeners +{ + public sealed class XmlTestListener : ITestListener + { + private XmlTestBatchSearcher testBatchSearcher = null; + private XmlTestBatch testBatch = new XmlTestBatch(); + private bool showTestCaseOnSuccess = false; + private XmlTestAssembly currentTestAssembly = null; + private XmlFixture currentFixture = null; + private XmlTestCase currentTest = null; + + public bool ShowTestCaseOnSuccess + { + get { return this.showTestCaseOnSuccess; } + set { this.showTestCaseOnSuccess = value; } + } + + public XmlTestBatch TestBatch + { + get { return this.testBatch; } + } + + public void SetPreviousTestBatch(string fileName) + { + XmlTestBatch testBatch = UnitSerializer.Deserialize(fileName); + if (testBatch != null) + SetPreviousTestBatch(testBatch); + } + + public void SetPreviousTestBatch(XmlTestBatch testBatch) + { + if (testBatch == null) + throw new ArgumentNullException("testBatch"); + this.testBatchSearcher = new XmlTestBatchSearcher(testBatch); + } + + public XmlTestBatchSearcher TestBatchSearcher + { + get { return this.testBatchSearcher; } + } + + public void ReportsGenerated( + string historyXml, + string historyHtml, + string batchXml, + string batchHtml) + {} + + public void Message(MessageImportance importance, string message) + { + if (this.TestBatch != null) + this.TestBatch.Log.LogEntries.Add(new XmlLogEntry(LogLevel.Message, message)); + } + + public void Message(string message) + { + if (this.TestBatch!=null) + this.TestBatch.Log.LogEntries.Add(new XmlLogEntry(LogLevel.Message, message)); + } + + public void Warning(string message) + { + if (this.TestBatch != null) + this.TestBatch.Log.LogEntries.Add(new XmlLogEntry(LogLevel.Warning, message)); + } + + public void Error(string message) + { + if (this.TestBatch != null) + this.TestBatch.Log.LogEntries.Add(new XmlLogEntry(LogLevel.Error, message)); + } + + public void Error(Exception ex) + { + if (this.TestBatch != null) + this.TestBatch.Log.LogEntries.Add(new XmlLogEntry(ex)); + } + + public void BeforeBatch(TestBatch batch) + { + this.testBatch.SetMainAssembly(batch.MainTestAssembly.Assembly); + if (this.testBatchSearcher!=null) + this.testBatch.HasHistory = true; + this.testBatch.StartTime = DateTime.Now.ToString("u"); + } + + public void AfterBatch(TestBatch batch) + { + if (this.testBatch != null) + { + this.testBatch.EndTime = DateTime.Now.ToString("u"); + this.testBatch.UpdateCounter(); + } + } + + public void BeforeAssembly(TestAssembly testAssembly) + { + this.currentTestAssembly = new XmlTestAssembly(testAssembly.Assembly.GetName(), testAssembly.Assembly.Location); + this.currentTestAssembly.StartTime = DateTime.Now; + this.testBatch.TestAssemblies.Add(this.currentTestAssembly); + } + + public void AfterAssembly(TestAssembly testAssembly) + { + if (this.currentTestAssembly != null) + { + this.currentTestAssembly.EndTime = DateTime.Now; + this.currentTestAssembly = null; + } + } + + public void AssemblySetUp(Result result) + { + if (this.currentTestAssembly!=null) + this.currentTestAssembly.AssemblySetUp = new XmlResult(result); + } + + public void AssemblyTearDown(Result result) + { + if (this.currentTestAssembly != null) + this.currentTestAssembly.AssemblyTearDown = new XmlResult(result); + } + + public void BeforeFixture(IFixture fixture, int testCaseCount) + { + this.currentFixture = new XmlFixture(fixture, testCaseCount, + GetCategories(fixture), this.currentTestAssembly.Fixtures.Count); + this.currentTestAssembly.Fixtures.Add(this.currentFixture); + } + + private static string GetCategories(IFixture fixture) + { + using (System.IO.StringWriter sw = new System.IO.StringWriter()) + { + bool first = true; + foreach (string category in fixture.Categories) + { + if (first) + { + sw.Write(category); + first = false; + } + else + sw.Write(";{0}", category); + } + return sw.ToString(); + } + } + + public void AfterFixture(IFixture fixture) + { + if (this.currentFixture != null) + { + this.currentFixture.UpdateCounter(); + this.currentFixture = null; + } + } + + public void FixtureSetUp(TestResult result) + { + if (this.currentFixture != null) + { + this.currentFixture.FixtureSetUp = new XmlResult(result); + this.currentFixture.Duration += result.Duration; + } + } + + public void FixtureTearDown(TestResult result) + { + if (this.currentFixture != null) + { + this.currentFixture.FixtureTearDown = new XmlResult(result); + this.currentFixture.Duration += result.Duration; + } + } + + public void SetUp(TestResult result) + { + if (this.currentTest != null) + { + this.currentTest.SetUp = new XmlResult(result); + this.currentFixture.Duration += result.Duration; + } + } + + public void Test(TestResult result) + { + if (this.currentTest != null) + { + this.currentTest.Test = new XmlResult(result); + this.currentFixture.Duration += result.Duration; + } + } + + public void TearDown(TestResult result) + { + if (this.currentTest != null) + { + this.currentTest.TearDown = new XmlResult(result); + this.currentFixture.Duration += result.Duration; + } + } + + public void BeforeTestCase(ITestCase test) + { + this.currentTest = new XmlTestCase(String.Format("{0}t{1}", + this.currentFixture.ID, + this.currentFixture.TestCases.Count), + test.Name); + this.currentFixture.TestCases.Add(this.currentTest); + } + + public void AfterTestCase(ITestCase test) + { + if (this.TestBatchSearcher != null) + { + XmlTestCase previous = this.TestBatchSearcher.GetTestCase(this.currentFixture, this.currentTest); + if (previous == null) + { + this.currentTest.History = XmlTestHistory.New; + } + else + { + if ( + this.currentTest.State == TestState.Success + && previous.State != TestState.Success) + { + this.currentTest.History = XmlTestHistory.Fixed; + } + else if ( + this.currentTest.State == TestState.Failure && + previous.State != TestState.Failure + ) + { + this.currentTest.History = XmlTestHistory.Failure; + } + } + } + + if (!this.ShowTestCaseOnSuccess && this.currentTest.State == TestState.Success) + { + this.currentTest.SetUp = null; + this.currentTest.Test = null; + this.currentTest.TearDown = null; + } + this.currentTest = null; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs.meta new file mode 100644 index 0000000..1f71746 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Listeners/XmlTestListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b70f7ccd2f4694224ac6dd3e99ad42d8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogError.png b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogError.png new file mode 100755 index 0000000000000000000000000000000000000000..6394bb75b6d7559444ffab403e84d1a3bd97b11b GIT binary patch literal 726 zcmV;{0xA88P)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU!R7pfZR5(v%kXcC7Q5=PT8AhaG)Pp|dgC(Uy)@X{kKxmj|h(;)( zB^YT)lomQTnPyp31SUp9Hi4N-1({M7NQ;&mMlR(Ns90GRDpqQ!=zPunlT*-z!{x&H zF6W#jlix>?KWAomP^Nm@WxBsdraym>1&c+NxvUijHxF5*(~G0)x<#wV&xvm+4L_-% zJ3EoVv?#_hqnXQzWhN_zFY#Wyj?wWfC5oP^63we5KgLJ+^thbf^k~L%;^D?gxP2aq zjc_3e5_PcCk?v4us-wK=ymu4D$k&cnbQ=>G&)x@RR^Y)kFlWQ*I5@T)5;j1%6TgCl z=D^id#)UA@@*EkcETTU(3{06&dX9O^ye3P@87#$Fw)a$^Fytpx__EIcoa+3Rh!xNNl_XT0Yd*)p;qsJX@4}*k{ZRVaS!Cif-zc)x6oK^gBR+`n6t(l z@fUim;L9y`7<@gE#>2arJstsuU6ACZby{eu`3u&X8Q&%h_zLabLc?Y|j%;#AT2CEf zXr~K=*lX)qOd0=09nCwyTOXlKFWmL8#~2ZcbeJ#F80oHcPy;OXnoJL4EIGjTR*=$J z*X5WDX-Hpv4Rr^@X$fAVt@hC>b*mv%ClzlIDsf**if%nGswLlh zbXtwd{N^7(feK1;S;_T0BZ`r}?k1EP%$F$J8%(*cGmrEuwDr^ws*{SB?CFLn*PwZo z9dhkof{cDf+$E!ruI&;&8Pgo0jtgf$wuRi761SM07*qo IM6N<$g8TJ8IsgCw literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogError.png.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogError.png.meta new file mode 100644 index 0000000..7cdb0b0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogError.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 4f9a192ad0c0449748ec5d2207339694 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs new file mode 100755 index 0000000..007176f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs @@ -0,0 +1,10 @@ +using System; +namespace QuickGraph.Unit +{ + public enum LogLevel + { + Message, + Warning, + Error + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs.meta new file mode 100644 index 0000000..d4d7de4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogLevel.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 447db32586b90477d9239aefe6583a50 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogMessage.png b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogMessage.png new file mode 100755 index 0000000000000000000000000000000000000000..143347b09017d088e7ef7430a356cea9007306d6 GIT binary patch literal 788 zcmV+v1MB>WP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU!l1W5CR5(v%Qf)|6VHkabp!!!3^sB!`5CjoK6a@Y1M_|^kis%Ee zFC?UI5{bwtNK!MhXqw96l}(g&(t)E_e0r?t1re?{>HA?mXRXv^IR; z!27=EInQ}Gyz62D4^mKzp){EfriqkVPgYk6QBp~=WrIw1Zr@0@Zr)VbN{ATYkbw{m zV!*kGRx<;uH;$i-3|~;e93x@axqy~#2ekT8a4eJU&wvPF77;!G!>At}HVz8@S0t_= z98YB*qOl~}zd3QQRu7t9P|aA7D9^y+^r4|=p+E*Oyo3W4HtZ`O02dPToTlqL9@KY( zW&9vZv>z|^Q|fx*BJoNpjT-F~YTmh#lymO6N}{|<3u?#?GGv>ARl_h(b%z8+-;f1p0h@j+%$pZb89Op1xiwcXL=SF?r1>t z#tFRYoLJ-R@C2~`^au`Lq~Pa5Sw5XskcdY?`{qz~zXgP{xKZ2YP>I!|0WNP4ht8OA z^inSZ;b@jiDGJ2sGCZCcoV%?$+nsJadTmA~pu(E|!{guyBaW5zLX@Q}C5R#a|U3Sk{JpsP`{rN8`*~ Sb^Ve600005r00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU!s7XXYR5(v#n7tUwaPzEEcc)-;@zYvr82ZqwP8Qme7~>$pC!?7)x1 zdC&j%ybsS&#=Rqm|E$0_hZyhMFLZiE*tDPskJ}@buiQC3Ip%TkKZd%`;I%L1+t(eK zjd5Hmo{eWjo0b)yM;-i&$JI;!^K>Qxn}98nB&tfHdDdi@mKBp#|Hb+4IG&Fim|!<{ zTQY%QGVM)~)Sg^2Eh|0^4=@$C)`8Zs27-sUeq$SpQ&v!ENS9sApt>XyWAnAY@?zB4 z&s4P6rx@$YmBKL!_O6oy&Sh8jT6vzu(|VPf6RCgYh1+4{H^T$n*o^C$@Sl{z0Ssj; zQAIwrhE#cu=ZhQbi z25mh|qP;1{*&~M+k~hjB#?#XkP5zcN9KCuN5`4GE5%4B(r$VK!a%;#FHftCC@7u7o zXW|>rmU0%1&jnYw+*O85Q7|gNDhrrZ{GKGV&L}yH7%b*CgtfPWkES!YOv&=yWd~ym zz!t%TJB*u`b!^X#prI}z)Pdh5_+p7AIGV_yL8@5!)Ki@|2PjUvRz9U zJ}G2oDDoNeDBM>7PFdiUz-Lkj49-MrQ7JFVK)h(VN@H~__D3-|+w=@RRIxXyI9e5M z8&pd6Wzku`ih)N8)&~lGjSBW=73UL$`icbELB|8y@8?icqUYj~@DLY%?bXHMR2S>G oRHT#NCi!_kN!3vuwWW*r0pxI~a@H@UKmY&$07*qoM6N<$f+3M@)Bpeg literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogWarning.png.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogWarning.png.meta new file mode 100644 index 0000000..7b877fa --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/LogWarning.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 91db4d529e12c49798f6eb354688a446 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging.meta new file mode 100644 index 0000000..35bb477 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: f2cf07a8f51ae4679a7405b6b6069f51 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs new file mode 100755 index 0000000..dbf925a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs @@ -0,0 +1,17 @@ +using System; +using System.IO; + +namespace QuickGraph.Unit.Logging +{ + public sealed class ConsoleLoggerListener : ILoggerListener + { + public void Log(LogLevel level, string message) + { + Console.WriteLine( + "[{0}] {1}", + level, + message + ); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs.meta new file mode 100644 index 0000000..fc7b972 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/ConsoleLoggerListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 75ada08075e5043529b85caa33057ed0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs new file mode 100755 index 0000000..e3caaf4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Logging +{ + [Serializable] + internal sealed class LoggerService : ILoggerService + { + private volatile object syncRoot = new object(); + private List listeners = new List(); + public object SyncRoot + { + get { return this.syncRoot;} + } + + public IList Listeners + { + get + { + lock(this.SyncRoot) + { + return this.listeners; + } + } + } + + public void Log(LogLevel level, string message) + { + lock (this.SyncRoot) + { + foreach (ILoggerListener listener in this.listeners) + listener.Log(level, message); + } + } + + public void Log(LogLevel level, string format, params object[] args) + { + if (this.Listeners.Count == 0) + return; + string message = string.Format(format, args); + this.Log(level, message); + } + + public void LogMessage(string message) + { + this.Log(LogLevel.Message, message); + } + + public void LogMessage(string format, params object[] args) + { + this.Log(LogLevel.Message, format, args); + } + + public void LogWarning(string message) + { + this.Log(LogLevel.Warning, message); + } + + public void LogWarning(string format, params object[] args) + { + this.Log(LogLevel.Warning, format, args); + } + + public void LogError(string message) + { + this.Log(LogLevel.Error, message); + } + + public void LogError(string format, params object[] args) + { + this.Log(LogLevel.Error, format, args); + } + + public void LogError(Exception ex) + { + this.Log(LogLevel.Error, ex.ToString()); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs.meta new file mode 100644 index 0000000..720e245 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/LoggerService.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10e67d67020384187bbd28beb30b88a5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs new file mode 100755 index 0000000..d422c19 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs @@ -0,0 +1,24 @@ +using System; +using QuickGraph.Unit.Serialization; + +namespace QuickGraph.Unit.Logging +{ + public sealed class XmlLoggerListener : ILoggerListener + { + private XmlLog log = new XmlLog(); + + public XmlLog GetLog() + { + return this.log; + } + + public void Log(LogLevel level, string message) + { + XmlLogEntry entry = new XmlLogEntry(); + entry.Level = level; + entry.Message = message; + + this.log.LogEntries.Add(entry); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs.meta new file mode 100644 index 0000000..c8bb178 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Logging/XmlLoggerListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1b50908409c74990bab1b1e010c253b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs new file mode 100755 index 0000000..d07d49c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Unit +{ + [Serializable] + public enum MessageImportance + { + Low, + Normal, + High + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs.meta new file mode 100644 index 0000000..9862e8c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MessageImportance.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0b3a7d4ad8714d9eb006945a40ba9f2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring.meta new file mode 100644 index 0000000..01122ff --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 1889fdbd1b31542ef8b85f4942c06afc +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs new file mode 100755 index 0000000..72b2195 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs @@ -0,0 +1,33 @@ +using System; +using QuickGraph.Unit.Logging; + +namespace QuickGraph.Unit.Monitoring +{ + public sealed class ConsoleLoggerMonitor : IMonitor + { + private ILoggerService logger; + private ConsoleLoggerListener listener = new ConsoleLoggerListener(); + + public ConsoleLoggerMonitor(ILoggerService logger) + { + if (logger == null) + throw new ArgumentNullException("logger"); + this.logger = logger; + } + + public void Start() + { + this.logger.Listeners.Add(this.listener); + } + + public void Stop() + { + this.logger.Listeners.Remove(this.listener); + } + + public void Dispose() + { + this.Stop(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs.meta new file mode 100644 index 0000000..9cf5f86 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleLoggerMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c149d3af890364f839a47fa999947446 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs new file mode 100755 index 0000000..9953d6f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; + +namespace QuickGraph.Unit.Monitoring +{ + public sealed class ConsoleMonitor : IMonitor + { + private TextWriter consoleOut; + private TextWriter consoleError; + private StringWriter _out = new StringWriter(); + private StringWriter _error = new StringWriter(); + + public ConsoleMonitor() + {} + + public void Start() + { + this.consoleOut = Console.Out; + this.consoleError = Console.Error; + + this._out = new StringWriter(); + this._error = new StringWriter(); + Console.SetOut(this._out); + Console.SetError(this._out); + } + + public string Out + { + get { return this._out.ToString(); } + } + + public string Error + { + get { return this._error.ToString(); } + } + + public void Stop() + { + if (this.consoleOut != null) + { + Console.SetOut(this.consoleOut); + this.consoleOut = null; + } + if (this.consoleError != null) + { + Console.SetError(this.consoleError); + this.consoleError = null; + } + } + + public void Dispose() + { + this.Stop(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs.meta new file mode 100644 index 0000000..b4ebfa2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ConsoleMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 76d9e132258544b6c8433e5b1cc30fba +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs new file mode 100755 index 0000000..d15bf06 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs @@ -0,0 +1,116 @@ +using System; +using System.Diagnostics; +using QuickGraph.Unit.Exceptions; + +namespace QuickGraph.Unit.Monitoring +{ + public sealed class DebugMonitor : IMonitor + { + private DefaultTraceListener defaultListener; + private DebugMonitorTraceListener listener; + + public DebugMonitor(ILoggerService logger) + { + if (logger == null) + throw new ArgumentNullException("logger"); + this.listener = new DebugMonitorTraceListener(logger); + } + + public void Start() + { + // find default listnerer + foreach (TraceListener tc in Debug.Listeners) + { + this.defaultListener = tc as DefaultTraceListener; + if (defaultListener != null) + break; + } + + // remove default listener + if (this.defaultListener != null) + Debug.Listeners.Remove(this.defaultListener); + + // adding custom + Debug.Listeners.Add(this.listener); + } + + public void Stop() + { + if (this.defaultListener != null) + { + Debug.Listeners.Add(this.defaultListener); + this.defaultListener = null; + } + Debug.Listeners.Remove(this.listener); + } + + public void Dispose() + { + this.Stop(); + } + + private sealed class DebugMonitorTraceListener : TraceListener + { + private ILoggerService logger; + private DefaultTraceListener defaultListener; + + public DebugMonitorTraceListener(ILoggerService logger) + { + this.logger = logger; + foreach (TraceListener tc in Debug.Listeners) + { + this.defaultListener = tc as DefaultTraceListener; + if (defaultListener != null) + break; + } + } + + private void WriteLine(string format, params object[] args) + { + this.logger.LogMessage("Debug", format, args); + if (this.defaultListener != null) + this.defaultListener.WriteLine(String.Format(format, args)); + } + + public override void Fail(string message) + { + this.logger.LogError("Debug", message); + throw new DebugFailureException(message); + } + + public override void Fail(string message, string messageDetail) + { + this.logger.LogError("Debug", "{0}\n{1}", message, messageDetail); + throw new DebugFailureException(message + messageDetail); + } + + public override void Write(string message) + { + this.logger.LogMessage("Debug", message); + if (this.defaultListener != null) + this.defaultListener.Write(message); + } + + public override void WriteLine(string message) + { + this.logger.LogMessage("Debug", message); + if (this.defaultListener != null) + this.defaultListener.WriteLine(message); + } + + public override void Write(string message, string category) + { + this.logger.LogMessage(category, message); + if (this.defaultListener != null) + this.defaultListener.Write(message,category); + } + + public override void WriteLine(string message, string category) + { + this.logger.LogMessage(category, message); + if (this.defaultListener != null) + this.defaultListener.WriteLine(message, category); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs.meta new file mode 100644 index 0000000..26a577d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/DebugMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c564ce30fc0ce4cf3b9d0ff1a392d5d6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs new file mode 100755 index 0000000..ee6a386 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Monitoring +{ + internal sealed class EnvironmentMonitor : IMonitor + { + private string currentDirectory; + + public void Start() + { + this.currentDirectory = Environment.CurrentDirectory; + + } + + public void Stop() + { + if (this.currentDirectory!=null) + Environment.CurrentDirectory = this.currentDirectory; + this.currentDirectory = null; + } + + public void Dispose() + { + Stop(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs.meta new file mode 100644 index 0000000..065af12 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/EnvironmentMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 92b4f21c473724cc4b2216f1b94de0a6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs new file mode 100755 index 0000000..17eb745 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs @@ -0,0 +1,10 @@ +using System; + +namespace QuickGraph.Unit.Monitoring +{ + public interface IMonitor : IDisposable + { + void Start(); + void Stop(); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs.meta new file mode 100644 index 0000000..32783c4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/IMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 01b8c355fe66a469daa30062267c08bc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs new file mode 100755 index 0000000..0837a55 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Monitoring +{ + public sealed class MonitorCollection : List, IDisposable + { + private ILoggerService logger; + public MonitorCollection(ILoggerService logger) + { + if (logger == null) + throw new ArgumentNullException("logger"); + this.logger = logger; + } + + public void Start() + { + foreach (IMonitor monitor in this) + { + monitor.Start(); + } + } + + public void Stop() + { + foreach (IMonitor monitor in this) + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + monitor.Stop(); + } + catch (Exception ex) + { + this.logger.LogError("Monitoring", ex, "monitor {0} failed to stop", monitor); + } + } + } + + public void Dispose() + { + this.Stop(); + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + foreach (IMonitor monitor in this) + monitor.Dispose(); + } + finally + { + this.Clear(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs.meta new file mode 100644 index 0000000..bbb05e0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/MonitorCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6eb312ea77cc443ad8602edf260d1971 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs new file mode 100755 index 0000000..1d9843a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs @@ -0,0 +1,53 @@ +using System; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Monitoring +{ + public sealed class ThreadExceptionMonitor: IMonitor + { + private ILoggerService logger; + private List exceptions = new List(); + + public ThreadExceptionMonitor(ILoggerService logger) + { + if (logger==null) + throw new ArgumentNullException("logger"); + this.logger = logger; + } + + public IList Exceptions + { + get { return this.exceptions; } + } + + public void Start() + { + System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); + } + + public void Clear() + { + this.exceptions.Clear(); + } + + public void Stop() + { + System.Windows.Forms.Application.ThreadException -= new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); + } + + public void Dispose() + { + this.Stop(); + } + + void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) + { + this.exceptions.Add(e.Exception); + this.logger.LogError( + "Thread", + e.Exception, + "Exception occured in concurrent thread"); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs.meta new file mode 100644 index 0000000..32cd24d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadExceptionMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 858e4040d68c14cae84980efb6884194 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs new file mode 100755 index 0000000..36dfce0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Globalization; +using System.Security.Principal; + +namespace QuickGraph.Unit.Monitoring +{ + internal sealed class ThreadMonitor : IMonitor + { + private CultureInfo cultureInfo; + private CultureInfo uiCulture; + private IPrincipal principal; + + public void Start() + { + this.cultureInfo = Thread.CurrentThread.CurrentCulture; + this.uiCulture = Thread.CurrentThread.CurrentUICulture; + this.principal = Thread.CurrentPrincipal; + } + + public void Stop() + { + if (this.cultureInfo != null) + { + Thread.CurrentThread.CurrentCulture = this.cultureInfo; + this.cultureInfo = null; + } + if (this.uiCulture != null) + { + Thread.CurrentThread.CurrentUICulture = this.uiCulture; + this.uiCulture = null; + } + if (this.principal != null) + { + Thread.CurrentPrincipal = this.principal; + this.principal = null; + } + } + + public void Dispose() + { + Stop(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs.meta new file mode 100644 index 0000000..c1f6f3c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/ThreadMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 37c3cce3bfce3416eb733a7a015a84c9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs new file mode 100755 index 0000000..dfafec6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs @@ -0,0 +1,50 @@ +using System; + +namespace QuickGraph.Unit.Monitoring +{ + public sealed class TimeMonitor : IMonitor + { + private DateTime startTime; + private DateTime endTime; + private bool running; + + public TimeMonitor() + {} + + public void Start() + { + this.startTime = this.endTime = DateTime.Now; + this.running = true; + } + + public void Stop() + { + if (running) + { + this.endTime = DateTime.Now; + this.running = false; + } + } + + public DateTime StartTime + { + get { return this.startTime; } + } + + public DateTime EndTime + { + get { return this.endTime; } + } + + public double Duration + { + get + { + TimeSpan ts = this.endTime - this.startTime; + return ts.TotalSeconds; + } + } + + public void Dispose() { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs.meta new file mode 100644 index 0000000..963eae1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/TimeMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec936bad68514473daf01dbd77b117fd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs new file mode 100755 index 0000000..0f9b346 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +namespace QuickGraph.Unit.Monitoring +{ + public sealed class UnhandledExceptionMonitor : IMonitor + { + private bool disposed = false; + public void Start() + { + AppDomain.CurrentDomain.UnhandledException+=new UnhandledExceptionEventHandler(UnhandledException); + } + + public void Stop() + { + AppDomain.CurrentDomain.UnhandledException -= new UnhandledExceptionEventHandler(UnhandledException); + } + + public void Dispose() + { + if (!disposed) + { + this.Stop(); + GC.SuppressFinalize(this); + this.disposed = true; + } + } + + private void UnhandledException(Object sender, UnhandledExceptionEventArgs args) + { + if (args.IsTerminating) + return; + + Assert.Fail("Unhandled Exception was catched\n", args.ExceptionObject); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs.meta new file mode 100644 index 0000000..a79bc3a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/UnhandledExceptionMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4d5e2d0b64e274ecd90b06e6946667c7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs new file mode 100755 index 0000000..4d2496b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit.Logging; +using QuickGraph.Unit.Serialization; + +namespace QuickGraph.Unit.Monitoring +{ + public class TestMonitor : IMonitor + { + private ILoggerService loggerService; + private MonitorCollection monitors; + private ConsoleMonitor consoleMonitor; + private TimeMonitor timeMonitor; + private UnhandledExceptionMonitor unhandledExceptionMonitor; + private ThreadExceptionMonitor threadExceptionMonitor; + private DebugMonitor debugMonitor; + private XmlLoggerListener loggerListener = null; + + public TestMonitor() + :this(Assert.Logger) + { } + + public TestMonitor(ILoggerService loggerService) + { + this.loggerService = loggerService; + this.consoleMonitor = new ConsoleMonitor(); + this.timeMonitor = new TimeMonitor(); + this.unhandledExceptionMonitor = new UnhandledExceptionMonitor(); + this.threadExceptionMonitor = new ThreadExceptionMonitor(loggerService); + this.debugMonitor = new DebugMonitor(loggerService); + this.loggerListener = new XmlLoggerListener(); + + this.monitors = new MonitorCollection(loggerService); + this.monitors.Add(this.consoleMonitor); + this.monitors.Add(this.timeMonitor); + this.monitors.Add(this.unhandledExceptionMonitor); + this.monitors.Add(this.threadExceptionMonitor); + this.monitors.Add(this.debugMonitor); + this.monitors.Add(new EnvironmentMonitor()); + this.monitors.Add(new ThreadMonitor()); + } + + public ILoggerService LoggerService + { + get { return this.loggerService; } + } + + public MonitorCollection Monitors + { + get { return this.monitors; } + } + + public ConsoleMonitor Console + { + get { return this.consoleMonitor; } + } + + public TimeMonitor Timer + { + get { return this.timeMonitor; } + } + + public UnhandledExceptionMonitor UnhandledException + { + get { return this.unhandledExceptionMonitor; } + } + + public ThreadExceptionMonitor ThreadException + { + get { return this.threadExceptionMonitor; } + } + + public DebugMonitor Debug + { + get { return this.debugMonitor; } + } + + public XmlLog GetLog() + { + return this.loggerListener.GetLog(); + } + + public void Start() + { + this.loggerListener = new XmlLoggerListener(); + this.LoggerService.Listeners.Add(this.loggerListener); + this.monitors.Start(); + } + + public void Stop() + { + this.monitors.Stop(); + this.LoggerService.Listeners.Remove(this.loggerListener); + } + + public void Dispose() + { + this.Stop(); + if (this.monitors != null) + { + this.monitors.Dispose(); + this.monitors = null; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs.meta new file mode 100644 index 0000000..bd5f9ea --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Monitoring/testmonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b33bbd03f6404aa69fc5aa191c9cb5e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs new file mode 100755 index 0000000..e726c38 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs @@ -0,0 +1,35 @@ +using System; +using System.Reflection; +using System.Collections.Generic; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class MultiThreadedTestAttribute : TestAttributeBase + { + private int threadCount = 1; + + public MultiThreadedTestAttribute() + { } + + public MultiThreadedTestAttribute(int threadCount) + { + this.threadCount = threadCount; + } + + public int ThreadCount + { + get { return this.threadCount; } + set { this.threadCount = value; } + } + + public override IEnumerable CreateTests(IFixture fixture, MethodInfo method) + { + for (int i = 0; i < this.ThreadCount; ++i) + { + yield return new MethodTestCase(fixture.Name, method); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs.meta new file mode 100644 index 0000000..94fe07f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cb0bec47b36e441408740361c8777c02 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs new file mode 100755 index 0000000..3570b03 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Reflection; +using System.Threading; +using QuickGraph.Unit.Monitoring; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] + public sealed class MultiThreadedTestFixtureAttribute : TestFixtureAttributeBase + { + private int retryCount = 1; + + public int RetryCount + { + get { return this.retryCount; } + set { this.retryCount = value; } + } + + public override IEnumerable CreateFixtures(Type type) + { + foreach (MultiThreadedTestFixtureAttribute attribute in + type.GetCustomAttributes(typeof(MultiThreadedTestFixtureAttribute), true)) + { + yield return new MultiThreadedTestFixture(attribute, type); + } + } + + private sealed class MultiThreadedTestFixture : TypeFixtureBase + { + public MultiThreadedTestFixture(MultiThreadedTestFixtureAttribute attribute, Type fixtureType) + :base(attribute,fixtureType) + {} + + public override IEnumerable CreateTestCases() + { + // we create only 1 test case for this type of + // fixture + MultiThreadedTestCase testCase = new MultiThreadedTestCase(this); + + // populate with threaded tests + foreach (MethodInfo method in this.FixtureType.GetMethods()) + { + Object[] decorators = method.GetCustomAttributes(typeof(TestDecoratorAttributeBase), true); + foreach (MultiThreadedTestAttribute attribute in method.GetCustomAttributes(typeof(MultiThreadedTestAttribute), true)) + { + // let's make sure the method takes a TestSynchronizer argument + if (!VerifyMethod(method)) + { + yield return new BadTestCase( + this.Name, + method.Name, + "MultiThreadTest method requires TestSynchronizer arugment", + new Exception() + ); + break; + } + + int index = 0; + foreach (ITestCase test in attribute.CreateTests(this, method)) + { + // we get the test case + ITestCase decoratedTest = DecorateTest(decorators, test); + // we add the synchronizer parameter + decoratedTest.Parameters.Add(new TestCaseParameter(testCase.Synchronizer)); + // we add a worker for the test + TestCaseWorker worker = new TestCaseWorker(decoratedTest, index); + testCase.Workers.Add(worker); + index++; + } + } + } + + yield return testCase; + } + + private bool VerifyMethod(MethodInfo method) + { + ParameterInfo[] parameters = method.GetParameters(); + return parameters.Length == 1 + && parameters[0].ParameterType == typeof(TestSynchronizer); + } + } + + private sealed class MultiThreadedTestCase : TestCaseBase + { + private volatile TestSynchronizer synchronizer; + private int retryCount; + private TestCaseWorkerCollection workers = new TestCaseWorkerCollection(); + + public MultiThreadedTestCase(MultiThreadedTestFixture fixture) + : base(fixture.Name) + { + this.retryCount = fixture.Attribute.RetryCount; + this.synchronizer = new TestSynchronizer(this.Name); + } + + public TestSynchronizer Synchronizer + { + get { return this.synchronizer; } + } + + public override string UndecoratedName + { + get { return "Multi"; } + } + + public TestCaseWorkerCollection Workers + { + get { return this.workers; } + } + + public override void Run(object fixture) + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + for (int i = 0; i < this.retryCount; ++i) + { + if (i != 0) + Console.WriteLine("Multithread test retry {0}/{1}", i, retryCount); + this.InternalRun(fixture); + } + } + + private void InternalRun(object fixture) + { + // block barrier + this.synchronizer.Block(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.Workers.StartAll(fixture); + } + finally + { + // make sure the barrier is hit + while(!this.Workers.ContainsAll(this.synchronizer.GetThreadNames())) + { + Thread.Sleep(100); + } + // this will launch all the threads... + this.synchronizer.Release(); + } + + // runs threads + this.Workers.WaitAll(); + } + finally + { + // aborting thread if not dead yet + this.Workers.CloseAll(); + } + + // verifying execution + this.Workers.Verify(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs.meta new file mode 100644 index 0000000..f1a1f1b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/MultiThreadedTestFixtureAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6350ff3a13c3b404985ff4e890fbdde0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs new file mode 100755 index 0000000..0b646a1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs @@ -0,0 +1,74 @@ +using System; +using System.Text.RegularExpressions; + +namespace QuickGraph.Unit +{ + public enum NameMatchType + { + Exact, + Contains, + Regex + } + + public interface INameMatcher + { + bool IsMatch(string value); + } + + public static class NameMatcherFactory + { + public static INameMatcher CreateMatcher(NameMatchType matchType, string name) + { + switch (matchType) + { + case NameMatchType.Exact: return new ExactNameMatcher(name); + case NameMatchType.Contains: return new ContainsNameMatcher(name); + case NameMatchType.Regex: return new RegexNameMatcher(name); + default: throw new NotSupportedException(matchType.ToString()); + } + } + + private sealed class ExactNameMatcher : INameMatcher + { + string name; + public ExactNameMatcher(string name) + { + this.name = name; + } + + public bool IsMatch(string value) + { + return this.name.Equals(value); + } + } + + + private sealed class ContainsNameMatcher : INameMatcher + { + string name; + public ContainsNameMatcher(string name) + { + this.name = name; + } + + public bool IsMatch(string value) + { + return this.name.Contains(value); + } + } + + private sealed class RegexNameMatcher : INameMatcher + { + private Regex rx; + public RegexNameMatcher(string name) + { + rx = new Regex(name, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + + public bool IsMatch(string name) + { + return rx.IsMatch(name); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs.meta new file mode 100644 index 0000000..0b6274f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/NameMatch.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ac83b71a4b9ef47f296d77d79e82c999 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations.meta new file mode 100644 index 0000000..4abed9d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: ef2da35880fa34598831e61f31222120 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs new file mode 100755 index 0000000..5f7fe3d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections; + +namespace QuickGraph.Operations +{ + public sealed class ArrayDomain : DomainBase + { + private Array array; + + public ArrayDomain(Array array) + { + if (array == null) + throw new ArgumentNullException("array"); + this.array = array; + } + + public override int Count + { + get { return array.Length; } + } + + public override IEnumerator GetEnumerator() + { + return array.GetEnumerator(); + } + + public override Object this[int index] + { + get { return this.array.GetValue(index); } + } + } + + public sealed class ArrayDomain : DomainBase + { + private T[] array; + + public ArrayDomain(T[] array) + { + if (array == null) + throw new ArgumentNullException("array"); + this.array = array; + } + + public override int Count + { + get { return array.Length; } + } + + public override IEnumerator GetEnumerator() + { + return array.GetEnumerator(); + } + + public override Object this[int index] + { + get { return this.array.GetValue(index); } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs.meta new file mode 100644 index 0000000..6777bb3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ArrayDomain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f01d9a316e350405b8007624e96cc17c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs new file mode 100755 index 0000000..706fbf4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs @@ -0,0 +1,35 @@ +using System; + +namespace QuickGraph.Operations +{ + public sealed class BooleanDomain : DomainBase + { + private bool[] values = new bool[] { true, false }; + public BooleanDomain() + {} + + public override int Count + { + get { return 2; } + } + + public override System.Collections.IEnumerator GetEnumerator() + { + return values.GetEnumerator(); + } + + public override Object this[int index] + { + get + { + switch (index) + { + case 0: return this.values[0]; + case 1: return this.values[1]; + default: + throw new ArgumentOutOfRangeException("index"); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs.meta new file mode 100644 index 0000000..1ea6668 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/BooleanDomain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23483340c3ce64b02b97563a8a4f9d1c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs new file mode 100755 index 0000000..8b62fcb --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + internal sealed class CartesianProductDomainTupleEnumerable : IEnumerable + { + private IList domains; + public CartesianProductDomainTupleEnumerable(IList domains) + { + this.domains = domains; + } + + public IEnumerator GetEnumerator() + { + return new CartesianProductDomainTupleEnumerator(this.domains); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs.meta new file mode 100644 index 0000000..f5a5275 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerable.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dde0115292fe941cc9854ffda2a11e9a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs new file mode 100755 index 0000000..64a1fe0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + internal sealed class CartesianProductDomainTupleEnumerator : DomainTupleEnumeratorBase + { + private ITuple tuple = null; + private int[] indices = null; + + public CartesianProductDomainTupleEnumerator(IList domains) + :base(domains) + { + this.indices=new int[this.Domains.Count]; + this.Reset(); + } + + public override void Reset() + { + for (int i = 0; i < this.indices.Length; ++i) + { + if (i==this.indices.Length-1) + this.indices[i] = -1; + else + this.indices[i] = 0; + } + this.tuple=null; + } + + public override bool MoveNext() + { + for (int i = this.indices.Length - 1; i >= 0; i--) + { + if (this.indices[i] < this.Domains[i].Count - 1) + { + // updating index + this.indices[i]++; + // reseting the other to zero + for(int j = i+1 ; j < this.indices.Length;++j) + this.indices[j] = 0; + + // getting the tuple + tuple = new Tuple(); + for (int k = 0; k < this.indices.Length; ++k) + { + object item = this.Domains[k][this.indices[k]]; + tuple.Add(item); + } + + return true; + } + } + + + return false; + } + + public override ITuple Current + { + get + { + return this.tuple; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs.meta new file mode 100644 index 0000000..1bb3344 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CartesianProductDomainTupleEnumerator.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f0c3e91211eb64aae91b2782ed6a49c6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs new file mode 100755 index 0000000..cb33a18 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections; + +namespace QuickGraph.Operations +{ + public sealed class CollectionDomain : CollectionBase, IDomain + { + private string name = null; + + public CollectionDomain() + { } + + public CollectionDomain(ICollection collection) + { + foreach (Object item in collection) + this.List.Add(item); + } + public CollectionDomain(IEnumerable enumerable) + { + foreach(Object item in enumerable) + this.List.Add(item); + } + + public string Name + { + get + { + return this.name; + } + set + { + this.name = value; + } + } + + public object this[int i] + { + get + { + return this.List[i]; + } + } + + public void AddDomain(IDomain domain) + { + if (domain == null) + throw new ArgumentNullException("domain"); + this.AddRange(domain); + } + + public void AddRange(IEnumerable enumerable) + { + if (enumerable == null) + throw new ArgumentNullException("enumerable"); + foreach (Object o in enumerable) + this.List.Add(o); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs.meta new file mode 100644 index 0000000..7cb2556 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CollectionDomain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 050c7b902865a4d3487d3513d83ccb86 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs new file mode 100755 index 0000000..b96c2a7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs @@ -0,0 +1,10 @@ +using System; + +namespace QuickGraph.Operations +{ + public enum CombinationType + { + PairWize, + Cartesian + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs.meta new file mode 100644 index 0000000..d77c35b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/CombinationType.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f849fef4fe034768b1c8133493dba77 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs new file mode 100755 index 0000000..91b847e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections; + +namespace QuickGraph.Operations +{ + public abstract class DomainBase : IDomain + { + private string name = null; + + public string Name + { + get + { + return this.name; + } + set + { + this.name = value; + } + } + + public abstract int Count { get;} + public abstract IEnumerator GetEnumerator(); + public abstract Object this[int index] { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs.meta new file mode 100644 index 0000000..5afc7f4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6ae5e419f657c4cb7bfdbcacc5b7a27c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs new file mode 100755 index 0000000..7105608 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + internal abstract class DomainTupleEnumeratorBase : + IEnumerator, + IEnumerator + { + private IList domains; + public DomainTupleEnumeratorBase(IList domains) + { + if (domains == null) + throw new ArgumentNullException("domains"); + this.domains = domains; + foreach(IDomain domain in domains) + { + if (domain.Count == 0) + throw new ArgumentException("A domain is empty"); + } + } + + public IList Domains + { + get + { + return this.domains; + } + } + + public abstract void Reset(); + public abstract bool MoveNext(); + public abstract ITuple Current {get;} + + Object IEnumerator.Current + { + get + { + return this.Current; + } + } + + public virtual void Dispose() + { + this.domains = null; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs.meta new file mode 100644 index 0000000..3fbf29b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/DomainTupleEnumeratorBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bbafa5dfeb40e46808c7a1153f7cde0f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs new file mode 100755 index 0000000..1e40f5a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + public static class Domains + { + public static EmptyDomain Empty + { + get + { + return new EmptyDomain(); + } + } + + public static BooleanDomain Boolean + { + get { return new BooleanDomain(); } + } + + public static bool IsUniform(IList domains) + { + if (domains == null) + throw new ArgumentNullException("domains"); + + int maxCount = int.MinValue; + int minCount = int.MaxValue; + foreach (IDomain domain in domains) + { + maxCount = Math.Max(maxCount, domain.Count); + minCount = Math.Max(minCount, domain.Count); + if (maxCount != minCount) + return false; + } + return true; + } + + public static IList Uniformize(params Object[] domains) + { + return Uniformize(ToDomains(domains)); + } + + public static IList Uniformize(params ICollection[] domains) + { + return Uniformize(ToDomains(domains)); + } + + public static IList Uniformize(params IEnumerable[] domains) + { + return Uniformize(ToDomains(domains)); + } + + public static IList Uniformize(IList domains) + { + if (domains == null) + throw new ArgumentNullException("domains"); + + Random rnd = new Random((int)DateTime.Now.Ticks); + // find max + int maxCount = int.MinValue; + int minCount = int.MaxValue; + foreach (IDomain domain in domains) + { + maxCount = Math.Max(maxCount, domain.Count); + minCount = Math.Max(minCount, domain.Count); + } + + if (minCount == maxCount) + return domains; + + IList udomains = new List(); + foreach (IDomain domain in domains) + { + if (domain.Count == maxCount) + { + udomains.Add(domain); + continue; + } + + Object[] udomain = new Object[maxCount]; + int i; + for(i = 0;i ToDomains(Array array) + { + if (array == null) + throw new ArgumentNullException("array"); + if (array.Length == 0) + throw new ArgumentException("Length is zero", "array"); + IDomain[] domains = new IDomain[array.Length]; + for (int i = 0; i < array.Length; ++i) + domains[i] = ToDomain(array.GetValue(i)); + return new List(domains); + } + + public static IList ToDomains(params Object[] items) + { + if (items.Length == 0) + throw new ArgumentException("Length is zero", "items"); + IList ds = new List(); + foreach (Object domain in items) + ds.Add(ToDomain(domain)); + return ds; + } + + public static IDomain ToDomain(Object item) + { + IDomain domain = item as IDomain; + if (domain != null) + return domain; + + String s = item as String; + if (s != null) + return ToDomain(s); + + Array array = item as Array; + if (array != null) + return ToDomain(array); + + ICollection collection = item as ICollection; + if (collection != null) + return ToDomain(collection); + + IEnumerable enumerable = item as IEnumerable; + if (enumerable != null) + return ToDomain(enumerable); + + return new CollectionDomain(new object[]{item}); + } + + public static IDomain ToDomain(string s) + { + return new StringDomain(s); + } + + public static CollectionDomain ToDomain(ICollection collection) + { + if (collection == null) + throw new ArgumentNullException("collection"); + if (collection.Count == 0) + throw new ArgumentException("Collection is emtpy"); + return new CollectionDomain(collection); + } + + public static CollectionDomain ToDomain(IEnumerable enumerable) + { + if (enumerable == null) + throw new ArgumentNullException("enumerable"); + return new CollectionDomain(enumerable); + } + + public static ArrayDomain ToDomain(T[] items) + { + if (items == null) + throw new ArgumentNullException("items"); + if (items.Length == 0) + throw new ArgumentException("No arguments"); + return new ArrayDomain(items); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs.meta new file mode 100644 index 0000000..3a6d4e6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Domains.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 773687409f9e84f60b5365183031cb20 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs new file mode 100755 index 0000000..ce6fc7a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System; + +namespace QuickGraph.Operations +{ + public sealed class EmptyDomain : IDomain + { + private string name = null; + public EmptyDomain() + {} + + public string Name + { + get + { + return this.name; + } + set + { + this.name=value; + } + } + + public IDomain Boundary + { + get + { + return this; + } + } + + public int Count + { + get + { + return 0; + } + } + + public object this[int i] + { + get + { + throw new InvalidOperationException("Empty domain"); + } + } + + public IEnumerator GetEnumerator() + { + return new ArrayList().GetEnumerator(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs.meta new file mode 100644 index 0000000..bfae1cd --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/EmptyDomain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 698f0b4c8adef47c396b1477903d0a24 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs new file mode 100755 index 0000000..b2111a2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + internal sealed class GreedyTupleEnumerable : IEnumerable + { + private IEnumerable enumerable; + public GreedyTupleEnumerable(IEnumerable enumerable) + { + if (enumerable == null) + throw new ArgumentNullException("enumerable"); + this.enumerable = enumerable; + } + + public IEnumerator GetEnumerator() + { + return new GreedyTupleEnumerator(this.enumerable.GetEnumerator()); + } + + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + private sealed class GreedyTupleEnumerator : IEnumerator + { + private Dictionary tuples = new Dictionary(); + private IEnumerator enumerator; + + public GreedyTupleEnumerator(IEnumerator enumerator) + { + this.enumerator = enumerator; + } + + public void Reset() + { + throw new NotSupportedException(); + } + + public bool MoveNext() + { + while (this.enumerator.MoveNext()) + { + if (this.tuples.ContainsKey(this.Current)) + continue; + this.tuples.Add(this.Current, null); + return true; + } + return false; + } + + public ITuple Current + { + get + { + return this.enumerator.Current; + } + } + + Object System.Collections.IEnumerator.Current + { + get { return this.Current; } + } + + public void Dispose() + { + if (this.enumerator != null) + { + this.enumerator.Dispose(); + this.enumerator = null; + } + this.tuples = null; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs.meta new file mode 100644 index 0000000..7c32599 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/GreedyTupleEnumerator.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ef66e85fd3a134614a8c2cb2bb095a9d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs new file mode 100755 index 0000000..ab891c8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections; + +namespace QuickGraph.Operations +{ + public interface IDomain : IEnumerable + { + string Name { get;set;} + int Count { get;} + Object this[int i] {get;} + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs.meta new file mode 100644 index 0000000..3af810c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/IDomain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57090d0765cc44cf3b06b28a37da8eaa +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs new file mode 100755 index 0000000..cb01fe6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections; + +namespace QuickGraph.Operations +{ + public interface ITuple : IEnumerable, IComparable + { + int Count { get;} + Object this[int i] { get;} + void Add(Object item); + void Concat(ITuple tuple); + + Object[] ToObjectArray(); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs.meta new file mode 100644 index 0000000..2b65204 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITuple.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f6e1cf3ef652941d3b6ed071e0c96274 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs new file mode 100755 index 0000000..60e1b3d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + public interface ITupleEnumeratorFactory + { + IEnumerator Create(ITuple tuple); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs.meta new file mode 100644 index 0000000..d68457c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/ITupleEnumeratorFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c44b161f99524a47b39c6482fda981e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs new file mode 100755 index 0000000..e660e03 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections; + +namespace QuickGraph.Operations +{ + public sealed class LinearInt32Domain : IDomain + { + private IDomain boundary = null; + private string name = null; + private int start; + private int stepCount; + private int step; + + public LinearInt32Domain(int start, int stepCount) + :this(start,stepCount,1) + {} + public LinearInt32Domain(int start, int stepCount,int step) + { + this.start = start; + this.step = step; + this.stepCount = stepCount; + } + + public string Name + { + get + { + return name; + } + + set + { + name = value; + } + } + + public int Count + { + get + { + return this.stepCount; + } + } + + public IDomain Boundary + { + get + { + if (this.boundary == null) + { + this.boundary = new CollectionDomain(new int[] { this[0], this[this.stepCount - 1] }); + } + return this.boundary; + } + } + + public int this[int index] + { + get + { + if (index >= this.stepCount) + throw new ArgumentOutOfRangeException("Index is greater or equal to count"); + return this.start + index * this.step; + } + } + Object IDomain.this[int index] + { + get + { + return this[index]; + } + } + + public IEnumerator GetEnumerator() + { + return new LinearIntEnumerator(this.stepCount, this.stepCount, this.step); + } + + public class LinearIntEnumerator : IEnumerator + { + private int start; + private int step; + private int stepCount; + private int index = -1; + public LinearIntEnumerator(int start, int stepCount,int step) + { + this.start = start; + this.step = step; + this.stepCount = stepCount; + } + + public void Reset() + { + this.index = -1; + } + + public bool MoveNext() + { + this.index++; + return this.index < this.stepCount; + } + + public int Current + { + get + { + if (this.index < 0) + throw new InvalidOperationException("MoveNext was not called"); + if (this.index >= this.stepCount) + throw new InvalidOperationException("Enumeration out of range"); + return this.start + this.index * this.step; + } + } + + Object IEnumerator.Current + { + get + { + return this.Current; + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs.meta new file mode 100644 index 0000000..7155374 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/LinearInt32Domain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 50815a066f93f48ec9c9839b07f3266f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs new file mode 100755 index 0000000..3488d17 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs @@ -0,0 +1,23 @@ +using System; + +namespace QuickGraph.Tests.Operations +{ + /// + /// + /// The QuickGraph.Operations namespace contains classes for building + /// Combinatorial Test suites. + /// + /// + /// The algorithms for generating the covergate suites are extracted + /// from Efficient Algorithms for Generation of Combinatorial Covering Suites, + /// by Adrian Dumitrescu. + /// + /// + internal sealed class NamespaceDoc + { + private NamespaceDoc() + { + + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs.meta new file mode 100644 index 0000000..8fc6972 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/NamespaceDoc.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e515f893fa4c342a5bf81814a1c920c4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs new file mode 100755 index 0000000..0add0da --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections; +using System.Drawing; +using System.Drawing.Imaging; +using System.Reflection; +using System.IO; + +namespace QuickGraph.Operations +{ + public static class OperationsResourceManager + { + public static Image GetImage(string imageName) + { + string resource = String.Format("QuickGraph.Unit.Operations.{0}.png", imageName); + Stream stream = typeof(OperationsResourceManager).Assembly + .GetManifestResourceStream(resource); + if (stream == null) + throw new Exception("Could not find resource " + resource); + Image img = Image.FromStream(stream); + return img; + } + + public static Image GetLogo() + { + return GetImage("operations"); + } + + public static Image GetLogoBanner() + { + return GetImage("operations.banner"); + } + + public static void DumpResources(string path) + { + if (path == null) + path = "."; + + using (Image logo = GetLogo()) + { + logo.Save(Path.Combine(path, "operations.png"), + System.Drawing.Imaging.ImageFormat.Png); + } + + using (Image logo = GetLogoBanner()) + { + logo.Save(Path.Combine(path, "operations.banner.png"), + System.Drawing.Imaging.ImageFormat.Png); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs.meta new file mode 100644 index 0000000..a009df2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/OperationsResourceManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7b39f33846494963b565b4fcd793f33 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs new file mode 100755 index 0000000..c4c9f41 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + internal sealed class PairWizeProductDomainTupleEnumerable : IEnumerable + { + private IList domains; + public PairWizeProductDomainTupleEnumerable(IList domains) + { + if (domains==null) + throw new ArgumentNullException("domains"); + this.domains = domains; + } + + public IList Domains + { + get + { + return this.domains; + } + } + + public IEnumerator GetEnumerator() + { + return new PairWizeProductDomainTupleEnumerator(this.Domains); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + private sealed class PairWizeProductDomainTupleEnumerator : DomainTupleEnumeratorBase + { + public PairWizeProductDomainTupleEnumerator(IList domains) + :base(domains) + { + this.Reset(); + } + + public override void Reset() + { + throw new NotImplementedException(); + } + + public override bool MoveNext() + { + throw new NotImplementedException(); + } + + public override ITuple Current + { + get + { + throw new NotImplementedException(); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs.meta new file mode 100644 index 0000000..a5bd8eb --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/PairWizeProductDomainTupleEnumerable.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a364ebbe9bf648f492d156bb12d72ea +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs new file mode 100755 index 0000000..8a1844c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs @@ -0,0 +1,282 @@ +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + /// + /// A class to generate permutations. + /// + /// + /// + /// This class can generate any sequence of permutation of order . + /// The method returns the next permutation, while + /// can be used to iterates all the rest of the permutations. + /// + /// + /// The permutation can be applied to an array using , it can also + /// be inverted using . + /// + /// + /// This class was extracted from + /// + /// Using Permutations in .NET for Improved Systems Security by + /// Dr. James McCaffrey. + /// + /// + /// + public sealed class Permutation + { + private int[] data = null; + private int order = 0; + + /// + /// Creates a new idenity permutation + /// + /// + /// order of the new permutation + /// + public Permutation(int n) + { + if (n <= 0) + throw new ArgumentOutOfRangeException("n cannot be negative or zero"); + this.data = new int[n]; + for (int i = 0; i < n; ++i) + { + this.data[i] = i; + } + this.order = n; + } + + /// + /// Creates the -th permutation of + /// order . + /// + /// + /// + public Permutation(int n, int k) + { + if (n <= 0) + throw new ArgumentOutOfRangeException("n cannot be negative or zero"); + if (k <= 0) + throw new ArgumentOutOfRangeException("k cannot be negative or zero"); + + this.data = new int[n]; + this.order = this.data.Length; + + // Step #1 - Find factoradic of k + int[] factoradic = new int[n]; + + for (int j = 1; j <= n; ++j) + { + factoradic[n - j] = k % j; + k /= j; + } + + // Step #2 - Convert factoradic to permuatation + int[] temp = new int[n]; + + for (int i = 0; i < n; ++i) + { + temp[i] = ++factoradic[i]; + } + + this.data[n - 1] = 1; // right-most element is set to 1. + + for (int i = n - 2; i >= 0; --i) + { + this.data[i] = temp[i]; + for (int j = i + 1; j < n; ++j) + { + if (this.data[j] >= this.data[i]) + ++this.data[j]; + } + } + for (int i = 0; i < n; ++i) // put in 0-based form + { + --this.data[i]; + } + } // Permutation(n,k) + + private Permutation(int[] a) + { + if (a.Length == 0) + throw new ArgumentException("Order cannot be zero"); + this.data = new int[a.Length]; + a.CopyTo(this.data, 0); + this.order = a.Length; + + this.CheckPermutation(); + } + + /// + /// Gets the order of the permutation + /// + /// + public int Order + { + get + { + return this.order; + } + } + + /// + /// Checks that the permutation is correct + /// + private void CheckPermutation() + { + if (this.data.Length != this.order) + throw new Exception("Data.Length is not equal to the Order"); + + bool[] checks = new bool[this.data.Length]; + for (int i = 0; i < this.order; ++i) + { + if (this.data[i] < 0 || this.data[i] >= this.order) + throw new Exception("Value out of range at index " + i.ToString()); // value out of range + + if (checks[this.data[i]] == true) + throw new Exception("Duplicate value at index " + i.ToString()); // value out of range + checks[this.data[i]] = true; + } + } + + /// + /// Converts the permutation to a string representation. + /// + /// + public override string ToString() + { + StringWriter sb = new StringWriter(); + sb.Write("("); + for (int i = 0; i < this.order; ++i) + { + sb.Write("{0} ", this.data[i]); + } + sb.Write(")"); + + return sb.ToString(); + } + + /// + /// Applis the permutation to the array + /// + /// + /// A array of Length equal + /// to . + /// + /// A new array containing the permutated element of + /// + public T[] ApplyTo(T[] arr) + { + if (arr.Length != this.order) + throw new ArgumentException("array Length is equal to the permutation order"); + + T[] result = new T[arr.Length]; + for (int i = 0; i < result.Length; ++i) + { + result[i] = arr[this.data[i]]; + } + + return result; + } + + public void ApplyTo(IList arr) + { + if (arr.Count != this.order) + throw new ArgumentException("array Count is equal to the permutation order"); + + T[] result = new T[arr.Count]; + for (int i = 0; i < result.Length; ++i) + { + result[i] = arr[this.data[i]]; + } + + for (int i = 0; i < result.Length; ++i) + { + arr[i] = result[i]; + } + } + + /// + /// Creates the inverse of the permutation. + /// + /// + public Permutation Inverse() + { + int[] inverse = new int[this.order]; + + for (int i = 0; i < inverse.Length; ++i) + { + inverse[this.data[i]] = i; + } + + return new Permutation(inverse); + } + + /// + /// Creates the next permutation in lexicographic order. + /// + /// + /// The next instance if there remain any; + /// otherwize a null reference. + /// + public Permutation GetSuccessor() + { + Permutation result = new Permutation(this.order); + + int left, right; + + for (int k = 0; k < result.order; ++k) // Step #0 - copy current data into result + { + result.data[k] = this.data[k]; + } + + left = result.order - 2; // Step #1 - Find left value + while ((result.data[left] > result.data[left + 1]) && (left >= 1)) + { + --left; + } + if ((left == 0) && (this.data[left] > this.data[left + 1])) + return null; + + right = result.order - 1; // Step #2 - find right; first value > left + while (result.data[left] > result.data[right]) + { + --right; + } + + int temp = result.data[left]; // Step #3 - swap [left] and [right] + result.data[left] = result.data[right]; + result.data[right] = temp; + + + int i = left + 1; // Step #4 - order the tail + int j = result.order - 1; + + while (i < j) + { + temp = result.data[i]; + result.data[i++] = result.data[j]; + result.data[j--] = temp; + } + + return result; + } + + /// + /// Gets an enumerable collection of successors. + /// + /// + public IEnumerable GetSuccessors() + { + Permutation current = this.GetSuccessor(); + while (current != null) + { + yield return current; + current = current.GetSuccessor(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs.meta new file mode 100644 index 0000000..add99a6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Permutation.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c5e236d1e54e412a85cd258aa1a8e08 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs new file mode 100755 index 0000000..d12bc7b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + public static class Products + { + #region Helpers + private static void CheckDomains(IList domains) + { + if (domains == null) + throw new ArgumentNullException("domains"); + if (domains.Count == 0) + throw new ArgumentException("domains is empty"); + for (int i = 0; i < domains.Count; ++i) + { + if (domains[i] == null) + throw new ArgumentNullException("Domain[" + i.ToString() + "] is null"); + if (domains[i].Count==0) + throw new ArgumentNullException("Domain[" + i.ToString() + "] is empty"); + } + } + #endregion + + #region Cartesian + public static IEnumerable Cartesian(IList domains) + { + CheckDomains(domains); + + return new CartesianProductDomainTupleEnumerable(domains); + } + + public static IEnumerable Cartesian(params IDomain[] domains) + { + return Cartesian(new List(domains)); + } + + public static IEnumerable Cartesian(params Object[] domains) + { + return Cartesian(Domains.ToDomains(domains)); + } + #endregion + + #region PairWize + public static IEnumerable PairWize(IList domains) + { + CheckDomains(domains); + if (domains.Count <= 2) + return Cartesian(domains); + + if (Domains.IsUniform(domains)) + return new UniformPairWizeProductDomainTupleEnumerable(domains); + else + { + IList udomains = Domains.Uniformize(domains); + return Greedy(new UniformPairWizeProductDomainTupleEnumerable(udomains)); + } + } + public static IEnumerable PairWize(params IDomain[] domains) + { + return PairWize(new List(domains)); + } + public static IEnumerable PairWize(params Object[] domains) + { + return PairWize(Domains.ToDomains(domains)); + } + #endregion + + #region TWize + public static IEnumerable TWize(int tupleSize, IList domains) + { + CheckDomains(domains); + + IList udomains = Domains.Uniformize(domains); + return new UniformTWizeProductDomainTupleEnumerable(udomains, tupleSize); + } + public static IEnumerable TWize(int tupleSize, params IDomain[] domains) + { + return TWize(tupleSize, new List(domains)); + } + public static IEnumerable TWize(int tupleSize, params Object[] domains) + { + return TWize(tupleSize, Domains.ToDomains(domains)); + } + #endregion + + public static IEnumerable Greedy(IEnumerable tuples) + { + if (tuples == null) + throw new ArgumentNullException("tuples"); + return new GreedyTupleEnumerable(tuples); + } + + + public static IEnumerable ComputeTupleProducts( + IList domains, + CombinationType combinationType) + { + switch (combinationType) + { + case CombinationType.PairWize: + return Products.PairWize(domains); + case CombinationType.Cartesian: + return Products.Cartesian(domains); + default: + throw new NotSupportedException(combinationType.ToString()); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs.meta new file mode 100644 index 0000000..46af4db --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Products.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c0716967c37e14096a08712ad51b2442 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs new file mode 100755 index 0000000..6014581 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; + +namespace QuickGraph.Operations +{ + internal sealed class StringDomain : DomainBase + { + private string value; + public StringDomain(string value) + { + this.value = value; + } + public override int Count + { + get { return 1; } + } + public override Object this[int i] + { + get + { + if (i != 0) + throw new ArgumentOutOfRangeException("index out of range"); + return this.value; + } + } + public override IEnumerator GetEnumerator() + { + ArrayList list = new ArrayList(); + list.Add(this.value); + return list.GetEnumerator(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs.meta new file mode 100644 index 0000000..95fd871 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/StringDomain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2b512920955924d3bbe3f6611f980dd8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs new file mode 100755 index 0000000..bc99220 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections; +using System.IO; + +namespace QuickGraph.Operations +{ + public sealed class Tuple : CollectionBase, + ITuple, + IEquatable, + IComparable + { + public Tuple() + {} + + public object this[int index] + { + get + { + return this.List[index]; + } + } + + public void Add(Object o) + { + this.InnerList.Add(o); + } + + public void Concat(ITuple tuple) + { + foreach (Object o in tuple) + this.Add(o); + } + + public override string ToString() + { + StringWriter sw = new StringWriter(); + foreach (object item in this) + sw.Write("{0}, ", item); + return sw.ToString().TrimEnd(',',' '); + } + + // override object.Equals + public bool Equals(ITuple tuple) + { + if (tuple == null) + return false; + return this.CompareTo(tuple) == 0; + } + + // override object.GetHashCode + public override int GetHashCode() + { + int hash = 0; + foreach (object o in this) + { + if (o != null) + hash += o.GetHashCode(); + } + return hash; + } + + public int CompareTo(object tuple) + { + return this.CompareTo(tuple as ITuple); + } + + public int CompareTo(ITuple tuple) + { + if (((object)tuple) == null) + return -1; + if (this.Count < tuple.Count) + return -1; + else if (this.Count > tuple.Count) + return 1; + for (int i = 0; i < this.Count; ++i) + { + int c = Comparer.Default.Compare(this[i], tuple[i]); + if (c != 0) + return c; + } + return 0; + } + + public Object[] ToObjectArray() + { + object[] objs = new object[this.Count]; + this.List.CopyTo(objs, 0); + return objs; + } + } +} + diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs.meta new file mode 100644 index 0000000..136abdf --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/Tuple.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a848add65a005410da63aa80d82ad835 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs new file mode 100755 index 0000000..d71d362 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs @@ -0,0 +1,206 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + public sealed class UniformPairWizeProductDomainTupleEnumerable : + IEnumerable + { + private IList domains; + public UniformPairWizeProductDomainTupleEnumerable(IList domains) + { + if (domains == null) + throw new ArgumentNullException("domains"); + this.domains = domains; + int count = -1; + for (int i = 0; i < domains.Count; ++i) + { + if (domains[i].Count == 0) + throw new ArgumentException("domain count empty", i.ToString()); + if (i == 0) + count = domains[i].Count; + else + { + if (count != domains[i].Count) + throw new ArgumentException("Domains have not uniform size"); + } + } + } + + public IList Domains + { + get + { + return this.domains; + } + } + + public IEnumerator GetEnumerator() + { + return new UniformPairWizeProductDomainTupleEnumerator(this.Domains); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + private sealed class UniformPairWizeProductDomainTupleEnumerator : + DomainTupleEnumeratorBase + { + private int m = -1; + private int domainCount=-1; + private List bipartiteGraphs = null; + private int bipartiteGraphIndex = -1; + private int leftIndex = 0; + private int rightIndex = -1; + private Tuple tuple = null; + + public UniformPairWizeProductDomainTupleEnumerator(IList domains) + :base(domains) + { + this.domainCount = this.Domains[0].Count; + this.Reset(); + } + + public override void Reset() + { + // get number of bipartite graphs + m = (int)Math.Ceiling(Math.Log(this.Domains.Count, 2)); + + // create bipartite graphs + this.bipartiteGraphs = new List(m); + for (int i = 0; i < m; ++i) + { + // create bipartie graph + BipartiteGraph bg = new BipartiteGraph(this.Domains.Count); + this.bipartiteGraphs.Add(bg); + + // do some swapping + if (i>0) + bg.Swap(i-1, bg.Left.Count+i-1); + } + + + this.bipartiteGraphIndex = -1; + this.leftIndex = 0; + this.rightIndex = 0; + this.tuple = null; + } + + public override bool MoveNext() + { + do + { + if (this.leftIndex == this.rightIndex && this.bipartiteGraphIndex < this.bipartiteGraphs.Count) + { + this.bipartiteGraphIndex++; + this.CreateTuple(); + this.bipartiteGraphIndex = this.bipartiteGraphs.Count; + return true; + } + else + { + this.bipartiteGraphIndex++; + if (this.bipartiteGraphIndex < this.bipartiteGraphs.Count) + { + this.CreateTuple(); + return true; + } + } + + // increasing index + this.rightIndex++; + if (this.rightIndex >= this.domainCount) + { + this.leftIndex++; + this.rightIndex = 0; + } + this.bipartiteGraphIndex = -1; + } while (this.leftIndex < this.domainCount && this.rightIndex < this.domainCount); + + return false; + } + + private void CreateTuple() + { + // get bipartite graph + BipartiteGraph bg = (BipartiteGraph)this.bipartiteGraphs[this.bipartiteGraphIndex]; + + this.tuple = new Tuple(); + for (int i = 0; i < this.Domains.Count; ++i) + { + if (bg.Left.ContainsKey(i)) + this.tuple.Add(this.Domains[i][leftIndex]); + else + this.tuple.Add(this.Domains[i][rightIndex]); + } + } + + public override ITuple Current + { + get + { + return this.tuple; + } + } + + private sealed class BipartiteGraph + { + private SortedList left = new SortedList(); + private SortedList right = new SortedList(); + + public BipartiteGraph(int count) + { + int middle = count / 2 + count%2; + int i = 0; + for (i = 0; i < middle; ++i) + { + left.Add(i, i); + } + for (; i < count; ++i) + right.Add(i, i); + } + + public void Swap(int i, int j) + { + left.Remove(i); + right.Remove(j); + left.Add(j, j); + right.Add(i, i); + } + + public SortedList Left + { + get + { + return this.left; + } + } + public SortedList Right + { + get + { + return this.right; + } + } + + public override string ToString() + { + StringWriter sw = new StringWriter(); + sw.Write("["); + foreach (object o in this.Left.Keys) + sw.Write("{0} ",o); + sw.Write("] ["); + foreach (object o in this.Right.Keys) + sw.Write("{0} ", o); + sw.Write("]"); + return sw.ToString(); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs.meta new file mode 100644 index 0000000..94305e7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformPairWizeProductDomainTupleEnumerable.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cc8c3b202bb794c859f89c05b3463c86 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs new file mode 100755 index 0000000..e51d63f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Operations +{ + public sealed class UniformTWizeProductDomainTupleEnumerable : + IEnumerable + { + private IList domains; + private int tupleSize; + public UniformTWizeProductDomainTupleEnumerable(IList domains, int tupleSize) + { + if (domains == null) + throw new ArgumentNullException("domains"); + if (tupleSize <= 0) + throw new ArgumentOutOfRangeException("tupleSize is negative or zero"); + + this.domains = domains; + this.tupleSize = tupleSize; + + int count = -1; + for (int i = 0; i < domains.Count; ++i) + { + if (i == 0) + count = domains[i].Count; + else + { + if (count != domains[i].Count) + throw new ArgumentException("Domains have not uniform size"); + } + } + } + + public IList Domains + { + get + { + return this.domains; + } + } + + public IEnumerator GetEnumerator() + { + return new UniformTWizeProductDomainTupleEnumerator(this.Domains, this.tupleSize); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + internal sealed class UniformTWizeProductDomainTupleEnumerator : + DomainTupleEnumeratorBase + { + private int tupleSize; + public UniformTWizeProductDomainTupleEnumerator(IList domains, int tupleSize) + :base(domains) + { + this.tupleSize = tupleSize; + this.CreateColoring(); + } + + public override void Reset() + { + throw new NotImplementedException(); + } + public override bool MoveNext() + { + throw new NotImplementedException(); + } + public override ITuple Current + { + get { throw new NotImplementedException(); } + } + + private void CreateColoring() + { + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs.meta new file mode 100644 index 0000000..93c2e72 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/UniformTWizeProductDomainTupleEnumerable.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 52e558d5ed1554b34a6192e7f5c91fb5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.banner.png b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.banner.png new file mode 100755 index 0000000000000000000000000000000000000000..672a2eb4c063c6f1b5328d8b13293baecb13c975 GIT binary patch literal 11013 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 literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.png.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.png.meta new file mode 100644 index 0000000..d25a259 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Operations/operations.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: d01713dfddf994b7392cef6a2fc8d3ce +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs new file mode 100755 index 0000000..48072be --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=true)] + public sealed class PerfMonitorAttribute : TestDecoratorAttributeBase + { + private string categoryName; + private string counterName; + private float valueDelta; + private bool relativeDelta = true; + + public PerfMonitorAttribute( + string categoryName, + string counterName, + float valueDelta + ) + { + this.categoryName = categoryName; + this.counterName = counterName; + this.valueDelta = valueDelta; + } + + public string CategoryName + { + get { return this.categoryName; } + set { this.categoryName = value; } + } + + public string CounterName + { + get { return this.counterName; } + set { this.counterName = value; } + } + + public float ValueDelta + { + get { return this.valueDelta; } + set { this.valueDelta = value; } + } + + public bool RelativeDelta + { + get { return this.relativeDelta; } + set { this.relativeDelta = value; } + } + + public override ITestCase Decorate(ITestCase testCase) + { + return new PerfMonitorTestCase(testCase, this); + } + + private sealed class PerfMonitorTestCase : TypeDecoratorTestCaseBase + { + public PerfMonitorTestCase(ITestCase testCase, PerfMonitorAttribute attribute) + :base(testCase, attribute) + {} + + public override void Run(object fixture) + { + using(PerformanceCounter counter = new PerformanceCounter( + this.Attribute.CategoryName, + this.Attribute.CounterName, + true)) + { + float startValue = counter.NextValue(); + Console.WriteLine( + "[start] {0}/{1}: {2} [{3}]", + this.Attribute.CategoryName, + this.Attribute.CounterName, + startValue, + counter.CounterType + ); + this.TestCase.Run(fixture); + float endValue = counter.NextValue(); + Console.WriteLine( + "[end] {0}/{1}: {2} [{3}]", + this.Attribute.CategoryName, + this.Attribute.CounterName, + endValue, + counter.CounterType + ); + + float delta = Math.Abs(endValue - startValue) ; + if (this.Attribute.RelativeDelta) + delta /= Math.Abs(startValue); + + if (delta > this.Attribute.ValueDelta) + Assert.Fail("{0}/{1} value delta ({2}) is greater than accepted threshold ({3})", + this.Attribute.CategoryName, + this.Attribute.CounterName, + this.Attribute.ValueDelta, + delta); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs.meta new file mode 100644 index 0000000..bf39266 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/PerfMonitorAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a984c64a8eb3483084a219d08ac898f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex.meta new file mode 100644 index 0000000..8d4502e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 514502fe4eb32445792adb6e0ada3eb7 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs new file mode 100755 index 0000000..5ad18db --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Pex.Framework.Packages; +using QuickGraph.Unit.Pex; + +[assembly: QuickGraphTestFramework] + +namespace QuickGraph.Unit.Pex +{ + public sealed class QuickGraphPackageAttribute : + PexPackageAssemblyAttribute + { + public QuickGraphPackageAttribute() + :base(typeof(QuickGraphPackageAttribute)) + { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs.meta new file mode 100644 index 0000000..416e386 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphPackageAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 404e4b573b9264bff9213f7d310a05b1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs new file mode 100755 index 0000000..6c3afb4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Pex.Framework.TestFrameworks; +using Microsoft.Pex.Engine.TestFrameworks; +using Microsoft.Pex.Engine.ComponentModel; +using Microsoft.ExtendedReflection.Metadata.Names; +using Microsoft.ExtendedReflection.Metadata; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Pex +{ + class QuickGraphTestFrameworkAttribute : + PexTestFrameworkAttributeBase + { + protected override IPexTestFramework CreateTestFramework(IPexComponent host) + { + return new TestFramework(host); + } + + class TestFramework : + AttributeBasedTestFrameworkBase + { + public TestFramework(IPexComponent host) + :base(host) + {} + + public override ShortAssemblyName AssemblyName + { + get { return ShortAssemblyName.FromAssembly(typeof(QuickGraph.IEdge<>).Assembly); } + } + + public override TypeName AssertionExceptionType + { + get { return Metadata.SerializableName; } + } + + public override TypeName FixtureAttribute + { + get { return Metadata.SerializableName; } + } + + public override TypeName FixtureSetUpAttribute + { + get { return Metadata.SerializableName; } + } + + protected override string GetHintPath(string assemblyName) + { + return null; + } + + public override string RootNamespace + { + get { return "QuickGraph.Unit"; } + } + + public override bool FixtureSetUpTearDownInstance + { + get { return false; } + } + + public override bool SupportsPartialClasses + { + get { return true; } + } + + public override TypeName FixtureTearDownAttribute + { + get { return Metadata.SerializableName; } + } + + public override TypeName IgnoreAttribute + { + get { return Metadata.SerializableName; } + } + + public override TypeName AssumptionExceptionType + { + get { return Metadata.SerializableName; } + } + + public override TypeName ExpectedExceptionAttribute + { + get { return Metadata.SerializableName; } + } + + protected override string IgnoreMessageProperty + { + get { return "Message"; } + } + + public override string Name + { + get { return "QuickGraph"; } + } + + public override TypeName SetUpAttribute + { + get { return Metadata.SerializableName; } + } + + public override bool IsFixture(TypeDefinition target) + { + return AttributeHelper.IsDefined( + target, + Metadata.Type); + } + + public override bool IsTest(MethodDefinition method) + { + return AttributeHelper.IsDefined( + method, + Metadata.Type); + } + + public override TypeName TearDownAttribute + { + get { return Metadata.SerializableName; } + } + + public override TypeName TestAttribute + { + get { return Metadata.SerializableName; } + } + + protected override bool TryGetCategories( + ICustomAttributeProviderEx element, + out IEnumerable names) + { + names = new string[] { }; + return false; + } + + public override bool TryGetAssemblySetupTeardownMethods(AssemblyEx assembly, out Method setup, out Method teardown) + { + setup = teardown = null; + return false; + } + + protected override string ExpectedExceptionProperty + { + get { return "ExpectedExceptionType"; } + } + + protected override bool HasIgnoreAttributeMessage + { + get { return true; } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs.meta new file mode 100644 index 0000000..4a44795 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Pex/QuickGraphTestFramework.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: afbb58fe197fe4372ba76c81b04fd46c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs new file mode 100755 index 0000000..25fd16c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs @@ -0,0 +1,228 @@ +using System.Collections; +using System.Collections.Specialized; +using System; +using System.Diagnostics; +using System.IO; + +namespace QuickGraph.Unit +{ + public class ProcessTester : IDisposable + { + private string fileName; + private string[] args; + private int expectedExitCode = 0; + private int exitCode; + private bool throwOnWrongExitCode = true; + private int timeOut = int.MaxValue; + private Process process; + private bool useShellExecute = false; + private bool redirectConsole = true; + private string consoleOut; + private string consoleError; + private bool dumpConsoleOnSuccess = false; + private StringDictionary environmentVariables = new StringDictionary(); + + public static void StartAndRun(string fileName, params string[] args) + { + using (ProcessTester tester = new ProcessTester(fileName, args)) + { + tester.ThrowOnWrongExitCode = false; + tester.Run(); + } + } + + public static void StartAndRun(string fileName, int exitCode, params string[] args) + { + using (ProcessTester tester = new ProcessTester(fileName, args)) + { + tester.ExpectedExitCode = exitCode; + tester.Run(); + } + } + + public ProcessTester() + { } + + public ProcessTester( + string fileName, + params string[] args) + { + if (fileName == null) + throw new ArgumentNullException("fileName"); + this.fileName = fileName; + this.args = args; + } + + public void Dispose() + { + if (this.process != null) + { + if (!this.process.HasExited) + this.process.Kill(); + this.process.Dispose(); + this.process = null; + GC.SuppressFinalize(this); + } + } + + public string ConsoleOut + { + get + { + return this.consoleOut; + } + } + + public string ConsoleError + { + get + { + return this.consoleError; + } + } + + public bool UseShellExecute + { + get { return this.useShellExecute; } + set { this.useShellExecute = value; } + } + + public bool DumpConsoleOnSuccess + { + get { return this.dumpConsoleOnSuccess; } + set { this.dumpConsoleOnSuccess = value; } + } + + public StringDictionary EnvironmentVariables + { + get { return this.environmentVariables; } + } + + public bool ThrowOnWrongExitCode + { + get { return this.throwOnWrongExitCode; } + set { this.throwOnWrongExitCode = value; } + } + + public int ExitCode + { + get { return this.exitCode; } + } + + public int ExpectedExitCode + { + get { return this.expectedExitCode; } + set { this.expectedExitCode = value; } + } + + public int TimeOut + { + get { return this.timeOut; } + set { this.timeOut = value; } + } + + public bool RedirectConsole + { + get { return this.redirectConsole; } + set { this.redirectConsole = value; } + } + + public string GetArguments() + { + StringWriter sw = new StringWriter(); + foreach (string arg in this.args) + sw.Write(" {0} ", arg); + return sw.ToString(); + } + + public bool Run(string fileName, params string[] args) + { + if (string.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + this.fileName = fileName; + this.args = args; + + return this.Run(); + } + + public bool Run() + { + ProcessStartInfo info = new ProcessStartInfo( + this.fileName, + this.GetArguments() + ); + info.CreateNoWindow = true; + info.UseShellExecute = this.UseShellExecute; + if (!this.UseShellExecute && this.RedirectConsole) + { + info.RedirectStandardOutput = true; + info.RedirectStandardError = true; + this.consoleError = ""; + this.consoleOut = ""; + } + else + { + info.RedirectStandardOutput = false; + info.RedirectStandardError = false; + } + foreach (DictionaryEntry de in this.EnvironmentVariables) + info.EnvironmentVariables.Add((string)de.Key, (string)de.Value); + + Console.WriteLine("\"{0}\" {1}", info.FileName, info.Arguments); + + this.process = Process.Start(info); + this.process.Start(); + + // getting console output + if (!this.UseShellExecute && this.RedirectConsole) + { + this.consoleOut += this.process.StandardOutput.ReadToEnd(); + this.consoleError += this.process.StandardError.ReadToEnd(); + } + + bool timedOut = process.WaitForExit(this.TimeOut); + this.process.Refresh(); + + // kill process if necessary + if (!process.HasExited) + process.Kill(); + + // getting console output + if (!this.UseShellExecute && this.RedirectConsole) + { + this.consoleOut += this.process.StandardOutput.ReadToEnd(); + this.consoleError += this.process.StandardError.ReadToEnd(); + } + + // check time out + if (!timedOut) + { + this.DumpConsoles(); + Assert.Fail("Process timed out"); + } + + // check return value + this.exitCode = process.ExitCode; + + if (this.ExitCode!= this.ExpectedExitCode || this.DumpConsoleOnSuccess) + this.DumpConsoles(); + + if (this.ThrowOnWrongExitCode) + { + Assert.AreEqual(this.ExpectedExitCode, this.ExitCode, + "Process ExitCode ({0}) does not match expected ExitCode ({1})", + this.ExitCode, this.ExpectedExitCode); + } + + return this.ExitCode == this.ExpectedExitCode; + } + + private void DumpConsoles() + { + if (!string.IsNullOrEmpty(this.ConsoleOut)) + Console.Out.WriteLine(this.ConsoleOut); + if (!string.IsNullOrEmpty(this.ConsoleError)) + Console.Error.WriteLine(this.ConsoleError); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs.meta new file mode 100644 index 0000000..ed95fa9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ProcessTester.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82faf2b596a3f4ef1ab3eaf2c8c0be52 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties.meta new file mode 100644 index 0000000..24b250b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 8bf43ae52321446e08721156c83c91c5 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..96d9a15 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Xml.Serialization; + +// 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("QuickGraph.Unit")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Home")] +[assembly: AssemblyProduct("QuickGraph.Unit")] +[assembly: AssemblyCopyright("Copyright Microsoft 2005")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..6f15f63 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b6425ec2682f548b587d2c01a8266e25 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj new file mode 100755 index 0000000..21411ed --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj @@ -0,0 +1,354 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {9FF2B839-743F-4A15-9D33-F11253BF6AE1} + Library + Properties + QuickGraph.Unit + QuickGraph.Unit + quickgraph.snk + File + true + SAK + SAK + SAK + SAK + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + Off + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Off + + + + False + + + False + + + + + + + + + + + + + Properties\version.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Component + + + + + + Component + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Component + + + Component + + + Component + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Component + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + + + + + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {A9A5C115-0680-44B3-A87E-5ECF4C93814E} + QuickGraph + + + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.meta new file mode 100644 index 0000000..3ec09f5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 513f9685eb9534da4aa15534eaad73c6 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc new file mode 100755 index 0000000..feffdec --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc.meta new file mode 100644 index 0000000..6d270be --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/QuickGraph.Unit.csproj.vspscc.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 54d12a41335dc45d692a0c7b4ba13420 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs new file mode 100755 index 0000000..eddd47a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; + +namespace QuickGraph.Unit +{ + public static class ReflectionAssert + { + public static void IsInstanceOfType(Type left, object value) + { + Assert.IsTrue(left.IsInstanceOfType(value), + "{0} is not an instance of type {1}", left, value.GetType()); + } + + public static void IsAssignableFrom(Type left, Type right) + { + Assert.IsTrue(left.IsAssignableFrom(right), + "Type {0} is not assignable from {1}", left,right); + } + + public static void IsSealed(Type type) + { + Assert.IsTrue(type.IsSealed, + "Type {0} is not sealed", type); + } + + public static void HasConstructor(Type type, params Type[] parameterTypes) + { + Assert.IsNotNull( + type.GetConstructor(parameterTypes), + "Type {0} has no suitable constructor", type); + } + + public static void IsTaggedWithAttribute( + ICustomAttributeProvider type, + Type attributeType, + bool inherit) + { + Object[] attributes = type.GetCustomAttributes(attributeType, inherit); + if (attributes == null || attributes.Length == 0) + Assert.Fail( + "{0} is not tagged with {1}", type, attributeType); + } + + public static void DisplayType(Type type) + { + Console.WriteLine("FullName: {0}", type.FullName); + Console.WriteLine("Base: {0}", type.BaseType); + Type[] interfaceTypes = type.GetInterfaces(); + Console.WriteLine("Interfaces ({0}):", interfaceTypes.Length); + foreach (Type interfaceType in interfaceTypes) + Console.WriteLine("\t{0}", interfaceType); + + ConstructorInfo[] constructors = type.GetConstructors(); + Console.WriteLine("Constructors ({0}):", constructors.Length); + foreach (ConstructorInfo constructor in constructors) + { + Console.WriteLine("\t{0}({1})", constructor.Name, + ParametersToString(constructor.GetParameters()) + ); + } + + MethodInfo[] methods = type.GetMethods(); + Console.WriteLine("Methods ({0}):", methods.Length); + foreach (MethodInfo method in methods) + { + Console.WriteLine("\t{0}({1})", method.Name, + ParametersToString(method.GetParameters()) + ); + } + } + + public static string ParametersToString(ParameterInfo[] parameters) + { + using (StringWriter writer = new StringWriter()) + { + foreach (ParameterInfo parameter in parameters) + writer.Write(",{0} {1}", parameter.ParameterType, parameter.Name); + + return String.Format("{0}", writer.ToString().TrimStart(',')); + } + } + + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs.meta new file mode 100644 index 0000000..34b3f16 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ReflectionAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c2625c8e48c2d49c49f195a4b7d75aa7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs new file mode 100755 index 0000000..c78d6a4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=true, Inherited=true)] + public sealed class RepeatAttribute : TestDecoratorAttributeBase + { + private int count = 1; + + public RepeatAttribute() + { } + + public RepeatAttribute(int count) + { + this.count = count; + } + + public int Count + { + get { return this.count; } + set { this.count = value; } + } + + public override ITestCase Decorate(ITestCase testCase) + { + return new RepeatTestCase(testCase, this); + } + + private sealed class RepeatTestCase : TypeDecoratorTestCaseBase + { + public RepeatTestCase(ITestCase testCase, RepeatAttribute attribute) + : base(testCase, attribute) + { } + + public override void Run(object fixture) + { + for (int i = 0; i < this.Attribute.count; ++i) + { + this.TestCase.Run(fixture); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs.meta new file mode 100644 index 0000000..57207fa --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RepeatAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0fa097940f9aa4f909d9f05bebb42d66 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports.meta new file mode 100644 index 0000000..19e0828 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: f891b7cc385814b439cbb14ba586fd5c +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs new file mode 100755 index 0000000..6d4e071 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs @@ -0,0 +1,97 @@ +using System; +using System.IO; +using System.Diagnostics; +using System.ComponentModel; +using System.Xml; + +namespace QuickGraph.Unit.Reports +{ + public abstract class FileReportBase : ReportBase + { + private string outputFolderName = null; + private string defaultFileExtension; + private string outputFileName; + private bool displayOnDisposed = false; + + public FileReportBase( + IContainer container, + string defaultFileExtension + ) + : base(container) + { + this.defaultFileExtension = defaultFileExtension.ToLower(); + } + + public bool DisplayOnDisposed + { + get { return this.displayOnDisposed; } + set { this.displayOnDisposed = value; } + } + + public string OutputFolderName + { + get { return this.outputFolderName; } + } + + public void SetOutputFolderName(string path, string testAssemblyName) + { + string folderName = ReportPath.GetName(testAssemblyName,this.CreationTime); + SetOutputFolderName(Path.Combine(path, folderName)); + } + + public void SetOutputFolderName(string outputFolderName) + { + this.outputFolderName = Path.GetFullPath(outputFolderName); + } + + public string DefaultFileExtension + { + get { return this.defaultFileExtension; } + } + + public string OutputFileName + { + get { return this.outputFileName; } + } + + public override void Generate() + { + Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFileName)); + using (StreamWriter swriter = new StreamWriter(this.OutputFileName)) + { + this.Generate(swriter); + } + } + + public abstract void Generate(TextWriter writer); + + public virtual void SetOutputFileName(string outputFileName) + { + this.outputFileName = outputFileName.Replace('.', '_'); + if (!this.OutputFileName.ToLower().EndsWith('.' + this.DefaultFileExtension)) + this.outputFileName += '.' + this.DefaultFileExtension; + + this.outputFileName = ReportPath.EscapeFileName(this.outputFileName); + if (!String.IsNullOrEmpty(this.OutputFolderName)) + this.outputFileName = Path.Combine( + this.OutputFolderName, + this.OutputFileName); + + this.outputFileName = Path.GetFullPath(this.OutputFileName); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + if (this.DisplayOnDisposed && this.OutputFileName != null) + { + System.Diagnostics.Process.Start(this.OutputFileName); + this.DisplayOnDisposed = false; + } + } + } + + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs.meta new file mode 100644 index 0000000..0a97567 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/FileReportBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b27f0a7cd85654e31a9b6dc7278054d7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs new file mode 100755 index 0000000..5ec6e95 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using System.Diagnostics; +using System.ComponentModel; + +namespace QuickGraph.Unit.Reports +{ + public abstract class ReportBase : Component + { + private bool generateOnDisposed = false; + private DateTime creationTime = DateTime.Now; + + public ReportBase(IContainer container) + { + container.Add(this); + } + + public DateTime CreationTime + { + get + { + return this.creationTime; + } + } + + public abstract void Generate(); + + public bool GenerateOnDisposed + { + get { return this.generateOnDisposed; } + set { this.generateOnDisposed = value; } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing && this.GenerateOnDisposed) + { + this.Generate(); + this.GenerateOnDisposed = false; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs.meta new file mode 100644 index 0000000..a805422 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 87ab06c7bfb3f43c390700e5bcbecd90 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs new file mode 100755 index 0000000..1526caf --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Reports +{ + public sealed class ReportCleaner + { + private Regex pattern; + private int maxReportCount = 25; + + public ReportCleaner(string testAssemblyName) + { + this.pattern = ReportPath.GetRegex(testAssemblyName); + } + + public int MaxReportCount + { + get { return this.maxReportCount; } + set { this.maxReportCount = value; } + } + + public void Clean(string path, TestRunner runner) + { + // to do implement + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs.meta new file mode 100644 index 0000000..e7854f0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportCleaner.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc2517e30c7b34bdeb47d2487b049095 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs new file mode 100755 index 0000000..5227884 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs @@ -0,0 +1,99 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Xml; +using System.Xml.XPath; + +namespace QuickGraph.Unit.Reports +{ + public sealed class ReportHistory + { + private string reportOutputPath; + private string testAssemblyName; + + public ReportHistory(string reportOutputPath, string testAssemblyName) + { + this.reportOutputPath = reportOutputPath; + this.testAssemblyName = testAssemblyName; + } + + public string ReportOutputPath + { + get { return this.reportOutputPath; } + } + + public string TestAssemblyName + { + get { return this.testAssemblyName; } + } + + public string GetLatestXmlReport() + { + List reports = new List(GetPreviousXmlReports()); + if (reports.Count == 0) + return null; + reports.Sort(new CreationTimeComparer()); + return reports[reports.Count - 1]; + } + + public IEnumerable GetPreviousXmlReports() + { + string searchPattern = String.Format("{0}.html.xml", ReportPath.EscapeAssemblyName(TestAssemblyName)); + searchPattern = ReportPath.EscapeFileName(searchPattern); + // look for the report file + foreach (string xmlreport in Directory.GetFiles( + this.ReportOutputPath, + searchPattern, + SearchOption.AllDirectories + )) + { + yield return xmlreport; + } + } + + public XmlDocument LoadReportHistory() + { + XmlDocument document = new XmlDocument(); + XmlElement root = document.CreateElement("MergedBatch"); + document.AppendChild(root); + XmlElement testBatches = document.CreateElement("TestBatches"); + root.AppendChild(testBatches); + + foreach (string previousResult in this.GetPreviousXmlReports()) + { + try + { + using (StreamReader reader = new StreamReader(previousResult)) + { + XmlDocument previousDocument = new XmlDocument(); + previousDocument.Load(reader); + string path = Path.GetFullPath(previousResult); + path = path.Substring(0, path.Length - ".xml".Length); + previousDocument.DocumentElement.SetAttribute("Path", path); + testBatches.AppendChild( + document.ImportNode(previousDocument.DocumentElement, true) + ); + } + } + catch (XmlException ex) + { + Assert.Logger.LogWarning("Error while loading {0}: {1}", + previousResult, + ex.Message); + } + } + + return document; + } + + private sealed class CreationTimeComparer : IComparer + { + public int Compare(string x, string y) + { + FileInfo fx = new FileInfo(x); + FileInfo fy = new FileInfo(y); + return fx.CreationTime.CompareTo(fy.CreationTime); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs.meta new file mode 100644 index 0000000..3eb25b3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportHistory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 51fc9e30f33674a19b9fb80b9ede7db6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs new file mode 100755 index 0000000..616553a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Reports +{ + public static class ReportPath + { + public static string GetName(string testAssemblyName, DateTime time) + { + return String.Format("{0}_{1}", + EscapeAssemblyName(testAssemblyName), + time.ToString("HHmmss") + ); + } + + internal static Regex GetRegex(string testAssemblyName) + { + string etan = EscapeAssemblyName(testAssemblyName).ToLower(); + return new Regex(etan + @"_\d{5}_\d{6}"); + } + + public static string EscapeFileName(string fileName) + { + return fileName + .Replace(' ', '_') + .Replace('/', '_') + .Replace(':', '_') + .Replace('(', '_') + .Replace(')', '_') + .Replace('[', '_') + .Replace(']', '_') + .Replace('{', '_') + .Replace('}', '_') + ; + } + + public static string EscapeAssemblyName(string assemblyName) + { + return EscapeFileName(assemblyName).Replace('.', '_'); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs.meta new file mode 100644 index 0000000..ad6866d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/ReportPath.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29546e0d4c4c144e5887f12a6eef0469 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs new file mode 100755 index 0000000..6d155fd --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs @@ -0,0 +1,47 @@ +using System; +using System.IO; +using System.Xml; +using System.Xml.XPath; +using System.Xml.Xsl; +using System.ComponentModel; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Reports +{ + public sealed class UnitTestHistoryHtmlReport : XslReportBase + { + private string entryAssemblyName; + + public UnitTestHistoryHtmlReport(IContainer container) + :base(container,"html") + {} + + public string EntryAssemblyName + { + get { return this.entryAssemblyName; } + set { this.entryAssemblyName = value; } + } + + protected override void GenerateXml(XmlTextWriter writer) + { + QuickGraph.Operations.OperationsResourceManager.DumpResources( + Path.GetDirectoryName(this.OutputFileName) + ); + UnitResourceManager.DumpResources( + Path.GetDirectoryName(this.OutputFileName) + ); + ReportHistory history = new ReportHistory( + this.OutputFolderName, this.EntryAssemblyName); + XmlDocument doc = history.LoadReportHistory(); + doc.Save(writer); + } + + protected override void TransformXml(XPathDocument document, XmlTextWriter writer) + { + XsltArgumentList args = new XsltArgumentList(); + + UnitResourceManager.HtmlHistoryReport.Transform(document, args, writer); + writer.Close(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs.meta new file mode 100644 index 0000000..69aa35e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHistoryHtmlReport.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 49846ad7dc5de427691ccb8a01f4b978 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs new file mode 100755 index 0000000..a1a108a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs @@ -0,0 +1,106 @@ +using System; +using System.IO; +using System.Xml; +using System.Xml.Xsl; +using System.Xml.XPath; +using System.Collections.Generic; +using System.ComponentModel; +using QuickGraph.Unit.Serialization; +using QuickGraph.Unit.Listeners; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Reports +{ + public sealed class UnitTestHtmlReport : XslReportBase + { + private XmlTestListener testListener = new XmlTestListener(); + private string entryAssemblyName; + private bool generateFixtureInSeparateFile = false; + private bool showFixturesSummary = true; + + public UnitTestHtmlReport(IContainer container) + :base(container,"html") + {} + + public bool GenerateFixtureInSeparateFile + { + get { return this.generateFixtureInSeparateFile; } + set { this.generateFixtureInSeparateFile = value; } + } + + public bool ShowFixturesSummary + { + get { return this.showFixturesSummary; } + set { this.showFixturesSummary = value; } + } + + public string EntryAssemblyName + { + get { return this.entryAssemblyName; } + set { this.entryAssemblyName = value; } + } + + public XmlTestListener TestListener + { + get { return this.testListener; } + set { this.testListener = value; } + } + + protected override void GenerateXml(XmlTextWriter writer) + { + QuickGraph.Operations.OperationsResourceManager.DumpResources(Path.GetDirectoryName(this.OutputFileName)); + UnitResourceManager.DumpResources(Path.GetDirectoryName(this.OutputFileName)); + UnitSerializer.TestBatchSerializer.Serialize( + writer, + this.TestListener.TestBatch); + } + + protected override void TransformXml(XPathDocument document, XmlTextWriter writer) + { + XsltArgumentList args = new XsltArgumentList(); + args.AddParam("separate-fixtures", "", (this.GenerateFixtureInSeparateFile) ? 1 : 0); + args.AddParam("show-fixtures-summary", "", (this.ShowFixturesSummary) ? 1 : 0); + args.AddParam("creation-time", "", this.CreationTime.ToString("u")); + + if (this.GenerateFixtureInSeparateFile) + this.GenerateFixtureReports(document, args); + + UnitResourceManager.HtmlReport.Transform(document, args, writer); + writer.Close(); + + } + + private void GenerateFixtureReports(XPathDocument document, XsltArgumentList args) + { + Console.WriteLine("Generating fixture reports"); + XPathNavigator navi = document.CreateNavigator(); + foreach (XPathNavigator node in navi.Select("//Fixture")) + { + Console.Write('.'); + string fileName = string.Format( + "{0}_{1}.html", + this.EntryAssemblyName.Replace('.', '_'), + node.GetAttribute("Name", "").Replace('.', '_') + ); + fileName = ReportPath.EscapeFileName(fileName); + fileName = Path.Combine(this.OutputFolderName, fileName); + + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + using (StreamWriter fixtureWriter = new StreamWriter(fileName)) + { + UnitResourceManager.HtmlFixtureReport.Transform(node, args, fixtureWriter); + } + } + catch (Exception ex) + { + Console.WriteLine("Failed generating {0}", fileName); + Console.WriteLine(ex.Message); + } + } + + Console.WriteLine(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs.meta new file mode 100644 index 0000000..34c11f8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/UnitTestHtmlReport.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9bbae41db87d4569958eca396cca9b9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs new file mode 100755 index 0000000..33a4e0a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.Diagnostics; +using System.ComponentModel; +using System.Xml; +using System.Xml.XPath; + +namespace QuickGraph.Unit.Reports +{ + public abstract class XslReportBase : FileReportBase + { + private string outputXmlFileName; + + public XslReportBase( + IContainer container, + string defaultFileExtension) + :base(container,defaultFileExtension) + {} + + public string OutputXmlFileName + { + get { return this.outputXmlFileName; } + } + + public override void SetOutputFileName(string outputFileName) + { + base.SetOutputFileName(outputFileName); + this.outputXmlFileName = this.OutputFileName + ".xml"; + } + + public sealed override void Generate(TextWriter writer) + { + using (StreamWriter xwriter = new StreamWriter(this.OutputXmlFileName)) + { + using (XmlTextWriter xxwriter = new XmlTextWriter(xwriter)) + { + xxwriter.Formatting = Formatting.Indented; + GenerateXml(xxwriter); + } + } + + XPathDocument doc = new XPathDocument(this.OutputXmlFileName); + using (XmlTextWriter xwriter = new XmlTextWriter(writer)) + { + xwriter.Formatting = Formatting.Indented; + TransformXml(doc,xwriter); + } + } + + protected abstract void GenerateXml(XmlTextWriter writer); + protected abstract void TransformXml(XPathDocument document, XmlTextWriter writer); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs.meta new file mode 100644 index 0000000..32259ca --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Reports/XslReportBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7e2e3021a03b4468cbcf64a2a4c91dbe +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs new file mode 100755 index 0000000..361ab64 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs @@ -0,0 +1,30 @@ +using System; +using System.Transactions; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method,AllowMultiple=false, Inherited=true)] + public sealed class RollbackAttribute : TestDecoratorAttributeBase + { + public override ITestCase Decorate(ITestCase testCase) + { + return new RolledbackTestCase(testCase); + } + + private sealed class RolledbackTestCase : DecoratorTestCaseBase + { + public RolledbackTestCase(ITestCase testCase) + :base(testCase) + {} + + public override void Run(Object fixture) + { + using (TransactionScope transactionScope = new TransactionScope()) + { + this.TestCase.Run(fixture); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs.meta new file mode 100644 index 0000000..d43e274 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RollbackAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: af958a6e9c3634c4d984e922c695fe55 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs new file mode 100755 index 0000000..66c7bb5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple=true, Inherited=true)] + public sealed class RowAttribute : Attribute + { + private object[] arguments; + + public RowAttribute(object a1) + { + this.arguments = new object[] { a1 }; + } + public RowAttribute(object a1, object a2) + { + this.arguments = new object[] { a1 , a2}; + } + public RowAttribute(object a1, object a2, object a3) + { + this.arguments = new object[] { a1, a2, a3 }; + } + public RowAttribute(object a1, object a2, object a3, object a4) + { + this.arguments = new object[] { a1, a2, a3,a4 }; + } + public RowAttribute(object a1, object a2, object a3, object a4, object a5) + { + this.arguments = new object[] { a1, a2, a3, a4,a5 }; + } + public RowAttribute(object a1, object a2, object a3, object a4, object a5, object a6) + { + this.arguments = new object[] { a1, a2, a3, a4, a5,a6 }; + } + public RowAttribute(object a1, object a2, object a3, object a4, object a5, object a6, object a7) + { + this.arguments = new object[] { a1, a2, a3, a4, a5, a6,a7 }; + } + public RowAttribute(object a1, object a2, object a3, object a4, object a5, object a6, object a7, object a8) + { + this.arguments = new object[] { a1, a2, a3, a4, a5, a6, a7, a8 }; + } + + public object[] GetArguments() + { + return arguments; + } + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] + public sealed class RowTestAttribute : TestAttributeBase + { + public override IEnumerable CreateTests(IFixture fixture, System.Reflection.MethodInfo method) + { + foreach (RowAttribute rowAttribute in method.GetCustomAttributes(typeof(RowAttribute), true)) + { + yield return new RowTestCase(fixture.Name, method, rowAttribute); + } + } + + public sealed class RowTestCase : MethodTestCase + { + public RowTestCase(string fixtureName, MethodInfo method, RowAttribute row) + :base(fixtureName, method) + { + foreach (object parameter in row.GetArguments()) + { + this.Parameters.Add(new TestCaseParameter(parameter)); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs.meta new file mode 100644 index 0000000..b50b8e3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/RowTestAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 184e8e3faecb54bb999dd757f4a25c68 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization.meta new file mode 100644 index 0000000..9a49124 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: f6b7c621e47574d878eee3234c899fac +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs new file mode 100755 index 0000000..022dd28 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs @@ -0,0 +1,71 @@ +using System; +using System.Xml.Serialization; +using System.IO; +using System.Xml; +using System.Threading; + +namespace QuickGraph.Unit.Serialization +{ + public static class UnitSerializer + { + private static volatile object syncRoot = new object(); + private static XmlSerializer testBatchSerializer = null; + + public static object SyncRoot + { + get { return syncRoot; } + } + + public static string XmlSerializerEscapeWorkAround(string s) + { + char[] array = s.ToCharArray(); + for (int i = 0; i < s.Length; ++i) + { + //#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + char c = array[i]; + if ( + !( + (c>=0x20 && c<=0xD7FF) + ||(c>=0xE000 && c<=0xFFFD) + || c == 0x9 || c==0xA || c==0xD + ) + ) + array[i] = 'x'; + } + return new string(array); + } + + public static XmlSerializer TestBatchSerializer + { + get + { + lock (SyncRoot) + { + if (testBatchSerializer == null) + testBatchSerializer = new XmlSerializer(typeof(XmlTestBatch)); + return testBatchSerializer; + } + } + } + + public static void Serialize(XmlTestBatch instance, string outputFileName) + { + using (StreamWriter sw = new StreamWriter(outputFileName)) + { + using (XmlTextWriter xw = new XmlTextWriter(sw)) + { + xw.Formatting = Formatting.Indented; + TestBatchSerializer.Serialize(xw, instance); + } + } + } + + public static XmlTestBatch Deserialize(string fileName) + { + using (StreamReader reader = new StreamReader(fileName)) + { + return (XmlTestBatch)TestBatchSerializer.Deserialize(reader); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs.meta new file mode 100644 index 0000000..ff84919 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/UnitSerializer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3e65bfda9be7e415a882cbdd5448194b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs new file mode 100755 index 0000000..d7fb626 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs @@ -0,0 +1,83 @@ +using System; +using System.Xml.Serialization; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlCounter + { + private int totalCount = 0; + private int successCount = 0; + private int failureCount = 0; + private int ignoreCount = 0; + private int notRunCount = 0; + + public XmlCounter() + { } + + public static XmlCounter Add(XmlCounter left, XmlCounter right) + { + XmlCounter counter = new XmlCounter(); + counter.TotalCount = left.TotalCount + right.TotalCount; + counter.SuccessCount = left.SuccessCount + right.SuccessCount; + counter.FailureCount = left.FailureCount + right.FailureCount; + counter.IgnoreCount = left.IgnoreCount + right.IgnoreCount; + counter.notRunCount = left.notRunCount + right.notRunCount; + return counter; + } + + public void Update() + { + this.totalCount = this.successCount + this.ignoreCount + this.failureCount + this.notRunCount; + } + + public static XmlCounter operator +(XmlCounter left, XmlCounter right) + { + return Add(left, right); + } + + [XmlAttribute] + public int TotalCount + { + get { return this.totalCount; } + set { this.totalCount = value; } + } + + [XmlAttribute] + public int SuccessCount + { + get { return this.successCount; } + set { this.successCount = value; } + } + + [XmlAttribute] + public int FailureCount + { + get { return this.failureCount; } + set { this.failureCount = value; } + } + + [XmlAttribute] + public int IgnoreCount + { + get { return this.ignoreCount; } + set { this.ignoreCount = value; } + } + + [XmlAttribute] + public int NotRunCount + { + get { return this.notRunCount; } + set { this.notRunCount = value; } + } + + public override string ToString() + { + return String.Format("{0} tests, {1} success, {2} failures, {3} ignored", + this.TotalCount, + this.SuccessCount, + this.FailureCount, + this.IgnoreCount); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs.meta new file mode 100644 index 0000000..b55f57c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlCounter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c1101705f386846f4a65c0e33beaef39 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs new file mode 100755 index 0000000..03681d0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlException + { + private string exceptionType; + private string message; + private string stackTrace; + private string source; + private PropertyCollection properties = new PropertyCollection(); + private XmlException innerException = null; + + public XmlException() + {} + + public static XmlException FromException(Exception exception) + { + if (exception == null) + throw new ArgumentNullException("exception"); + if (exception is System.Reflection.TargetInvocationException) + return FromException(exception.InnerException); + + XmlException xex = new XmlException(); + xex.ExceptionType = exception.GetType().FullName; + xex.Message = UnitSerializer.XmlSerializerEscapeWorkAround(exception.Message); + xex.StackTrace = exception.StackTrace; + xex.Source = exception.Source; + if (exception.InnerException!=null) + xex.InnerException = FromException(exception.InnerException); + + foreach (System.Collections.DictionaryEntry de in exception.Data) + { + xex.Properties.Add(de); + } + + return xex; + } + + [XmlAttribute] + public string Source + { + get { return this.source; } + set { this.source = value; } + } + + [XmlAttribute] + public string ExceptionType + { + get { return this.exceptionType; } + set { this.exceptionType = value; } + } + + [XmlAttribute] + public string Message + { + get { return this.message; } + set { this.message = value; } + } + + [XmlElement] + public string StackTrace + { + get { return this.stackTrace; } + set { this.stackTrace = value; } + } + + [XmlElement] + public XmlException InnerException + { + get { return this.innerException; } + set { this.innerException = value; } + } + + [XmlArray("Properties")] + [XmlArrayItem(typeof(XmlException.Property))] + public PropertyCollection Properties + { + get { return this.properties;} + } + + [Serializable] + public sealed class Property + { + private string name; + private string value; + + [XmlAttribute] + public string Name + { + get { return this.name; } + set { this.name = value; } + } + + [XmlAttribute] + public string Value + { + get { return this.value; } + set { this.value = value; } + } + } + + [Serializable] + public sealed class PropertyCollection : List + { + public void Add(System.Collections.DictionaryEntry de) + { + Property p = new Property(); + p.Name = String.Format("{0}",de.Key); + p.Value = String.Format("{0}",de.Value); + this.Add(p); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs.meta new file mode 100644 index 0000000..4f77d11 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fc9fe251544f54d6bbcceca75f2004a7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs new file mode 100755 index 0000000..4764575 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs @@ -0,0 +1,146 @@ +using System; +using System.Xml.Serialization; +using System.Threading; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlFixture + { + private string id; + private string name; + private string description; + private string categories; + private double duration=0; + private ApartmentState apartment = ApartmentState.Unknown; + private int timeOut = 1; + private XmlCounter counter = new XmlCounter(); + private XmlResult fixtureSetUp = null; + private XmlResult fixtureTearDown = null; + private XmlTestCaseCollection testCases = new XmlTestCaseCollection(); + private int testCaseCount; + + public XmlFixture() + { } + + internal XmlFixture(IFixture fixture, int testCaseCount, string categories, int fixtureIndex) + { + this.Name = fixture.Name; + this.testCaseCount = testCaseCount; + this.Categories = categories; + this.TimeOut = fixture.TimeOut; + this.Apartment = fixture.Apartment; + this.Description = fixture.Description; + this.ID = + String.Format("fix{0}", fixtureIndex); + } + + [XmlAttribute("id")] + public string ID + { + get { return this.id; } + set { this.id = value; } + } + + [XmlElement] + public XmlCounter Counter + { + get { return this.counter; } + set { this.counter = value; } + } + + [XmlAttribute] + public string Name + { + get { return this.name; } + set { this.name = value; } + } + + [XmlAttribute] + public ApartmentState Apartment + { + get { return this.apartment; } + set { this.apartment = value; } + } + + [XmlAttribute] + public int TimeOut + { + get { return this.timeOut; } + set { this.timeOut = value; } + } + + [XmlAttribute] + public string Description + { + get { return this.description; } + set { this.description = value; } + } + + [XmlAttribute] + public string Categories + { + get { return this.categories; } + set { this.categories = value; } + } + + [XmlAttribute] + public double Duration + { + get { return this.duration; } + set { this.duration=value; } + } + + [XmlElement] + public XmlResult FixtureSetUp + { + get { return this.fixtureSetUp; } + set { this.fixtureSetUp = value; } + } + + [XmlElement] + public XmlResult FixtureTearDown + { + get { return this.fixtureTearDown; } + set { this.fixtureTearDown = value; } + } + + [XmlArray("TestCases")] + [XmlArrayItem("TestCase",typeof(XmlTestCase))] + public XmlTestCaseCollection TestCases + { + get { return this.testCases; } + } + + public void UpdateCounter() + { + this.counter = new XmlCounter(); + // the fixture setup/teardown run and failed ? + if ((this.FixtureSetUp != null && this.FixtureSetUp.State != TestState.Success) + || (this.FixtureTearDown != null && this.FixtureTearDown.State != TestState.Success) + ) + { + this.counter.FailureCount = this.testCaseCount; + } + else + { + foreach (XmlTestCase test in this.TestCases) + { + switch (test.State) + { + case TestState.Success: this.counter.SuccessCount++; + break; + case TestState.Failure: this.counter.FailureCount++; + break; + case TestState.Ignore: this.counter.IgnoreCount++; + break; + case TestState.NotRun: this.counter.NotRunCount++; + break; + } + } + } + this.counter.Update(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs.meta new file mode 100644 index 0000000..5a3cd37 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixture.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 640479c625af14dd4b53e1051b75f3bb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs new file mode 100755 index 0000000..6becf99 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlFixtureCollection : List + { + private XmlCounter counter = new XmlCounter(); + + [XmlElement] + public XmlCounter Counter + { + get { return this.counter; } + set { this.counter = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs.meta new file mode 100644 index 0000000..fd56e5c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlFixtureCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 048c4cdbba9664c26a8e1acde3289999 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs new file mode 100755 index 0000000..ab149ad --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs @@ -0,0 +1,18 @@ +using System; +using System.Xml.Serialization; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlLog + { + private XmlLogEntryCollection logEntries = new XmlLogEntryCollection(); + + [XmlArray] + [XmlArrayItem("LogEntry")] + public XmlLogEntryCollection LogEntries + { + get { return this.logEntries; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs.meta new file mode 100644 index 0000000..9817088 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLog.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b475be0b4be34f7aa373ce21102c33c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs new file mode 100755 index 0000000..3f3a7c3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs @@ -0,0 +1,63 @@ +using System; +using System.Xml.Serialization; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlLogEntry + { + private LogLevel level = LogLevel.Message; + private DateTime time; + private string message; + private XmlException exception; + + public XmlLogEntry() + { + this.time = DateTime.Now; + } + + public XmlLogEntry( + LogLevel level, + string message + ) + { + this.level = level; + this.message = message; + } + + public XmlLogEntry(Exception ex) + { + this.level = LogLevel.Error; + this.message = ex.Message; + this.exception = XmlException.FromException(ex); + } + + [XmlAttribute] + public LogLevel Level + { + get { return this.level; } + set { this.level = value; } + } + + [XmlAttribute] + public DateTime Time + { + get { return this.time; } + set { this.time = value; } + } + + [XmlAttribute] + public string Message + { + get { return this.message; } + set { this.message = value; } + } + + [XmlElement] + public XmlException Exception + { + get { return this.exception; } + set { this.exception = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs.meta new file mode 100644 index 0000000..340e487 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntry.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f397b40a3d98d412dad8c07cc44f96e4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs new file mode 100755 index 0000000..6274aa4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlLogEntryCollection : List + { + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs.meta new file mode 100644 index 0000000..c62a2ae --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlLogEntryCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 96a7205423b644cbfbdf2010e37bd355 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs new file mode 100755 index 0000000..df10036 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs @@ -0,0 +1,97 @@ +using System; +using System.Xml.Serialization; +using System.Diagnostics; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlMachine + { + private string machineName; + private string frameworkVersion; + private string operatingSystem; + private EnvironmentVariableCollection environmentVariables = new EnvironmentVariableCollection(); + + public static XmlMachine Create() + { + XmlMachine machine = new XmlMachine(); + + machine.MachineName = Environment.MachineName; + machine.FrameworkVersion = Environment.Version.ToString(); + machine.OperatingSystem = Environment.OSVersion.VersionString; + + foreach (System.Collections.DictionaryEntry de in Environment.GetEnvironmentVariables()) + { + machine.EnvironmentVariables.Add( + new EnvironmentVariable(String.Format("{0}",de.Key), String.Format("{0}",de.Value)) + ); + } + + return machine; + } + + [XmlAttribute] + public string MachineName + { + get { return this.machineName; } + set { this.machineName = value; } + } + + [XmlAttribute] + public string FrameworkVersion + { + get { return this.frameworkVersion; } + set { this.frameworkVersion = value; } + } + + [XmlAttribute] + public string OperatingSystem + { + get { return this.operatingSystem; } + set { this.operatingSystem = value; } + } + + [XmlArray("EnvironmentVariables")] + [XmlArrayItem("EnvironmentVariable")] + public EnvironmentVariableCollection EnvironmentVariables + { + get { return this.environmentVariables; } + } + + [Serializable] + public sealed class EnvironmentVariableCollection : List + {} + + [Serializable] + public sealed class EnvironmentVariable + { + private string name; + private string value; + + public EnvironmentVariable() { } + public EnvironmentVariable( + string name, + string value + ) + { + this.name = name; + this.value = value; + } + + [XmlAttribute] + public string Name + { + get { return this.name; } + set { this.name = value; } + } + + [XmlAttribute] + public string Value + { + get { return this.value; } + set { this.value = value; } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs.meta new file mode 100644 index 0000000..0f83792 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMachine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fe8cceaa6e700424d86babed4ceb6f4c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs new file mode 100755 index 0000000..be8e287 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using QuickGraph.Unit.Monitoring; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public class XmlMonitor + { + private string consoleOut; + private string consoleError; + private string startTime; + private string endTime; + private double duration; + private XmlLog log = new XmlLog(); + + public XmlMonitor() + {} + + public XmlMonitor(TestMonitor monitor) + { + this.Update(monitor); + } + + public void Update(TestMonitor monitor) + { + this.consoleError = UnitSerializer.XmlSerializerEscapeWorkAround(monitor.Console.Error); + this.consoleOut = UnitSerializer.XmlSerializerEscapeWorkAround(monitor.Console.Out); + this.startTime = monitor.Timer.StartTime.ToString("u"); + this.endTime = monitor.Timer.EndTime.ToString("u"); + this.duration = monitor.Timer.Duration; + this.log = monitor.GetLog(); + } + + [XmlAttribute] + public string StartTime + { + get { return this.startTime; } + set { this.startTime = value; } + } + + [XmlAttribute] + public string EndTime + { + get { return this.endTime; } + set { this.endTime = value; } + } + + [XmlAttribute] + public double Duration + { + get { return this.duration; } + set { this.duration = value; } + } + + [XmlElement] + public XmlLog Log + { + get { return this.log; } + set { this.log = value; } + } + + [XmlElement] + public string ConsoleOut + { + get { return this.consoleOut; } + set { this.consoleOut = value; } + } + + [XmlElement] + public string ConsoleError + { + get { return this.consoleError; } + set { this.consoleError = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs.meta new file mode 100644 index 0000000..8d0de0c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlMonitor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23f6ab64aa054468297432ba4eef079b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs new file mode 100755 index 0000000..9d01e33 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using QuickGraph.Unit.Monitoring; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public class XmlResult : XmlMonitor + { + private string id; + private TestState state = TestState.NotRun; + private XmlException exception = null; + + public XmlResult() + { } + + public XmlResult(Result result) + : base(result.Monitor) + { + this.Update(result); + } + + public void Update(Result result) + { + if (result == null) + throw new ArgumentNullException("result"); + this.state = result.State; + if (result.Exception != null) + this.exception = XmlException.FromException(result.Exception); + this.Update(result.Monitor); + } + + [XmlAttribute("id")] + public string ID + { + get { return this.id; } + set { this.id = value; } + } + + [XmlAttribute] + public TestState State + { + get + { + return this.state; + } + set + { + this.state = value; + } + } + + [XmlElement] + public XmlException Exception + { + get { return this.exception; } + set { this.exception = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs.meta new file mode 100644 index 0000000..6994fea --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlResult.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 59b226c4fbecc4c889c24552d4729102 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs new file mode 100755 index 0000000..c9266d8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using System.Xml; +using System.Reflection; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlTestAssembly + { + private XmlCounter counter = new XmlCounter(); + private XmlFixtureCollection fixtures = new XmlFixtureCollection(); + private XmlResult assemblySetUp = null; + private XmlResult assemblyTearDown = null; + private string assemblyName = null; + private string assemblyFullName = null; + private string assemblyLocation = null; + private DateTime startTime; + private DateTime endTime; + private double duration; + + public XmlTestAssembly() + {} + + public XmlTestAssembly(AssemblyName assemblyName, string location) + : this() + { + this.assemblyName = assemblyName.Name; + this.assemblyFullName = assemblyName.FullName; + this.assemblyLocation = location; + } + + [XmlAttribute] + public string AssemblyName + { + get { return this.assemblyName; } + set { this.assemblyName = value; } + } + + [XmlAttribute] + public string AssemblyFullName + { + get { return this.assemblyFullName; } + set { this.assemblyFullName = value; } + } + + [XmlAttribute] + public string AssemblyLocation + { + get { return this.assemblyLocation; } + set { this.assemblyLocation = value; } + } + + [XmlAttribute] + public DateTime StartTime + { + get { return this.startTime; } + set { this.startTime = value; } + } + + [XmlAttribute] + public DateTime EndTime + { + get { return this.endTime; } + set { this.endTime = value; } + } + + [XmlAttribute] + public double Duration + { + get { return this.duration; } + set { this.duration = value; } + } + + [XmlElement] + public XmlCounter Counter + { + get { return this.counter; } + set { this.counter = value; } + } + + [XmlElement] + public XmlResult AssemblySetUp + { + get { return this.assemblySetUp; } + set { this.assemblySetUp = value; } + } + + [XmlElement] + public XmlResult AssemblyTearDown + { + get { return this.assemblyTearDown; } + set { this.assemblyTearDown = value; } + } + + [XmlArray("Fixtures")] + [XmlArrayItem("Fixture")] + public XmlFixtureCollection Fixtures + { + get { return this.fixtures; } + } + + public void UpdateCounter() + { + this.counter = new XmlCounter(); + this.duration = 0; + foreach (XmlFixture fixture in this.Fixtures) + { + fixture.UpdateCounter(); + this.counter = this.counter + fixture.Counter; + this.duration += fixture.Duration; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs.meta new file mode 100644 index 0000000..81378a5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssembly.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa419f592f7eb4df7bf9f48e1741db2b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs new file mode 100755 index 0000000..bdaf53a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlTestAssemblyCollection : List + {} +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs.meta new file mode 100644 index 0000000..290d4b2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestAssemblyCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e5885269221d247f38ab29bb42dbf467 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs new file mode 100755 index 0000000..beec230 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using System.Reflection; +using System.IO; + +namespace QuickGraph.Unit.Serialization +{ + [XmlRoot("TestBatch")] + [Serializable] + public sealed class XmlTestBatch + { + private XmlMachine machine; + private string entryAssemblyName = null; + private string entryAssemblyLocation = null; + private XmlCounter counter = new XmlCounter(); + private XmlTestAssemblyCollection testAssemblies = new XmlTestAssemblyCollection(); + private string commandLine = null; + private string startTime = DateTime.Now.ToString("u"); + private string endTime = DateTime.Now.ToString("u"); + private double duration; + private bool hasHistory = false; + private XmlLog log = new XmlLog(); + + public XmlTestBatch() + { } + + public void SetMainAssembly(Assembly entryAssembly) + { + this.machine = XmlMachine.Create(); + this.commandLine = Environment.CommandLine; + if (entryAssembly != null) + { + this.entryAssemblyLocation = Path.GetFileName(entryAssembly.Location); + this.entryAssemblyName = entryAssembly.GetName().Name; + } + } + + [XmlAttribute] + public bool HasHistory + { + get { return this.hasHistory; } + set { this.hasHistory = value; } + } + + [XmlAttribute] + public string CommandLine + { + get { return this.commandLine; } + set { this.commandLine = value; } + } + + [XmlAttribute] + public string EntryAssemblyLocation + { + get { return this.entryAssemblyLocation; } + set { this.entryAssemblyLocation = value; } + } + + [XmlAttribute] + public string EntryAssemblyName + { + get { return this.entryAssemblyName; } + set { this.entryAssemblyName = value; } + } + + [XmlAttribute] + public string StartTime + { + get { return this.startTime; } + set { this.startTime = value; } + } + + [XmlAttribute] + public string EndTime + { + get { return this.endTime; } + set { this.endTime = value; } + } + + [XmlAttribute] + public double Duration + { + get { return this.duration; } + set { this.duration = value; } + } + + [XmlElement] + public XmlCounter Counter + { + get { return this.counter; } + set { this.counter = value; } + } + + [XmlElement] + public XmlMachine Machine + { + get { return this.machine; } + set { this.machine = value; } + } + + [XmlElement] + public XmlLog Log + { + get { return this.log; } + set { this.log = value; } + } + + [XmlArray("TestAssemblies")] + [XmlArrayItem("TestAssembly")] + public XmlTestAssemblyCollection TestAssemblies + { + get { return this.testAssemblies; } + } + + public void UpdateCounter() + { + this.counter = new XmlCounter(); + this.duration = 0; + + foreach (XmlTestAssembly testAssembly in this.TestAssemblies) + { + testAssembly.UpdateCounter(); + this.counter = this.counter + testAssembly.Counter; + this.duration += testAssembly.Duration; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs.meta new file mode 100644 index 0000000..cc0e20a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatch.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f488747bf97bf449a83cb3608fcd8b84 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs new file mode 100755 index 0000000..bd2942d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit.Serialization +{ + public sealed class XmlTestBatchSearcher + { + private XmlTestBatch testBatch; + private Dictionary testCases = new Dictionary(); + private Dictionary fixtures = new Dictionary(); + + public XmlTestBatchSearcher(XmlTestBatch testBatch) + { + this.testBatch = testBatch; + + foreach (XmlTestAssembly testAssembly in this.testBatch.TestAssemblies) + { + foreach (XmlFixture fixture in testAssembly.Fixtures) + { + this.fixtures[fixture.Name]=fixture; + foreach (XmlTestCase testCase in fixture.TestCases) + { + string testName = testCase.GetFullName(fixture); + if (this.testCases.ContainsKey(testName)) + Console.WriteLine("Warning: duplicate test {0}", testName); + else + this.testCases.Add(testName,testCase); + } + } + } + } + + public IDictionary TestCases + { + get { return this.testCases; } + } + + public IDictionary Fixtures + { + get { return this.fixtures; } + } + + public XmlFixture GetFixture(XmlFixture fixture) + { + if (fixture == null) + throw new ArgumentNullException("fixture"); + return GetFixture(fixture.Name); + } + + public XmlFixture GetFixture(string fixtureName) + { + XmlFixture tc = null; + this.fixtures.TryGetValue(fixtureName, out tc); + return tc; + } + + public XmlTestCase GetTestCase(string fixtureName, string testCaseName) + { + XmlTestCase tc = null; + this.testCases.TryGetValue( + XmlTestCase.GetTestCaseFullName(fixtureName,testCaseName), + out tc); + return tc; + } + + public XmlTestCase GetTestCase(XmlFixture fixture, XmlTestCase testCase) + { + if (fixture == null) + throw new ArgumentNullException("fixture"); + if (testCase == null) + throw new ArgumentNullException("testCase"); + + return GetTestCase(fixture.Name, testCase.Name); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs.meta new file mode 100644 index 0000000..8446710 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestBatchSearcher.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a5e3a4d6fffac4fc8ae9b9c8d3349e8c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs new file mode 100755 index 0000000..06a26e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs @@ -0,0 +1,140 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using QuickGraph.Unit.Monitoring; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlTestCase + { + private string id; + private TestState state = TestState.NotRun; + private string name; + private double duration=0; + private XmlResult setUp = null; + private XmlResult tearDown = null; + private XmlResult test = null; + private XmlTestHistory history = XmlTestHistory.NoChange; + + public XmlTestCase() + { } + + public XmlTestCase(string id,string name) + { + this.id = id; + this.name = name; + } + + [XmlAttribute("id")] + public string ID + { + get { return this.id; } + set { this.id = value; } + } + + [XmlAttribute] + public string Name + { + get { return this.name; } + set { this.name = value; } + } + + public static string GetTestCaseFullName(string fixtureName, string testName) + { + return string.Format("{0}.{1}", fixtureName, testName); + } + public string GetFullName(XmlFixture fixture) + { + return GetTestCaseFullName(fixture.Name, this.Name); + } + + [XmlAttribute] + public double Duration + { + get { return this.duration; } + set { this.duration = value; } + } + + [XmlAttribute] + public XmlTestHistory History + { + get { return this.history; } + set + { + this.history = value; + } + } + + [XmlElement] + public XmlResult SetUp + { + get { return this.setUp; } + set + { + this.setUp = value; + this.Update(); + } + } + + [XmlElement] + public XmlResult TearDown + { + get { return this.tearDown; } + set + { + this.tearDown=value; + this.Update(); + } + } + + [XmlElement] + public XmlResult Test + { + get { return this.test; } + set + { + this.test = value; + this.Update(); + } + } + + [XmlAttribute] + public TestState State + { + get { return this.state; } + set { this.state = value; } + } + + public void Update() + { + this.duration = 0; + if (this.SetUp != null) + { + this.state = MaxState(this.state, this.SetUp.State); + this.duration += this.SetUp.Duration; + } + + if (this.Test != null) + { + this.state = MaxState(this.state, this.Test.State); + this.duration += this.Test.Duration; + } + + if (this.TearDown != null) + { + this.state = MaxState(this.state, this.TearDown.State); + this.duration += this.TearDown.Duration; + } + } + + private static TestState MaxState(TestState left, TestState right) + { + if ((short)left > (short)right) + return left; + else + return right; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs.meta new file mode 100644 index 0000000..a5063c0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5be67a8a8967c41d7ade0fabaf1ca757 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs new file mode 100755 index 0000000..edcc545 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit.Serialization +{ + [Serializable] + public sealed class XmlTestCaseCollection : List + { + public XmlTestCaseCollection() { } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs.meta new file mode 100644 index 0000000..999cbf9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestCaseCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 152293c88986845e897031013d7a56a9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs new file mode 100755 index 0000000..b52de99 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Unit +{ + public enum XmlTestHistory + { + NoChange, + New, + Fixed, + Failure + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs.meta new file mode 100644 index 0000000..3093ae1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/Serialization/XmlTestHistory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41700096ec8374713a6639e974c4d692 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs new file mode 100755 index 0000000..4316755 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.CompilerServices; +using System.Collections.Generic; +using System.Xml.Serialization; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + public static class SerializationAssert + { + public static void IsSerializable(Type type) + { + SerializableAttribute attribute = ReflectionHelper.GetAttribute(type); + Assert.IsNotNull(attribute, + "{0} is not tagged with [SerializableAttribute]", type); + } + + public static void IsXmlSerializable(Type type) + { + new XmlSerializer(type); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs.meta new file mode 100644 index 0000000..43a7d23 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SerializationAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 049d15a0e5f4a4809bc28b594cfa58ab +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs new file mode 100755 index 0000000..261a85a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs @@ -0,0 +1,70 @@ +using System; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=true, Inherited=true)] + public sealed class SetEnvironmentVariableAttribute : TestDecoratorAttributeBase + { + private string name; + private string value; + + public SetEnvironmentVariableAttribute( + string name, + string value) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + this.name = name; + this.value = value; + } + + public string Name + { + get { return this.name; } + } + + public string Value + { + get { return this.value; } + } + + public override ITestCase Decorate(ITestCase test) + { + return new SetEnvironmentVariableTestCase(test, this); + } + + private sealed class SetEnvironmentVariableTestCase : TypeDecoratorTestCaseBase + { + public SetEnvironmentVariableTestCase( + ITestCase testCase, + SetEnvironmentVariableAttribute attribute) + :base(testCase,attribute) + {} + + public override void Run(object fixture) + { + string value = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + value = Environment.GetEnvironmentVariable(this.Attribute.Name); + Console.WriteLine("Setting {0}={1}", + this.Attribute.Name, + this.Attribute.Value); + Environment.SetEnvironmentVariable( + this.Attribute.Name, + this.Attribute.Name); + + this.TestCase.Run(fixture); + } + finally + { + Environment.SetEnvironmentVariable( + this.Attribute.Name, + value); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs.meta new file mode 100644 index 0000000..b4dbfab --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetEnvironmentVariableAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5c60f437f6f7a414c9e4481ab0ad331e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs new file mode 100755 index 0000000..05b358e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class SetUpAttribute : Attribute { } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs.meta new file mode 100644 index 0000000..3a27f4c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/SetUpAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da16e55ef173a4159a966002da2f13b9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs new file mode 100755 index 0000000..dbddea9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs @@ -0,0 +1,47 @@ +using System; +using System.IO; + +namespace QuickGraph.Unit +{ + public static class StreamAssert + { + public static void AreEqual(Stream leftStream, Stream rightStream) + { + Assert.AreEqual(leftStream.CanRead, rightStream.CanRead, + "CanRead property is not the same"); + Assert.AreEqual(leftStream.CanSeek, rightStream.CanSeek, + "CanSeek property is not the same"); + Assert.AreEqual(leftStream.CanTimeout, rightStream.CanTimeout, + "CanTimeOut property is not the same"); + Assert.AreEqual(leftStream.CanWrite, rightStream.CanWrite, + "CanWriteProperty is not the same"); + + if (leftStream.CanRead) + { + using (StreamReader leftReader = new StreamReader(leftStream)) + using (StreamReader rightReader = new StreamReader(rightStream)) + { + AreEqual(leftReader, rightReader); + } + } + } + + public static void AreEqual(StreamReader leftReader, StreamReader rightReader) + { + Assert.AreEqual(leftReader.EndOfStream, rightReader.EndOfStream, + "The end of the streams do not match"); + int lineNumber = 0; + while (!leftReader.EndOfStream) + { + string leftLine = leftReader.ReadLine(); + string rightLine = rightReader.ReadLine(); + Assert.AreEqual(leftLine, rightLine, + "Line {0} are different: [[{1}]], [[{2}]]", + lineNumber, leftLine, rightLine); + Assert.AreEqual(leftReader.EndOfStream, rightReader.EndOfStream, + "The end of the streams do not match"); + lineNumber++; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs.meta new file mode 100644 index 0000000..6a2852c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StreamAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0caf9a2424e024fa3810026c88644cdf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs new file mode 100755 index 0000000..034b8e2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs @@ -0,0 +1,62 @@ +using System; +using System.Text; + +namespace QuickGraph.Unit +{ + public static class StringAssert + { + public static void AreEqual(string expected, string value, StringComparison comparaison) + { + Assert.IsTrue(expected.Equals(value, comparaison), + "[{0}]!=[{1}] using comparaison {2}", + expected, value, comparaison); + } + + public static void AreNotEqual(string expected, string value, StringComparison comparaison) + { + Assert.IsFalse(expected.Equals(value, comparaison), + "[{0}]==[{1}] using comparaison {2}", + expected, value, comparaison); + } + + public static void Contains(string value, string match) + { + Assert.IsTrue(value.Contains(match), + "[{0}] does not contain [{1}]", value, match); + } + + public static void EndsWith(string value, string match) + { + EndsWith(value, match, StringComparison.CurrentCulture); + } + + public static void EndsWith(string value, string match, StringComparison stringComparaison) + { + Assert.IsTrue(value.EndsWith(match, stringComparaison), + "[{0}] does not end with [{1}]", value, match); + } + + public static void StartsWith(string value, string match) + { + StartsWith(value, match, StringComparison.CurrentCulture); + } + + public static void StartsWith(string value, string match, StringComparison stringComparaison) + { + Assert.IsTrue(value.StartsWith(match,stringComparaison), + "[{0}] does not end with [{1}]", value, match); + } + + public static void IsNullOrEmpty(string value) + { + Assert.IsTrue(String.IsNullOrEmpty(value), + "[[{0}]] is not null or empty", value); + } + + public static void IsNotNullOrEmpty(string value) + { + Assert.IsFalse(String.IsNullOrEmpty(value), + "[[{0}]] is not null or empty", value); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs.meta new file mode 100644 index 0000000..c196723 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/StringAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e0612e511b73d4b2ab2535a01dcef258 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs new file mode 100755 index 0000000..6e9d66b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class TearDownAttribute : Attribute { } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs.meta new file mode 100644 index 0000000..b799b2e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TearDownAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9c8f222deaa8d42ea8742ebd8a65bc54 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs new file mode 100755 index 0000000..5039fe2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class TestAttribute : TestAttributeBase + { + public override IEnumerable CreateTests( + IFixture fixture, + MethodInfo method + ) + { + yield return new MethodTestCase(fixture.Name, method); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs.meta new file mode 100644 index 0000000..1928a1d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1929ee663cab641aca49eabb0190d97c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCase.png b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCase.png new file mode 100755 index 0000000000000000000000000000000000000000..c1cdf1a0d1ef309228705c898a8c804784fb9d1a GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~i!NkD8c+bn)8^~cR3GxeO_z!~S5z@6l5zYdS z$YP+X!ywFfJby(BNU+2;qQp5rH#aq}gn^+`tCtNZ*x>2n7*a8(HGq@vfC9(s%eAxY zi;Ftg=T6$O#-UNnm-$nbPe_0ar;D_Ll+XdbXBLM%_n30KeP=eE>GpB=2JNn#>1wa~ z0*pfH>3#D9L|Ue*t-p3F`faw%b&mVaZz4Ef k&og-O_SpP)<_|mg8y)zHr?1Nk1G parameters) + { + object[] objs = new object[parameters.Count]; + int i =0; + foreach(TestCaseParameter parameter in parameters) + objs[i++] = parameter.Value; + return objs; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameter.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameter.cs.meta new file mode 100644 index 0000000..ee15090 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9ae8708286e34e47a1fae7b3b1b1266 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs new file mode 100755 index 0000000..831bdd3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit +{ + public abstract class TestCaseParameterFactoryAttributeBase : Attribute, + ITestCaseParameterFactory + { + public abstract IEnumerable CreateInstances(Type targetType); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs.meta new file mode 100644 index 0000000..c3d6247 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestCaseParameterFactoryAttributeBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fde25a74f258745a69d7a64733bed3b0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs new file mode 100755 index 0000000..a63cbc3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Unit +{ + public static class TestConsole + { + private static string reportDirectoryName = ""; + + public static string ReportDirectoryName + { + get { return reportDirectoryName; } + } + + internal static void SetReportDirectoryName(string directoryName) + { + reportDirectoryName = directoryName; + } + + public static void WriteImage(string url) + { + Console.WriteLine("[img src=\"{0}\" /]", url); + } + + public static void WriteUri(string uriString) + { + WriteUri(new Uri(System.IO.Path.GetFullPath(uriString))); + } + + public static void WriteUri(Uri uri) + { + Console.WriteLine(uri.AbsoluteUri); + } + + public static void WriteBold(string message) + { + Console.Write("**{0}**", message); + } + + public static void WriteBold(string format, params object[] args) + { + WriteBold(string.Format(format, args)); + } + + public static void WriteLineBold(string message) + { + WriteBold(message); + Console.WriteLine(); + } + + public static void WriteLineBold(string format, params object[] args) + { + WriteLineBold(string.Format(format, args)); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs.meta new file mode 100644 index 0000000..f83ffb7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestConsole.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 69ec0be44fa0545fa8e9a84337bc8c85 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs new file mode 100755 index 0000000..fb75d1a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public sealed class TestFixtureAttribute : TestFixtureAttributeBase + { + public TestFixtureAttribute() + : base() + { } + + public override IEnumerable CreateFixtures(Type fixture) + { + yield return new TestFixture(this, fixture); + } + + private sealed class TestFixture : TypeFixtureBase + { + public TestFixture(TestFixtureAttribute attribute, Type fixtureType) + :base(attribute, fixtureType) + {} + + public override IEnumerable CreateTestCases() + { + foreach (MethodInfo method in this.FixtureType.GetMethods()) + { + Object[] decorators = method.GetCustomAttributes(typeof(TestDecoratorAttributeBase), true); + + foreach (TestAttributeBase attribute in method.GetCustomAttributes(typeof(TestAttributeBase), true)) + { + foreach (ITestCase test in attribute.CreateTests(this, method)) + yield return DecorateTest(decorators, test); + } + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs.meta new file mode 100644 index 0000000..e5f3b77 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 03d3bf1eed1ac4896beb7751e48da0c1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs new file mode 100755 index 0000000..4bb1b8e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class TestFixtureSetUpAttribute : Attribute { } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs.meta new file mode 100644 index 0000000..449a1e0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureSetUpAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2ff4bd850e9d5493baf8cd43eec03557 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs new file mode 100755 index 0000000..9c1f91d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs @@ -0,0 +1,7 @@ +using System; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class TestFixtureTearDownAttribute : Attribute { } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs.meta new file mode 100644 index 0000000..693098d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestFixtureTearDownAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48c2f2a27ca9c4faf9a59940dafbe8f0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs new file mode 100755 index 0000000..abf33f9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs @@ -0,0 +1,565 @@ +using System; +using System.Diagnostics; +using System.ComponentModel; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using System.Threading; +using System.Xml; +using QuickGraph.Unit.Serialization; +using QuickGraph.Unit.Listeners; +using QuickGraph.Unit.Filters; +using QuickGraph.CommandLine; +using QuickGraph.Unit.Reports; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + public sealed class TestRunner : Component + { + private readonly object syncRoot = new object(); + private int successExitCode = 100; + private int failureExitCode = 101; + private TestRunnerArguments arguments = new TestRunnerArguments(); + private TestBatchFactory batchFactory = new TestBatchFactory(); + private ConsoleTestListener consoleListener = new ConsoleTestListener(); + private TestListenerCollection testListeners = new TestListenerCollection(); + private UnitTestHtmlReport report = null; + private string historyReportHtml = null; + private string historyReportXml = null; + + public TestRunner(IContainer container) + : this(container, Assembly.GetEntryAssembly()) + {} + + public TestRunner(IContainer container, Assembly assembly) + { + if (container == null) + throw new ArgumentNullException("container"); + container.Add(this); + if (assembly != null) + this.BatchFactory.TestAssemblies.Add(assembly); + + this.TestListeners.Add(this.consoleListener); + } + + public ConsoleTestListener ConsoleListener + { + get { return this.consoleListener; } + } + + public TestBatchFactory BatchFactory + { + get { return this.batchFactory; } + } + + public TestRunnerArguments Arguments + { + get { return this.arguments; } + set + { + if (value == null) + throw new ArgumentNullException("Arguments"); + this.arguments = value; + } + } + + public int SuccessExitCode + { + get { return this.successExitCode; } + set { this.successExitCode = value; } + } + + public int FailureExitCode + { + get { return this.failureExitCode; } + set { this.failureExitCode = value; } + } + + public UnitTestHtmlReport Report + { + get { return this.report; } + } + + [System.Diagnostics.DebuggerStepThrough] + public int Run(IEnumerable args) + { + this.TestListeners.Message("QuickGraph.Unit v{0}", + typeof(TestRunner).Assembly.GetName().Version); + this.TestListeners.Message( + MessageImportance.High, + "Test Assembly: {0}", Assembly.GetEntryAssembly().FullName); + + CommandLineParser parser = CommandLineParser.Create(); + if (!parser.Parse(this.arguments, args)) + { + this.TestListeners.Error("Error while parsing arguments"); + parser.ShowHelp(); + return this.FailureExitCode; + } + + if (this.Arguments.Help) + { + parser.ShowHelp(); + return this.SuccessExitCode; + } + + // run tests + return Run(); + } + + public TestListenerCollection TestListeners + { + get { return this.testListeners; } + } + + [System.Diagnostics.DebuggerStepThrough] + public int Run() + { + if (this.Arguments.BreakOnStart) + Debugger.Break(); + + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); + return this.InternalRun(); + } + finally + { + AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(CurrentDomain_AssemblyResolve); + } + } + + Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + string name = args.Name.Split(',')[0]; + + // handling System.Xml.Serializer + if (name.EndsWith("XmlSerializers")) + return null; + + this.TestListeners.Message( + MessageImportance.Low, + "Resolving Assembly name: {0}", name); + foreach (Assembly testAssembly in this.BatchFactory.TestAssemblies) + { + string directory = Path.GetDirectoryName(testAssembly.Location); + this.TestListeners.Message( + MessageImportance.Low, + "Probing in directory {0}", directory); + + string path = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.TestListeners.Message( + MessageImportance.Low, + "Probing {0}", path); + path = Path.Combine(directory, name + ".dll"); + return Assembly.LoadFrom(path); + } + catch (Exception) + { + this.TestListeners.Message( + MessageImportance.Low, + "Failed to load {0}", path); + } + + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.TestListeners.Message( + MessageImportance.Low, + "Probing {0}", path); + path = Path.Combine(directory, name + ".exe"); + return Assembly.LoadFrom(path); + } + catch (Exception) + { + this.TestListeners.Message( + MessageImportance.Low, + "Failed to load {0}", path); + return null; + } + } + + return null; + } + + private int InternalRun() + { + if (!this.InitializeTestBatch()) + return this.ExitCode; + + // reflect + this.TestListeners.Message( + MessageImportance.Low, + "Loading tests"); + this.BatchFactory.Create(); + this.TestListeners.Message( + MessageImportance.Low, + "Found {0} fixtures, {1} tests", + this.BatchFactory.Batch.GetFixtureCount(), + this.BatchFactory.Batch.GetTestCount() + ); + + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + string currentDirectory = Environment.CurrentDirectory; + try + { + // execute + this.TestListeners.BeforeBatch(this.BatchFactory.Batch); + foreach (TestAssembly testAssembly in this.BatchFactory.Batch.TestAssemblies) + { + // set current directory as assembly location + Environment.CurrentDirectory = Path.GetDirectoryName(testAssembly.Assembly.Location); + this.ExecuteTestAssembly(testAssembly); + } + } + catch (Exception ex) + { + this.TestListeners.Error("Error in Test Harness!"); + this.TestListeners.Error(ex); + } + finally + { + Environment.CurrentDirectory = currentDirectory; + this.EndTestExecution(); + } + return this.ExitCode; + } + + private void PrepareReports() + { + if (this.Arguments.GenerateReport == ReportGenerationScenario.None) + return; + + this.report = new UnitTestHtmlReport(this.Container); + this.report.GenerateOnDisposed = false; + this.report.GenerateFixtureInSeparateFile = this.Arguments.GenerateFixtureReportInSeparateFiles; + this.report.ShowFixturesSummary = this.Arguments.ShowFixturesSummary; + this.report.EntryAssemblyName = this.BatchFactory.MainAssembly; + if (this.Arguments.ForceReportOutputPath) + this.report.SetOutputFolderName(this.Arguments.ReportOutputPath); + else + this.report.SetOutputFolderName(this.Arguments.ReportOutputPath, this.BatchFactory.MainAssembly); + this.report.TestListener.ShowTestCaseOnSuccess = this.Arguments.ShowTestCaseOnSuccess; + this.TestListeners.Add(this.report.TestListener); + + // we precreate the directory name + if (!Directory.Exists(this.report.OutputFolderName)) + Directory.CreateDirectory(this.report.OutputFolderName); + TestConsole.SetReportDirectoryName(this.report.OutputFolderName); + + this.LoadPreviousResult(); + } + + private void LoadPreviousResult() + { + if (!this.Arguments.UseLatestHistory) + return; + if (!System.IO.Directory.Exists(this.Arguments.ReportOutputPath)) + return; + do + { + string latestResultFile = new ReportHistory( + this.Arguments.ReportOutputPath, + this.BatchFactory.MainAssembly).GetLatestXmlReport(); + if (latestResultFile != null) + { + this.TestListeners.Message( + MessageImportance.Low, + "Found previous report: {0}", latestResultFile); + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.report.TestListener.SetPreviousTestBatch(latestResultFile); + this.TestListeners.Message( + MessageImportance.Low, + "Loaded {0} fixtures and {1} tests in previous report", + this.report.TestListener.TestBatchSearcher.Fixtures.Count, + this.report.TestListener.TestBatchSearcher.TestCases.Count); + break; + } + catch (Exception ex) + { + this.TestListeners.Warning("Failure while loading previous report"); + this.TestListeners.Message( + MessageImportance.Low, + "Error: {0}", ex.Message); + // deleting previous report + ReportCleaner cleaner = new ReportCleaner(this.BatchFactory.MainAssembly); + cleaner.Clean(Path.GetDirectoryName(latestResultFile), this); + } + } + else + { + this.TestListeners.Message( + MessageImportance.Low, + "Could not find previous result"); + break; + } + } while (true); + } + + private void CleanOldReports() + { + if (!this.Arguments.CleanOldReports) + return; + + this.TestListeners.Message( + MessageImportance.Low, + "Cleaning old reports"); + ReportCleaner cleaner = new ReportCleaner(this.BatchFactory.MainAssembly); + cleaner.MaxReportCount = this.Arguments.MaxReportCount; + cleaner.Clean(this.Arguments.ReportOutputPath, this); + } + + private void GenerateReportHistory() + { + if (!this.Arguments.GenerateReportHistory) + return; + + using (UnitTestHistoryHtmlReport historyReport = new UnitTestHistoryHtmlReport(this.Container)) + { + historyReport.SetOutputFolderName(this.Arguments.ReportOutputPath); + historyReport.EntryAssemblyName = this.BatchFactory.MainAssembly; + historyReport.SetOutputFileName("test_history"); + historyReport.Generate(); + this.historyReportHtml = historyReport.OutputFileName; + this.historyReportXml = historyReport.OutputXmlFileName; + this.TestListeners.Message( + MessageImportance.High, + "History: {0}", new Uri(historyReport.OutputFileName).AbsoluteUri); + + if (this.Arguments.OpenReportHistory) + { + Thread thread = new Thread(delegate(object name) { Process.Start(name.ToString()); }); + thread.Start(historyReport.OutputFileName); + } + } + } + + private bool InitializeTestBatch() + { + this.BatchFactory.FixtureFilter = this.Arguments.GetFixtureFilter(); + this.BatchFactory.TestCaseFilter = this.Arguments.GetTestCaseFilter(); + + this.CleanOldReports(); + this.PrepareReports(); + + // adding assemblies + foreach (string assemblyName in this.Arguments.TestAssemblies) + { + if (!this.LoadTestAssembly(assemblyName)) + return false; + } + return true; + } + + private bool LoadTestAssembly(string assemblyName) + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + Assembly testAssembly = Assembly.LoadFile(assemblyName); + this.BatchFactory.TestAssemblies.Add(testAssembly); + return true; + } + catch (Exception ex) + { + this.TestListeners.Error("Error while loading {0}", assemblyName); + this.TestListeners.Error(ex); + return false; + } + } + + [System.Diagnostics.DebuggerStepThrough] + private void ExecuteTestAssembly(TestAssembly testAssembly) + { + this.TestListeners.BeforeAssembly(testAssembly); + + // run assemblysetup + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + if (this.RunAssemblySetUp(testAssembly)) + { + foreach (IFixture fixture in testAssembly.Fixtures) + { + using (FixtureRunner runner = + new FixtureRunner( + fixture, + testAssembly.GetTestCasesFromFixture(fixture), + this.TestListeners) + ) + { + runner.Run(); + } + // collect GC + GC.WaitForPendingFinalizers(); + GC.Collect(); + } + } + } + finally + { + // run assembly teardown + this.RunAssemblyTearDown(testAssembly); + this.TestListeners.AfterAssembly(testAssembly); + } + } + + private void EndTestExecution() + { + // finish + this.TestListeners.AfterBatch(this.BatchFactory.Batch); + + // generate report + this.GenerateReport(); + this.GenerateReportHistory(); + + this.TestListeners.ReportsGenerated( + this.historyReportXml, + this.historyReportHtml, + this.report.OutputXmlFileName, + this.report.OutputFileName + ); + + if (!this.Counter.Succeeded) + this.TestListeners.Message( + MessageImportance.High, + "Test FAILED"); + else + this.TestListeners.Message( + MessageImportance.High, + "Test SUCCESS"); + } + + private bool RunAssemblySetUp(TestAssembly testAssembly) + { + if (testAssembly.AssemblySetUp == null) + return true; + + Result result = new Result(testAssembly.AssemblySetUp.Name); + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + result.Start(); + testAssembly.AssemblySetUp.Invoke(null, null); + result.Success(); + } + catch (Exception ex) + { + Exception current = ex; + if (current is TargetInvocationException) + current = current.InnerException; + if (current is QuickGraph.Unit.Exceptions.IgnoreException) + result.Ignore(); + else + result.Fail(current); + } + this.TestListeners.AssemblySetUp(result); + + return result.State == TestState.Success; + } + + private void RunAssemblyTearDown(TestAssembly testAssembly) + { + if (testAssembly.AssemblyTearDown == null) + return; + + Result result = new Result(testAssembly.AssemblyTearDown.Name); + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + result.Start(); + testAssembly.AssemblyTearDown.Invoke(null, null); + result.Success(); + } + catch (Exception ex) + { + Exception current = ex; + if (current is TargetInvocationException) + current = current.InnerException; + if (current is QuickGraph.Unit.Exceptions.IgnoreException) + result.Ignore(); + else + result.Fail(current); + } + this.TestListeners.AssemblyTearDown(result); + } + + public TestCounter Counter + { + get { return this.consoleListener.Counter; } + } + + public int ExitCode + { + get + { + if (this.consoleListener.Counter == null) + return this.FailureExitCode; + return (this.consoleListener.Counter.HasFailures) ? + this.FailureExitCode: this.SuccessExitCode; + } + } + + private void GenerateReport() + { + switch (this.Arguments.GenerateReport) + { + case ReportGenerationScenario.None: + return; + case ReportGenerationScenario.OnFailure: + if (!this.Counter.HasFailures) + return; + else + break; + } + + if (this.Arguments.ForceReportOutputPath) + this.report.SetOutputFileName("TestWithResults"); + else + this.report.SetOutputFileName(this.BatchFactory.MainAssembly); + this.report.Generate(); + this.TestListeners.Message( + MessageImportance.High, + "Test report: {0}", new Uri(this.report.OutputFileName).AbsoluteUri); + if (this.Arguments.OpenReport) + { + Thread thread = new Thread(new ThreadStart(this.OpenReport)); + thread.Start(); + } + } + + private void OpenReport() + { + System.Diagnostics.Process.Start(report.OutputFileName); + } + + public static int TestMain(IEnumerable args) + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + using (UnitContainer container = new UnitContainer()) + { + using (TestRunner runner = new TestRunner(container)) + { + runner.Run(args); + return runner.ExitCode; + } + } + } + catch (Exception ex) + { + Console.WriteLine("Error in Test Harness!"); + Console.WriteLine(ex.ToString()); + return 101; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs.meta new file mode 100644 index 0000000..def10ed --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunner.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 155982f2d7cd645a9b2677c55c2b3a24 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs new file mode 100755 index 0000000..6802603 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs @@ -0,0 +1,252 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; +using QuickGraph.CommandLine; +using QuickGraph.Unit.Filters; +using QuickGraph.Unit.Reports; +using QuickGraph.Unit.Serialization; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [XmlRoot("unit")] + public sealed class TestRunnerArguments + { + [Argument( + ShortName = "h", + LongName = "help", + Description = "Display help")] + [XmlAttribute("help")] + public bool Help = false; + + [Argument( + ShortName = "gr", + LongName = "generate-report", + Description = "specify if a report has to be generated" + )] + [XmlAttribute("generate-report")] + public ReportGenerationScenario GenerateReport = ReportGenerationScenario.Always; + + [Argument( + ShortName="stcos", + LongName="show-test-case-on-success", + Description="Show test case on success in the reports" + )] + [XmlAttribute("show-test-case-on-success")] + public bool ShowTestCaseOnSuccess = true; + + [Argument( + ShortName = "or", + LongName = "open-report", + Description = "open report after created" + )] + [XmlAttribute("open-report")] + public bool OpenReport = false; + + [Argument( + ShortName = "rf", + LongName = "report-folder", + Description = "specify report folder" + )] + [XmlAttribute("report-folder")] + public string ReportOutputPath = "Reports"; + + [Argument( + ShortName="frop", + LongName="force-report-folder", + Description="Disable automatic report folder name generation" + )] + public bool ForceReportOutputPath = false; + + [Argument( + ShortName = "gfrisf", + LongName="generate-fixture-report-in-separate-files", + Description="Generates fixture reports in separate HTML files" + )] + [XmlAttribute("generate-fixture-report-in-separate-files")] + public bool GenerateFixtureReportInSeparateFiles = false; + + [Argument( + ShortName="sfs", + LongName="show-fixtures-summary", + Description="Shows a summary of the fixtures")] + public bool ShowFixturesSummary = true; + + [Argument( + ShortName = "ulh", + LongName="use-latest-history", + Description="Use latest test report to determine new failures, fixed tests" + )] + [XmlAttribute("use-latest-history")] + public bool UseLatestHistory = true; + + [Argument( + ShortName="cor", + LongName="clean-old-reports", + Description="Automatically deletes old report folders" + )] + [XmlAttribute("clean-old-reports")] + public bool CleanOldReports = true; + + [Argument( + ShortName="mrc", + LongName="max-report-count", + Description="Number of old report stored on disk. Older reports are automatically deleted (if clean-reports is true)" + )] + [XmlAttribute("max-report-count")] + public int MaxReportCount = 25; + + [Argument( + ShortName="grh", + LongName="generate-report-history", + Description="Generates an history of the previous and current results" + )] + [XmlAttribute("generate-report-history")] + public bool GenerateReportHistory = true; + + [Argument( + ShortName="orh", + LongName="open-report-history", + Description="Opens the report history on completion" + )] + [XmlAttribute("open-report-history")] + public bool OpenReportHistory = true; + + [Argument( + ShortName = "bs", + LongName = "break-on-start", + Description = "Debugger break on start" + )] + [XmlAttribute("break-on-start")] + public bool BreakOnStart = false; + + [Argument( + ShortName ="rfa", + LongName = "run-failures", + Description="Run failures from report" + )] + [XmlArray("run-failures")] + [XmlArrayItem("run-failure")] + public List RunFailures = new List(); + + [Argument( + ShortName = "ff", + LongName = "fixture-filter", + Description = "fixture name filters (fixture name must contain the filter string)" + )] + [XmlArray("fixture-filters")] + [XmlArrayItem("fixture-filter")] + public List FixtureFilters = new List(); + + [Argument( + ShortName = "tcf", + LongName = "test-case-filter", + Description = "test case name filters (test case name must contain the filter string" + )] + [XmlArray("test-case-filters")] + [XmlArrayItem("test-case-filter")] + public List TestCaseFilters = new List(); + + [Argument( + ShortName="c", + LongName="category", + Description="Test categories to run" + )] + [XmlArray("categories")] + [XmlArrayItem("category")] + public List Categories = new List(); + + [Argument( + ShortName = "ta", + LongName = "test-assembly", + Description = "Test assemblies")] + [XmlArray("test-assemblies")] + [XmlArrayItem("test-assembly")] + public List TestAssemblies = new List(); + + [Argument( + ShortName="ucf", + LongName="use-current-fixures", + Description="Run fixture tagged with [CurrentFixture] only")] + public bool UseCurrentFixtures = false; + + public IFixtureFilter GetFixtureFilter() + { + IFixtureFilter filter=null; + if (this.FixtureFilters.Count != 0) + filter = new ScopeFixtureFilter(this.FixtureFilters); + + if (this.Categories.Count != 0) + { + if (filter == null) + filter = new CategoryFixtureFilter(this.Categories); + else + filter = new AndFixtureFilter( + filter, + new CategoryFixtureFilter(this.Categories) + ); + } + + if (this.RunFailures.Count != 0) + { + foreach (string runFailureReport in this.RunFailures) + { + if (!File.Exists(runFailureReport)) + throw new ArgumentException("Could not find failure file "+ runFailureReport); + XmlTestBatch testBatch = UnitSerializer.Deserialize(runFailureReport); + if (testBatch != null) + { + FailureFilter failureFilter = new FailureFilter(testBatch); + if (filter == null) + filter = failureFilter; + else + filter = new AndFixtureFilter(filter, failureFilter); + } + } + } + + if (this.UseCurrentFixtures) + { + if (filter == null) + filter = new CurrentFixtureFilter(); + else + filter = new AndFixtureFilter(filter, new CurrentFixtureFilter()); + } + + if (filter == null) + filter = new AnyFixtureFilter(); + return filter; + } + + public ITestCaseFilter GetTestCaseFilter() + { + ITestCaseFilter filter = null; + + if (this.TestCaseFilters.Count != 0) + return new ScopeTestCaseFilter(this.TestCaseFilters); + + if (this.RunFailures.Count != 0) + { + foreach (string runFailureReport in this.RunFailures) + { + if (!File.Exists(runFailureReport)) + throw new ArgumentException("Could not find failure file " + runFailureReport); + XmlTestBatch testBatch = UnitSerializer.Deserialize(runFailureReport); + if (testBatch != null) + { + FailureFilter failureFilter = new FailureFilter(testBatch); + if (filter == null) + filter = failureFilter; + else + filter = new AndTestCaseFilter(filter, failureFilter); + } + } + } + + if (filter==null) + filter = new AnyTestCaseFilter(); + return filter; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs.meta new file mode 100644 index 0000000..faf88cb --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestRunnerArguments.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 236250fee053347d4a84f81f58a628ed +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs new file mode 100755 index 0000000..aa5cfce --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +namespace QuickGraph.Unit +{ + [Serializable] + public sealed class TestSynchronizer : IDisposable + { + private readonly object syncRoot = new object(); + private String name; + private ManualResetEvent barrier; + private List threadNames = new List(); + + public TestSynchronizer(string name) + { + if (String.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + this.name = name; + } + + public ICollection GetThreadNames() + { + lock(syncRoot) + { + return new List(this.threadNames); + } + } + + public String Name + { + get { return this.name; } + } + + public void Block() + { + // make sure we cleaned up + this.Close(); + this.barrier = new ManualResetEvent(false); + } + + public void Release() + { + if (this.barrier == null) + throw new InvalidOperationException("Block must be called first"); + this.barrier.Set(); + } + + public void Synchronize() + { + if (this.barrier == null) + throw new InvalidOperationException("Block must be called first"); + // add thread name + lock (syncRoot) + { + this.threadNames.Add(Thread.CurrentThread.Name); + } + this.barrier.WaitOne(); + } + + public void Close() + { + if (this.barrier != null) + { + IDisposable disposable = this.barrier as IDisposable; + if (disposable != null) + disposable.Dispose(); + this.barrier = null; + } + } + + public void Dispose() + { + this.Close(); + } + + public override string ToString() + { + return this.Name; + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs.meta new file mode 100644 index 0000000..481c451 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TestSynchronizer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a2581e84044624565b738cc601a407b5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs new file mode 100755 index 0000000..fd3732f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.CompilerServices; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited=true, AllowMultiple=true)] + public sealed class MultiThreadedRepeatAttribute : TestDecoratorAttributeBase + { + private int threadCount = 1; + + public MultiThreadedRepeatAttribute(int threadCount) + { + this.threadCount = threadCount; + } + + public int ThreadCount + { + get { return this.threadCount; } + set { this.threadCount = value; } + } + + public override ITestCase Decorate(ITestCase testCase) + { + return new MultiThreadedRepeatTestCase(testCase, this); + } + + private sealed class MultiThreadedRepeatTestCase : TypeDecoratorTestCaseBase + { + private TestSynchronizer synchronizer; + private TestCaseWorkerCollection workers = new TestCaseWorkerCollection(); + + public MultiThreadedRepeatTestCase(ITestCase testCase, MultiThreadedRepeatAttribute attribute) + :base(testCase, attribute) + { + this.synchronizer = new TestSynchronizer(this.Name); + } + + public override void Run(object fixture) + { + // we block the synchronizer + try + { + this.synchronizer.Block(); + // create the pool of threads + for (int i = 0; i < this.Attribute.ThreadCount; ++i) + { + SynchronizedTestCase synchronizedTest = new SynchronizedTestCase(this.TestCase, this.synchronizer); + workers.Add(new TestCaseWorker(synchronizedTest, i)); + } + // starting threads + this.workers.StartAll(fixture); + // release barrier + this.synchronizer.Release(); + // wait for finish and verify + this.workers.WaitAll(); + this.workers.Verify(); + } + finally + { + // shutting down the synchronizer + this.synchronizer.Close(); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs.meta new file mode 100644 index 0000000..203c59c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/ThreadedRepeatAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 86a01533f2ec443a19d05aa7f239566a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs new file mode 100755 index 0000000..648810e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple =true, Inherited =true)] + public sealed class TypeFactoryAttribute : TestCaseParameterFactoryAttributeBase + { + private Type factoryType; + + public TypeFactoryAttribute(Type factoryType) + { + if (factoryType == null) + throw new ArgumentNullException("factoryType"); + this.factoryType = factoryType; + } + + public Type FactoryType + { + get { return this.factoryType; } + } + + public override IEnumerable CreateInstances(Type targetType) + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + foreach (MethodInfo method in ReflectionHelper.GetMethods(this.FactoryType, typeof(FactoryAttribute))) + { + if (method.GetParameters().Length > 0) + continue; + + FactoryAttribute factoryAttribute = ReflectionHelper.GetAttribute(method); + + // the method returns the type or a enumerable collection + if (targetType.IsAssignableFrom(method.ReturnType)) + yield return CreateSingleInstance(method); + else if ( + targetType.IsAssignableFrom(typeof(IEnumerable<>).MakeGenericType(targetType)) + || ( + targetType.IsAssignableFrom(typeof(IEnumerable)) + && targetType.IsAssignableFrom(factoryAttribute.FactoredType) + ) + ) + { + foreach (TestCaseParameter parameter in CreateMultipleInstances(method)) + yield return parameter; + } + } + } + + private TestCaseParameter CreateSingleInstance(MethodInfo method) + { + object instance = null; + object factory = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + factory = Activator.CreateInstance(this.FactoryType); + instance = method.Invoke(factory, null); + } + finally + { + IDisposable disposable = factory as IDisposable; + if (disposable != null) + disposable.Dispose(); + } + + return new TestCaseParameter( + String.Format("{0}.{1}",this.FactoryType.Name,method.Name), + instance + ); + } + + private IEnumerable CreateMultipleInstances(MethodInfo method) + { + System.Collections.IEnumerable instances = null; + object factory = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + factory = Activator.CreateInstance(this.FactoryType); + instances = method.Invoke(factory, null) as IEnumerable; + + int index = 0; + foreach (object instance in instances) + { + yield return new TestCaseParameter( + String.Format("{0}.{1}.{2}", this.FactoryType.Name, method.Name, index++), + instance + ); + } + } + finally + { + IDisposable disposable = factory as IDisposable; + if (disposable != null) + disposable.Dispose(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs.meta new file mode 100644 index 0000000..620d859 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFactoryAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0de4d812c65ea4fb193863fab9f42793 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs new file mode 100755 index 0000000..cd7948a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs @@ -0,0 +1,102 @@ +using System; +using System.Reflection; +using System.Collections.Generic; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple =true, Inherited =true)] + public sealed class TypeFixtureAttribute : TestFixtureAttributeBase + { + private Type testedType; + + public TypeFixtureAttribute(Type testedType) + { + if (testedType == null) + throw new ArgumentNullException("testedType"); + this.testedType = testedType; + } + + public Type TestedType + { + get { return this.testedType; } + } + + public override IEnumerable CreateFixtures(Type fixtureType) + { + yield return new TypeFixture(this, fixtureType); + } + + private sealed class TypeFixture : TypeFixtureBase + { + public TypeFixture(TypeFixtureAttribute attribute, Type fixtureType) + :base(attribute, fixtureType) + {} + + public override IEnumerable CreateTestCases() + { + Object[] attributes = this.FixtureType.GetCustomAttributes(typeof(TestCaseParameterFactoryAttributeBase),true); + List> instances = new List>(); + List> tests = new List>(); + + // first get the number of instances + instances.Add(new List(this.CreateAllInstances(attributes))); + int instanceCount = instances[0].Count; + + // get the number of tests + tests.Add(new List(CreateTestCaseInstances())); + int testCount = tests[0].Count; + + // prepare for cross product + for(int i=1;i ToList(IEnumerable en, int capacity) + { + List list = new List(capacity); + list.AddRange(en); + return list; + } + + private IEnumerable CreateAllInstances(Object[] attributes) + { + foreach (TestCaseParameterFactoryAttributeBase atr in attributes) + { + foreach (TestCaseParameter instance in atr.CreateInstances( + this.Attribute.TestedType + )) + yield return instance; + } + } + + private IEnumerable CreateTestCaseInstances() + { + foreach (MethodInfo method in this.FixtureType.GetMethods()) + { + Object[] decorators = method.GetCustomAttributes(typeof(TestDecoratorAttributeBase), true); + + foreach (TestAttributeBase attribute in method.GetCustomAttributes(typeof(TestAttributeBase), true)) + { + foreach (ITestCase test in attribute.CreateTests(this, method)) + yield return DecorateTest(decorators, test); + } + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs.meta new file mode 100644 index 0000000..80b3cfc --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/TypeFixtureAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d1fc2f14e24041dc80b24b7a33f3e4a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs new file mode 100755 index 0000000..d60594f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Operations; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Parameter,AllowMultiple =true,Inherited =true)] + public abstract class UsingAttributeBase : + Attribute, + IParameterDomainFactory + { + public abstract void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture); + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs.meta new file mode 100644 index 0000000..2c7bbd0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingAttributeBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f8227b89b8984e098cc5a713d7e666a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs new file mode 100755 index 0000000..353c200 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Operations; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public sealed class UsingBooleanAttribute : UsingAttributeBase + { + public UsingBooleanAttribute() + { } + + public override void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture) + { + domains.Add(Domains.Boolean); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs.meta new file mode 100644 index 0000000..f0f139d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingBooleanAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9cf622f9953e0493a83054266c4ac150 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs new file mode 100755 index 0000000..751b867 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Operations; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)] + public sealed class UsingEnumAttribute : UsingAttributeBase + { + public override void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture) + { + Assert.IsTrue(parameter.ParameterType.IsEnum, + "Parameter {0} must be an enum", parameter.Name); + ArrayDomain domain = new ArrayDomain(Enum.GetValues(parameter.ParameterType)); + domains.Add(domain); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs.meta new file mode 100644 index 0000000..b585990 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingEnumAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 920bfc5dee2884103bbb430c06e9cb20 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs new file mode 100755 index 0000000..012ab1e --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Operations; +using System.Reflection; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage( + AttributeTargets.Parameter, + AllowMultiple = true, + Inherited = true)] + public sealed class UsingFactoriesAttribute : UsingAttributeBase + { + private Type factoryType = null; + public UsingFactoriesAttribute(Type factoryType) + { + if (factoryType == null) + throw new ArgumentNullException("factoryType"); + this.factoryType = factoryType; + } + + public Type FactoryType + { + get + { + return this.factoryType; + } + set + { + this.factoryType = value; + } + } + + public override void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture) + { + Object factory = null; + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + factory = Activator.CreateInstance(this.FactoryType); + this.GetAllDomains(domains, parameter, factory); + } + finally + { + IDisposable disposable = factory as IDisposable; + if (disposable != null) + disposable.Dispose(); + } + } + + private void GetAllDomains( + IList domains, + ParameterInfo parameter, + object factory) + { + foreach (MethodInfo factoryMethod in ReflectionHelper.GetMethods(factory.GetType(), typeof(FactoryAttribute))) + { + if (factoryMethod.GetParameters().Length > 0) + continue; + Type returnType = factoryMethod.ReturnType; + + // check single object return + if (parameter.ParameterType.IsAssignableFrom(returnType)) + { + object result = factoryMethod.Invoke(factory, null); + IDomain domain = Domains.ToDomain(result); + domain.Name = factoryMethod.Name; + domains.Add(domain); + continue; + } + + // check array + if (returnType.HasElementType) + { + Type elementType = returnType.GetElementType(); + if (parameter.ParameterType == elementType) + { + object result = factoryMethod.Invoke(factory,null); + IDomain domain = Domains.ToDomain(result); + domain.Name = factoryMethod.Name; + domains.Add(domain); + continue; + } + } + + // check IEnumerable + if (returnType.IsGenericType) + { + if (typeof(IEnumerable<>).IsAssignableFrom(returnType.GetGenericTypeDefinition())) + { + if (parameter.ParameterType.IsAssignableFrom(returnType.GetGenericArguments()[0])) + { + object result = factoryMethod.Invoke(factory, null); + IDomain domain = Domains.ToDomain(result); + domain.Name = factoryMethod.Name; + domains.Add(domain); + continue; + } + } + } + + // check factory type + FactoryAttribute factoryAttribute = ReflectionHelper.GetAttribute(factoryMethod); + if (factoryAttribute != null) + { + Type factoredType = factoryAttribute.FactoredType; + if (parameter.ParameterType == factoredType) + { + object result = factoryMethod.Invoke(factory, null); + IDomain domain = Domains.ToDomain(result); + domain.Name = factoryMethod.Name; + domains.Add(domain); + continue; + } + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs.meta new file mode 100644 index 0000000..de7e78a --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingFactoriesAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e2ac88e6f5bb1448195492e3bf5a3831 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs new file mode 100755 index 0000000..53d27da --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Operations; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)] + public sealed class UsingImplementationsAttribute : UsingAttributeBase + { + private Type typeFromAssembly; + + public UsingImplementationsAttribute(Type typeFromAssembly) + { + if (typeFromAssembly == null) + throw new ArgumentNullException("typeFromAssembly"); + this.typeFromAssembly = typeFromAssembly; + } + + public override void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture) + { + List types = new List(); + foreach (Type type in typeFromAssembly.Assembly.GetExportedTypes()) + { + if (type.IsAbstract || type.IsInterface || !type.IsClass) + continue; + + if (!parameter.ParameterType.IsAssignableFrom(type)) + continue; + + // create instance + Object instance = Activator.CreateInstance(type); + types.Add(instance); + } + + CollectionDomain domain = new CollectionDomain(types); + domain.Name = typeFromAssembly.Assembly.GetName().Name; + domains.Add(domain); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs.meta new file mode 100644 index 0000000..79623e7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingImplementationsAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1fb8b1192be4a46dcaf9b583a2be1b65 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs new file mode 100755 index 0000000..b49bb8b --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using QuickGraph.Operations; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)] + public sealed class UsingLinearAttribute : UsingAttributeBase + { + private int start; + private int step; + private int stepCount; + + public UsingLinearAttribute(int start, int stepCount) + :this(start,stepCount,1) + { + } + + public UsingLinearAttribute(int start, int stepCount, int step) + { + this.start = start; + this.stepCount = stepCount; + this.step = step; + } + + public int Start + { + get { return this.start; } + } + + public int StepCount + { + get { return this.stepCount; } + } + + public int Step + { + get { return this.step; } + } + + public override void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture) + { + LinearInt32Domain domain = new LinearInt32Domain(start, stepCount, step); + domains.Add(domain); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs.meta new file mode 100644 index 0000000..0b96f06 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLinearAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4220fdaecf0214831b2f061f681a4f35 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs new file mode 100755 index 0000000..8782cb8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs @@ -0,0 +1,53 @@ +using System; +using System.Reflection; +using System.Collections.Generic; +using QuickGraph.Operations; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)] + public sealed class UsingLiteralsAttribute : UsingAttributeBase + { + private string values; + + public UsingLiteralsAttribute(string values) + { + this.values = values; + } + + /// + /// Gets a list of values separated by ; + /// + /// + public string Values + { + get + { + return this.values; + } + } + + public override void CreateDomains( + IList domains, + ParameterInfo parameter, + IFixture fixture) + { + bool isString = parameter.ParameterType.IsAssignableFrom(typeof(string)); + List data = new List(); + foreach (string memberName in this.Values.Split(';')) + { + object cresult = null; + if (isString) + cresult = memberName.ToString(); + else + cresult = Convert.ChangeType(memberName, parameter.ParameterType); + data.Add(cresult); + } + if (data.Count == 0) + return; + + CollectionDomain domain = new CollectionDomain(data); + domains.Add(domain); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs.meta new file mode 100644 index 0000000..0ea4779 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingLiteralsAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e90486b19aa948dd97ace6e108ab66a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs new file mode 100755 index 0000000..227de7c --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Operations; +using System.Reflection; + +namespace QuickGraph.Unit +{ + public sealed class UsingXmlAttribute : UsingAttributeBase + { + private string resourceName; + private string xPath; + + public UsingXmlAttribute(string resourceName, string xPath) + { + this.resourceName = resourceName; + this.xPath = xPath; + } + + public override void CreateDomains(IList domains, ParameterInfo parameter, IFixture fixture) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs.meta new file mode 100644 index 0000000..dcc0b0d --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/UsingXmlAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 763138ed95b624a8589436fb32ae8b64 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs new file mode 100755 index 0000000..72dba7f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Xml; +using System.Xml.Schema; +using System.IO; + +namespace QuickGraph.Unit +{ + public static class XmlAssert + { + public static XmlDocument IsWellFormedXml(string xml) + { + Assert.IsNotNull(xml); + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + return doc; + } + + public static XmlDocument IsWellFormed(string fileName) + { + Assert.IsNotNull(fileName); + XmlDocument doc = new XmlDocument(); + doc.Load(fileName); + return doc; + } + + public static XmlDocument IsWellFormed(TextReader reader) + { + Assert.IsNotNull(reader); + XmlDocument doc = new XmlDocument(); + doc.Load(reader); + return doc; + } + + public static XmlDocument IsWellFormed(XmlReader reader) + { + Assert.IsNotNull(reader); + XmlDocument doc = new XmlDocument(); + doc.Load(reader); + return doc; + } + + public static XmlDocument IsWellFormed(Stream stream) + { + Assert.IsNotNull(stream); + XmlDocument doc = new XmlDocument(); + doc.Load(stream); + return doc; + } + + public static XmlSchema IsSchemaValid(Stream stream, bool warningsAsError) + { + Assert.IsNotNull(stream); + SchemaValidator validator = new SchemaValidator(warningsAsError); + return validator.ValidateSchema(stream); + } + + public static XmlSchema IsSchemaValid(TextReader reader, bool warningsAsError) + { + Assert.IsNotNull(reader); + SchemaValidator validator = new SchemaValidator(warningsAsError); + return validator.ValidateSchema(reader); + } + + public static XmlSchema IsSchemaValid(XmlReader reader, bool warningsAsError) + { + Assert.IsNotNull(reader); + SchemaValidator validator = new SchemaValidator(warningsAsError); + return validator.ValidateSchema(reader); + } + + public static XmlSchema IsSchemaValid(string fileName, bool warningsAsError) + { + Assert.IsNotNull(fileName); + using (StreamReader reader = new StreamReader(fileName)) + { + return IsSchemaValid(reader, warningsAsError); + } + } + + public static XmlSchema IsSchemaValidXml(string xml, bool warningsAsError) + { + Assert.IsNotNull(xml); + using (StringReader reader = new StringReader(xml)) + { + return IsSchemaValid(reader, warningsAsError); + } + } + + public static XmlDocument IsValidXml(string xml, bool warningsAsError) + { + Assert.IsNotNull(xml); + SchemaValidator validator = new SchemaValidator(warningsAsError); + return validator.Validate(IsWellFormedXml(xml)); + } + + public static XmlDocument IsValid(string fileName, bool warningsAsError) + { + Assert.IsNotNull(fileName); + SchemaValidator validator = new SchemaValidator(warningsAsError); + return validator.Validate(IsWellFormed(fileName)); + } + + public static XmlDocument IsValid(XmlReader reader, bool warningsAsError) + { + Assert.IsNotNull(reader); + SchemaValidator validator = new SchemaValidator(warningsAsError); + return validator.Validate(IsWellFormed(reader)); + } + + public static XmlDocument IsValid(TextReader reader, bool warningsAsError) + { + Assert.IsNotNull(reader); + SchemaValidator validator = new SchemaValidator(warningsAsError); + return validator.Validate(IsWellFormed(reader)); + } + + private sealed class SchemaValidator + { + private int errorCount = 0; + private int warningCount = 0; + private bool warningsAsError = false; + + public SchemaValidator(bool warningsAsError) + { + this.warningsAsError = warningsAsError; + } + + public XmlDocument Validate(XmlDocument document) + { + document.Validate(new ValidationEventHandler(this.ValidationEvent)); + this.ValidateResults(); + return document; + } + + public XmlDocument Validate(XmlDocument document, XmlNode nodeToValidate) + { + document.Validate(new ValidationEventHandler(this.ValidationEvent), nodeToValidate); + this.ValidateResults(); + return document; + } + + public XmlSchema ValidateSchema(Stream stream) + { + XmlSchema schema = XmlSchema.Read( + stream, + new ValidationEventHandler(ValidationEvent)); + this.ValidateResults(); + return schema; + } + + public XmlSchema ValidateSchema(TextReader reader) + { + XmlSchema schema = XmlSchema.Read( + reader, + new ValidationEventHandler(ValidationEvent)); + this.ValidateResults(); + return schema; + } + + public XmlSchema ValidateSchema(XmlReader reader) + { + XmlSchema schema = XmlSchema.Read( + reader, + new ValidationEventHandler(ValidationEvent)); + this.ValidateResults(); + return schema; + } + + private void ValidateResults() + { + Console.WriteLine("Validation: {0} errors, {1} warnings", + this.errorCount, + this.warningCount); + if (this.errorCount > 0) + Assert.Fail("{0} error in schema", this.errorCount); + if (this.warningsAsError && this.warningCount > 0) + Assert.Fail("{0} warnings in schema", this.warningCount); + } + + private void ValidationEvent(Object sender, ValidationEventArgs e) + { + switch (e.Severity) + { + case XmlSeverityType.Error: + errorCount++; break; + case XmlSeverityType.Warning: + warningCount++; break; + } + + Console.WriteLine("{0}: {1}", e.Severity, e.Message); + Console.WriteLine(e.Exception); + Console.WriteLine(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs.meta new file mode 100644 index 0000000..1474119 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlAssert.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 211839295ed914a2fa3052fac43b308d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs new file mode 100755 index 0000000..ea7bcb8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs @@ -0,0 +1,37 @@ +using System; +using System.Xml.XPath; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=true)] + public sealed class XmlDataProviderAttribute : DataProviderAttributeBase + { + private string fileName; + private XPathDocument data; + + public XmlDataProviderAttribute(string fileName) + { + if (String.IsNullOrEmpty(fileName)) + throw new ArgumentException("fileName"); + this.fileName = fileName; + } + + public string FileName + { + get { return this.fileName; } + } + + public override IXPathNavigable GetData() + { + if (this.data == null) + this.data = new XPathDocument(this.FileName); + return this.data; + } + + public override string Name + { + get { return System.IO.Path.GetFileName(this.FileName); } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs.meta new file mode 100644 index 0000000..2e5c3ca --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/XmlDataProviderAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b216b0f8e2f04106836fe9ca6b22bd4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt new file mode 100755 index 0000000..55881e1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt @@ -0,0 +1,851 @@ + + + + + + + + + + + + + + SUCCESS + + + FAILURE + + + + + s + + + + + + : + : + + + + showToolTip() + hideToolTip() + + + + javascript:mark('') + + + + + tg + javascript:toggle('tg','')[-] + + + + + tg + javascript:toggle('tg','')[+] + + + + odd + even + + + + + log + Odd + + log + Even + + + + + + successOdd + successEven + + + + + failureOdd + failureEven + + + + + ignoreOdd + ignoreEven + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tests, +success, -failures, ~ignored, *new failure, !fixed + + + , + + + , + - + , + ~ + + , + * + , + + ! + + + + + + + + 100.00 + + + + % + + + + + + + + + + + + + Log.png + + + + + + + + + + + + w + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + Type: + + + + + + Source: + + + + + + + + + : + + + + + + + +
+ +
+						
+					
+
+ + + + + +
+ + + + + + Console Output + + + + + Console Output + + +
+
+
+ + + + + + + + + + + + + + + + +
+ +
+							
+						
+
+ + +
+
+ + + \w+):\/\/\/?(?[\w.]+\/?)\S*", + RegexOptions.IgnoreCase + | RegexOptions.CultureInvariant + | RegexOptions.IgnorePatternWhitespace + | RegexOptions.Compiled + ); + private static Regex imgRegex = new Regex(@"\[img\s*src=\""(?.*?)\""\s*/\]", + RegexOptions.IgnoreCase + | RegexOptions.CultureInvariant + | RegexOptions.IgnorePatternWhitespace + | RegexOptions.Compiled + ); + private static Regex boldRegex = new Regex(@"\*\*(?.+?)\*\*", + RegexOptions.IgnoreCase + | RegexOptions.CultureInvariant + | RegexOptions.IgnorePatternWhitespace + | RegexOptions.Compiled + ); + + // XML-escapes a string + private string EscapeString(string value) + { + using(StringWriter sw = new StringWriter()) + { + foreach(char c in value) + { + if (c >= 0 && c <= 0x1F && c!=9 && c!=10 && c!=13) + { + sw.Write("&#{0};", (int)c); + } + else + { + switch(c) + { + case '<': sw.Write("<"); break; + case '>': sw.Write(">"); break; + case '&': sw.Write("&"); break; + default: sw.Write(c); break; + } + } + } + return sw.ToString(); + } + } + + // processes console text to + // add Url higlighting, image embedding, etc... + public string FormatConsole(string value) + { + string result = EscapeString(value); + result = urlRegex.Replace(result, "$&"); + result = imgRegex.Replace(result, "\"${Url}\""); + result = boldRegex.Replace(result, "${Value}"); + return result; + } +]]> + + + +
+

Machine details

+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Machine description
Machine name + +
Framework + +
OS + +
+ + + +
+
+ + + + + + + + + + +
Log + + + errors, + + + + warnings, + + + + messages +
+
+
+
+ + + + + + + + + +
+ + +
+
+ + +
+ + + + + + + + _ + + + .html + + + + + + + + + + _blank + + + + + # + + + + + + + + + + + + + + + + + + + + +

Fixtures summary

+ + + + + + +
+
+
+ + + +

+ + newfailures + New failures () +

+
+ + + + + + + +
+ +
+ +
+
+
+ + + + +

+ + fixedtests + Fixed tests () +

+
+ + + + + + + +
+ +
+ +
+
+
+ + + +

+ + newtests + New tests () +

+
+ + + + + + + +
+ +
+ +
+
+
+ + + + + +
+

Throwed exceptions

+ + + + + + + + + + +
+ + + + , + exceptions +
+ + + + + + + + +
+ +
+
+
+ +
+
+
+ + + + + + + + + rf + div +

+ + + + + + + , + + + + +

+
+ + + + + + + + +
+ + + + +
+ + , + + Categories= + + ,ApartementState. + + ,TimeOut= + [min] +
+
+ + + + + + + +
+ +
+ + + + + + +
+
+ + + + javascript:copyToClipboad('') + Repro + + + + + /ff:"" + /or+ + + + + /ff:"" + /tcf:"" /or+ /orh- + + +
+

+ 10 longuest tests +

+ + + + + + + + + + + +
+ + + +
+
+
+ +
+

+ 10 longuest fixtures +

+ + + + + + + +
+
+
+ + + + + + + + + + + + + # + + + + + # + _blank + + + + + + + + + + + New Failure! + + + Fixed! + + + New! + + + + + + td + rt + + + + + + + + + , + + + + +
+
+ closedToggle + + + + + + + + + + + + + + +
+ + +
+
+ + +
+ + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ + +
+ +
+ + +
+
\ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt.meta new file mode 100644 index 0000000..f092f5f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/common.xslt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: dcf27b113715147a9a24252d1aef7ad7 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs new file mode 100755 index 0000000..534ecec --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs @@ -0,0 +1,104 @@ +using System; +using System.IO; +using System.Reflection; +using QuickGraph.Unit.Exceptions; +using QuickGraph.Unit.Core; + +namespace QuickGraph.Unit +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true)] + public class ExpectedExceptionAttribute : TestDecoratorAttributeBase + { + private Type expectedExceptionType; + private NameMatchType messageMatchType = NameMatchType.Contains; + private string messagePattern = null; + + public ExpectedExceptionAttribute(Type expectedExceptionType) + { + if (expectedExceptionType == null) + throw new ArgumentNullException("expectedExceptionType"); + this.expectedExceptionType = expectedExceptionType; + } + + public Type ExpectedExceptionType + { + get { return this.expectedExceptionType; } + } + + public NameMatchType MessageMatchType + { + get { return this.messageMatchType; } + set { this.messageMatchType = value; } + } + + public string MessagePattern + { + get { return this.messagePattern; } + set { this.messagePattern = value; } + } + + public override ITestCase Decorate(ITestCase testCase) + { + return new ExpectedExceptionTestCase(testCase, this); + } + + private sealed class ExpectedExceptionTestCase : TypeDecoratorTestCaseBase + { + public ExpectedExceptionTestCase(ITestCase testCase, ExpectedExceptionAttribute attribute) + : base(testCase, attribute) + {} + + public override string Name + { + get { return String.Format("{0}({1})", + this.TestCase.Name, + this.Attribute.ExpectedExceptionType.Name); } + } + + public override void Run(Object fixture) + { + System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); + try + { + this.TestCase.Run(fixture); + } + catch (Exception ex) + { + Exception current = ex; + // check if current expection is expecetd or ignored + while (current != null) + { + if (current.GetType() == this.Attribute.ExpectedExceptionType) + { + VerifyException(current); + return; + } + if (current.GetType() == typeof(IgnoreException)) + { + VerifyException(current); + return; + } + current = current.InnerException; + } + current = ex; + if (current is TargetInvocationException) + current = current.InnerException; + throw new ExceptionTypeMistmatchException(this.Attribute.ExpectedExceptionType, current); + } + throw new ExceptionNotThrowedException(this.Attribute.ExpectedExceptionType); + } + + private void VerifyException(Exception ex) + { + if (String.IsNullOrEmpty(this.Attribute.MessagePattern)) + return; + + INameMatcher matcher = NameMatcherFactory.CreateMatcher( + this.Attribute.MessageMatchType, + this.Attribute.MessagePattern); + if (!matcher.IsMatch(ex.Message)) + throw new ExceptionMessageDoesNotMatchException(matcher, ex); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs.meta new file mode 100644 index 0000000..f902a27 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/expectedexceptionattribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 83122e885fbb34a548a3a130614a625b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt new file mode 100755 index 0000000..e6bb408 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt @@ -0,0 +1,20 @@ + + + + + + saved from url=(0028)http://blog.dotnetwiki.org/ + + + <xsl:value-of select="@Name"/>, + <xsl:call-template name="counter-figures"/> + + + + + + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt.meta new file mode 100644 index 0000000..2788834 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/fixturetest.xslt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 54a024fadda8f4ed6a5d5f88b0854545 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css new file mode 100755 index 0000000..3620fd8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css @@ -0,0 +1,41 @@ +h1 { font-family:Verdana; font-weight:Bold; font-size:14pt; color:#BB5500; margin-bottom:0pt; vertical-align:bottom; } +h2 { font-family:Verdana; font-weight:Bold; font-size:12pt; color:#BB5500;margin-bottom:0pt; } +h3 { font-family:Verdana; font-weight:Bold; font-size:10pt; color:#BB5500;margin-bottom:0pt; } +h4 { font-family:Verdana; font-size:10pt; margin-bottom:0pt; } +a { color:#660000;} +span.toggle { cursor:pointer; font-size:6pt;} +div.toggle { display:block; background-color:White;} +div.closedToggle{ display:none; background-color:White;} +body,p,li { font-family:Verdana; font-size:9pt;} +p.menu { font-size:8pt; font-family:Verdana; font-weight:bold} +p.copyright { font-size:7pt; font-family:Verdana;} +p.repro { font-size: 7pt; font-family:Verdana;background-color:#FEFEFE; border-width:thin; border-style:dashed; border-color:Gray;} +table { font-family:Verdana; font-weight:normal; font-size:8pt; color:black; } +table.indented { text-indent:10pt;} +tr.heading { background-color:#CCCCFF; font-weight:bold; color:black;} +tr.repro { background-color:#FFFFAF; font-size:7pt;} +tr.even { background-color:#FFFFDF;} +tr.odd { background-color:#FFFFA9;} +tr.successEven { background-color:#EFFFEF; } +tr.successOdd { background-color:#C0FFC0; } +tr.ignoreEven { background-color:#FFCC33; } +tr.ignoreOdd { background-color:#FFBB33; } +tr.failureTitle { background-color:#FF6000; color:White; font-weight:bold; } +tr.failureEven { background-color:#FFEEDE; } +tr.failureOdd { background-color:#FFD0C0; } +tr.logMessageEven { background-color:#FFFFDF; } +tr.logMessageOdd { background-color:#FFFFA9; } +tr.logWarningEven { background-color:#FFFEEE; } +tr.logWarningOdd { background-color:#FFE0D0; } +tr.logErrorEven { background-color:#FFEEDE; } +tr.logErrorOdd { background-color:#FFD0C0; } +tr.consoleTitle { background-color:#777777; color:White; font-weight:bold; } +td.smallLeft { font-size:7pt; font-weight: normal; text-align:left; vertical-align:top; } +td.smallRight { font-size:7pt; font-weight: normal; text-align:right; vertical-align:top; } +pre.console { border-color:#DDDDDD; border-style:dashed; border-width:thin; background-color:White;} +pre.stackTrace { border-color:#FF8686; border-style:dashed; border-width:thin; background-color:White;} +div.tooltip { border-width: 2;background-color: #dddddd; padding: 0;} +span.newFailure { color:#FF0000; font-size:7pt; font-weight: normal; text-align:left; vertical-align:super; font-weight:bold;} +span.fixed { color:#008F00; font-size:7pt; font-weight: normal; text-align:left; vertical-align:super; font-weight:bold;} +span.newTest { color:black; font-size:7pt; font-weight: normal; text-align:left; vertical-align:super; font-weight:bold;} +span.button { color:Navy; cursor:pointer; font-size:6.5pt; vertical-align:super; font-weight:normal;} diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css.meta new file mode 100644 index 0000000..b880e21 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.css.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: a83b074158f104c93abeb3538cf86401 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.snk b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.snk new file mode 100755 index 0000000000000000000000000000000000000000..a630ef50c86fa24e26a52eec015fa55208e88f88 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098C00=AIu009kK;!dACRXV-KH)dj;nb`? zQ-=oWiUP?hh*WlnvfVGfm9#9y3TlZ|`s83+8-J3WMR2A z=(@EZk;?n=R>be9Rx*auG5x-%)9XA~D_w_2_|t+K16R$vK4oKp(9|K;Hjx2NDzuZZ&_)S*sKMY5pd*oMVL^RY7a>LF)jWaD zH9+7eB}>7|QdR8LGqPH(c?4W_-Zl{b(M|kwR&4er(F;*P-Z(LSEDmFar`aqbIZM%6 zw)(nzh2eWNj--p4f84EudoAu?TDH4kOeNxk{9`(IPx;9YXQl5(Ka9&b?c;|mU04rN z;2YM972RJ?l%aG3p`TCVBgEtsqB;;xUn?(_NJ}fTk@tJCdf!LrWd@ikgm3K{=HtB zzaG%6^UQJ>-L@jy`SMVEVAnMS4b zz{rCok_J%M80o1MkST42B@}*!gK(`UND()vgy*%*qU`n-fDxg7McjZBIF!xWZvQ#J i7M{3*W_%R=cpVx!)OoGh(&7BFE!7GIWyT37q2QHHg&b@E literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.snk.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.snk.meta new file mode 100644 index 0000000..3badac7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/quickgraph.snk.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 3b9c6297d313745c1bb9619217e797d6 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js new file mode 100755 index 0000000..fa2780f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js @@ -0,0 +1,78 @@ +function toggle(toggleId, divId) +{ + var tog=document.getElementById(toggleId); + var div=document.getElementById(divId); + + if (tog.innerText == "[-]") + { + div.style.display = "none"; + tog.innerText = "[+]"; + } + else + { + div.style.display= "block"; + tog.innerText = "[-]"; + } +} + +function copyToClipboad(id) +{ + var el = document.getElementById(id); + window.clipboardData.setData( + "Text", + el.innerText + ); +} + +function mark(id) +{ + var element = document.getElementById(id); + + if (element.oldBackgroundColor == null) + { + element.oldBackgroundColor = element.style.backgroundColor; + element.style.backgroundColor = "#F0F0F0"; + } + else + { + element.style.backgroundColor = element.oldBackgroundColor; + element.style.oldBackgroundColor = null; + } +} + +var timerId = null; +var toolTipId = null; + +function showToolTip() +{ + toolTipId = this.tooltip; + document.onmousemove = checkEl; + checkToolTip(); +} + +function hideToolTip() +{ + var whichEl = document.all[toolTipId].style; + whichEl.visibility = "hidden"; + toolTipId = null; + + if (timerId) clearTimeout(timerId); + document.onmousemove = null; +} + +function checkToolTip() +{ + if (timerId) clearTimeout(timerID); + var left = event.clientX + document.body.scrollLeft; + var top = event.clientY + document.body.scrollTop + 20; + timerId = setTimeout("displayToolTip(" + left + ", " + top + ")", 300); +} + +function displayToolTip(left, top) +{ + document.onmousemove = null; + var whichEl = document.all[active].style; + whichEl.left = left; + whichEl.top = top; + whichEl.visibility = "visible"; +} \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js.meta new file mode 100644 index 0000000..90afc53 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/report.js.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d5d294ef3864744f29bc804b438bf83f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.banner.png b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.banner.png new file mode 100755 index 0000000000000000000000000000000000000000..26ccc991265ba550ef4ca0e43b199b0acd4cb21e GIT binary patch literal 9581 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 DbL*dc literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.png.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.png.meta new file mode 100644 index 0000000..5d49c40 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unit.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 49d172c24b15743fabda3f7296621b0d +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt new file mode 100755 index 0000000..e9b9c8f --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt @@ -0,0 +1,159 @@ + + + + + + saved from url=(0027)http://blog.dotnetwiki.org/ + + + <xsl:value-of select="@EntryAssemblyLocation"/> Test Report + + + + +

+ + Test Report: + ,
+

+

+ + + () + +

+ + + + +
+ + + + + New failures: , + Fixed tests: , + Start Time: , + End Time: , + Duration: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + batchLog +
+

Log

+ + +
+
+ + + +

Assembly setup and teardown

+ + + + + + + +
+
+
+ + + a +

+ + + + , +

+
+ + + + + + + + + + + + + + + + + + +
FullName + +
Location + +
StartTime + +
StartTime + +
+
+ + + + +
+
\ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt.meta new file mode 100644 index 0000000..c5cde16 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittest.xslt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 795dbb6ee89da46fd853f567c6012093 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt new file mode 100755 index 0000000..accdd85 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt @@ -0,0 +1,26 @@ + + + + + + saved from url=(0027)http://blog.dotnetwiki.org/ + + + <xsl:value-of select="@EntryAssemblyLocation"/> Test Report + + + + + + + + + +This document is designed to be viewed using the frames feature. +If you see this message, you are using a +non-frame-capable web client. + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt.meta new file mode 100644 index 0000000..db770be --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittestframes.xslt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: b5955fcabe74e4b7e869bc827213bf5f +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt new file mode 100755 index 0000000..a7bf8e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt @@ -0,0 +1,253 @@ + + + + + + + + + + saved from url=(0027)http://blog.dotnetwiki.org/ + + Test Summary + + + +

+ + Test Summary +

+ + + + + + + +
+ + + + + + + + + + + + + +
NameSuccess (average)Duration
+
+ + + + + + + + + #sec + + + + + + ( + + + + ) + + + + + + + + + + + + + + + + + + + + +

+ sec + +

+

+ + batchhistory + + Batch History

+
+ + + + + + + + + + + + + + + + + +
+ Time (yMMdd_hhmmss) + + Success + + + + Duration +
+ + + + + + + + + + +
+
+
+ + + + + + + 100.00 + + + + % + + + + + + + + + + + + + + + + + + +

+ + fixtureHistory + + Fixture history

+
+ + + + + + + + + + +
+ Name + Run count + Success average +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +

+ + machines + + Machines +

+
+ + + + + + + + + +
+ Name + .NET + OS +
+
+
+ + + + + + + + + + +
+ + +
+ + + + + + + + +
+ +
\ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt.meta b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt.meta new file mode 100644 index 0000000..1d7a368 --- /dev/null +++ b/src/Assets/quickgraph4unity/Editor/Tests/QuickGraph.Unit/unittesthistory.xslt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 70912547dd1294f86b83dd04b7807b6a +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/License.txt b/src/Assets/quickgraph4unity/License.txt new file mode 100644 index 0000000..da3dc93 --- /dev/null +++ b/src/Assets/quickgraph4unity/License.txt @@ -0,0 +1,31 @@ +Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. + +1. Definitions + +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the software. + +A "contributor" is any person that distributes its contribution under this license. + +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights + +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. + +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations + +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. + +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. + +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. + +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. + +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/License.txt.meta b/src/Assets/quickgraph4unity/License.txt.meta new file mode 100644 index 0000000..c3f3872 --- /dev/null +++ b/src/Assets/quickgraph4unity/License.txt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: e291f9596344f4a2986a7d4d0d809c58 +TextScriptImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime.meta b/src/Assets/quickgraph4unity/Runtime.meta new file mode 100644 index 0000000..67f5246 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 6ec3abd72777142dab2310a2b92fc228 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data.meta new file mode 100644 index 0000000..d35c12b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: c617cce6056bc4376a7447f1c2192355 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs new file mode 100755 index 0000000..94efca5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Data; + +namespace QuickGraph.Data +{ + public sealed class DataRelationEdge : IEdge + { + private readonly DataRelation relation; + public DataRelationEdge(DataRelation relation) + { + if (relation == null) + throw new ArgumentNullException("relation"); + this.relation = relation; + } + + public DataRelation Relation + { + get { return this.relation; } + } + + public DataTable Source + { + get { return this.relation.ParentTable;} + } + + public DataTable Target + { + get { return this.relation.ChildTable; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs.meta new file mode 100644 index 0000000..268aedf --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataRelationEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 39bd74b12b8fd4aaab376010d7d7e3ff +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs new file mode 100755 index 0000000..58121a6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Data; +using QuickGraph.Algorithms; + +namespace QuickGraph.Data +{ + public sealed class DataSetGraphPopulatorAlgorithm : + AlgorithmBase> + { + private readonly DataSet dataSet; + + public DataSetGraphPopulatorAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph, + DataSet dataSet + ) + : base(visitedGraph) + { + if (dataSet == null) + throw new ArgumentNullException("dataSet"); + + this.dataSet = dataSet; + } + + public DataSet DataSet + { + get { return this.dataSet; } + } + + protected override void InternalCompute() + { + foreach (DataTable table in this.DataSet.Tables) + this.VisitedGraph.AddVertex(table); + + foreach (DataRelation relation in this.DataSet.Relations) + this.VisitedGraph.AddEdge(new DataRelationEdge(relation)); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs.meta new file mode 100644 index 0000000..9ce1abb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/DataSetGraphPopulatorAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6a5a3e533069c4dd7a427a43d22629f8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties.meta new file mode 100644 index 0000000..cff9037 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 47508c611e5bd46bcb2b68daadb64387 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..c6d3569 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +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("QuickGraph.Data")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("dc10088a-bf22-4a42-b15e-47c9fd314f7a")] diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..a22822d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7c78b8f5644294dcaaaf1479fb4c63f8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj new file mode 100755 index 0000000..4ace50c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj @@ -0,0 +1,71 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {960C14D1-EDBD-40E5-8AE6-25E311551B87} + Library + Properties + QuickGraph.Data + QuickGraph.Data + SAK + SAK + SAK + SAK + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + Off + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Off + + + + + + + + + Properties\version.cs + + + + + + + + {A9A5C115-0680-44B3-A87E-5ECF4C93814E} + QuickGraph + + + + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.meta new file mode 100644 index 0000000..640b911 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: dbcae02b5a1cf438690d54dc79bc92c1 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc new file mode 100755 index 0000000..feffdec --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc.meta new file mode 100644 index 0000000..e8db203 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Data/QuickGraph.Data.csproj.vspscc.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 3ccc58af676ff4f1ea34e7fff536a03e +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz.meta new file mode 100644 index 0000000..7bc6436 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 017451d781c6845e2ab05c6728b2a7b5 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs new file mode 100755 index 0000000..4addb7b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using QuickGraph.Algorithms.Condensation; + +namespace QuickGraph.Graphviz +{ + public class CondensatedGraphRenderer : + GraphRendererBase> + where TEdge : IEdge + where TGraph : IMutableVertexAndEdgeListGraph, new() + { + public CondensatedGraphRenderer( + IVertexAndEdgeListGraph> visitedGraph) + :base(visitedGraph) + {} + + protected override void Initialize() + { + base.Initialize(); + this.Graphviz.FormatVertex+=new FormatVertexEventHandler(Graphviz_FormatVertex); + this.Graphviz.FormatEdge += new FormatEdgeEventHandler>(Graphviz_FormatEdge); + } + + + void Graphviz_FormatVertex(Object sender, FormatVertexEventArgs e) + { + StringWriter sw = new StringWriter(); + sw.WriteLine("{0}-{1}", e.Vertex.VertexCount, e.Vertex.EdgeCount); + foreach (var v in e.Vertex.Vertices) + sw.WriteLine(" {0}", v); + foreach(TEdge edge in e.Vertex.Edges) + sw.WriteLine(" {0}", edge); + e.VertexFormatter.Label = this.Graphviz.Escape(sw.ToString()); + } + + void Graphviz_FormatEdge(object sender, FormatEdgeEventArgs> e) + { + StringWriter sw = new StringWriter(); + sw.WriteLine("{0}", e.Edge.Edges.Count); + foreach (var edge in e.Edge.Edges) + sw.WriteLine(" {0}", edge); + e.EdgeFormatter.Label.Value = this.Graphviz.Escape(sw.ToString()); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs.meta new file mode 100644 index 0000000..3dcd665 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/CondensatedGraphRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b33120b322cb246d3a9e11f9462403e4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot.meta new file mode 100644 index 0000000..a537765 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 2b8bfd4de5f6e4c3aa6129d46f386a62 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs new file mode 100755 index 0000000..92fce1f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs @@ -0,0 +1,91 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.IO; + + public class GraphvizArrow + { + private GraphvizArrowClipping clipping; + private GraphvizArrowFilling filling; + private GraphvizArrowShape shape; + + public GraphvizArrow(GraphvizArrowShape shape) + { + this.shape = shape; + this.clipping = GraphvizArrowClipping.None; + this.filling = GraphvizArrowFilling.Close; + } + + public GraphvizArrow(GraphvizArrowShape shape, GraphvizArrowClipping clip, GraphvizArrowFilling fill) + { + this.shape = shape; + this.clipping = clip; + this.filling = fill; + } + + public string ToDot() + { + using (StringWriter writer = new StringWriter()) + { + if (this.filling == GraphvizArrowFilling.Open) + { + writer.Write('o'); + } + switch (this.clipping) + { + case GraphvizArrowClipping.Left: + writer.Write('l'); + break; + + case GraphvizArrowClipping.Right: + writer.Write('r'); + break; + } + writer.Write(this.shape.ToString().ToLower()); + return writer.ToString(); + } + } + + public override string ToString() + { + return this.ToDot(); + } + + public GraphvizArrowClipping Clipping + { + get + { + return this.clipping; + } + set + { + this.clipping = value; + } + } + + public GraphvizArrowFilling Filling + { + get + { + return this.filling; + } + set + { + this.filling = value; + } + } + + public GraphvizArrowShape Shape + { + get + { + return this.shape; + } + set + { + this.shape = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs.meta new file mode 100644 index 0000000..e976a50 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrow.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dfe1a8eaf409f4dbbab23a67ee7221bd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs new file mode 100755 index 0000000..87b3fc6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs @@ -0,0 +1,12 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizArrowClipping + { + None, + Left, + Right + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs.meta new file mode 100644 index 0000000..d6bb846 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowClipping.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 324b91d72fde14a9a8d71d12583cb475 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs new file mode 100755 index 0000000..b03dc49 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs @@ -0,0 +1,11 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizArrowFilling + { + Close, + Open + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs.meta new file mode 100644 index 0000000..10d1a15 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowFilling.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d3d040cfb7814349873c2fd3fd86fc4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs new file mode 100755 index 0000000..58ccae5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs @@ -0,0 +1,18 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizArrowShape + { + Box, + Crow, + Diamond, + Dot, + Inv, + None, + Normal, + Tee, + Vee + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs.meta new file mode 100644 index 0000000..e6306fa --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizArrowShape.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bd07ed306c32043c9a61a27a1c739281 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs new file mode 100755 index 0000000..1b96388 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs @@ -0,0 +1,12 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizClusterMode + { + Local, + Global, + None + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs.meta new file mode 100644 index 0000000..97420d0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizClusterMode.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d59e2dc9eb44c422189dfee09cd59d24 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs new file mode 100755 index 0000000..103bb6e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs @@ -0,0 +1,361 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Collections; + using System.Drawing; + using System.IO; + + public class GraphvizEdge + { + private string comment = null; + private GraphvizEdgeDirection dir = GraphvizEdgeDirection.Forward; + private System.Drawing.Font font = null; + private Color fontColor = Color.Black; + private GraphvizEdgeExtremity head = new GraphvizEdgeExtremity(true); + private GraphvizArrow headArrow = null; + private bool isConstrained = true; + private bool isDecorated = false; + private GraphvizEdgeLabel label = new GraphvizEdgeLabel(); + private GraphvizLayer layer = null; + private int minLength = 1; + private Color strokeColor = Color.Black; + private GraphvizEdgeStyle style = GraphvizEdgeStyle.Unspecified; + private GraphvizEdgeExtremity tail = new GraphvizEdgeExtremity(false); + private GraphvizArrow tailArrow = null; + private string tooltip = null; + private string url = null; + private double weight = 1; + + internal string GenerateDot(Hashtable pairs) + { + bool flag = false; + StringWriter writer = new StringWriter(); + foreach (DictionaryEntry entry in pairs) + { + if (flag) + { + writer.Write(", "); + } + else + { + flag = true; + } + if (entry.Value is string) + { + writer.Write("{0}=\"{1}\"", entry.Key.ToString(), entry.Value.ToString()); + continue; + } + if (entry.Value is GraphvizEdgeDirection) + { + writer.Write("{0}={1}", entry.Key.ToString(), ((GraphvizEdgeDirection) entry.Value).ToString().ToLower()); + continue; + } + if (entry.Value is GraphvizEdgeStyle) + { + writer.Write("{0}={1}", entry.Key.ToString(), ((GraphvizEdgeStyle) entry.Value).ToString().ToLower()); + continue; + } + if (entry.Value is Color) + { + Color color = (Color) entry.Value; + writer.Write("{0}=\"#{1}{2}{3}{4}\"", new object[] { entry.Key.ToString(), color.R.ToString("x2").ToUpper(), color.G.ToString("x2").ToUpper(), color.B.ToString("x2").ToUpper(), color.A.ToString("x2").ToUpper() }); + continue; + } + writer.Write(" {0}={1}", entry.Key.ToString(), entry.Value.ToString().ToLower()); + } + return writer.ToString(); + } + + public string ToDot() + { + Hashtable dic = new Hashtable(); + if (this.Comment != null) + { + dic["comment"] = this.Comment; + } + if (this.Dir != GraphvizEdgeDirection.Forward) + { + dic["dir"] = this.Dir.ToString().ToLower(); + } + if (this.Font != null) + { + dic["fontname"] = this.Font.Name; + dic["fontsize"] = this.Font.SizeInPoints; + } + if (this.FontColor != Color.Black) + { + dic["fontcolor"] = this.FontColor; + } + this.Head.AddParameters(dic); + if (this.HeadArrow != null) + { + dic["arrowhead"] = this.HeadArrow.ToDot(); + } + if (!this.IsConstrained) + { + dic["constraint"] = this.IsConstrained; + } + if (this.IsDecorated) + { + dic["decorate"] = this.IsDecorated; + } + this.Label.AddParameters(dic); + if (this.Layer != null) + { + dic["layer"] = this.Layer.Name; + } + if (this.MinLength != 1) + { + dic["minlen"] = this.MinLength; + } + if (this.StrokeColor != Color.Black) + { + dic["color"] = this.StrokeColor; + } + if (this.Style != GraphvizEdgeStyle.Unspecified) + { + dic["style"] = this.Style.ToString().ToLower(); + } + this.Tail.AddParameters(dic); + if (this.TailArrow != null) + { + dic["arrowtail"] = this.TailArrow.ToDot(); + } + if (this.ToolTip != null) + { + dic["tooltip"] = this.ToolTip; + } + if (this.Url != null) + { + dic["URL"] = this.Url; + } + if (this.Weight != 1) + { + dic["weight"] = this.Weight; + } + return this.GenerateDot(dic); + } + + public override string ToString() + { + return this.ToDot(); + } + + public string Comment + { + get + { + return this.comment; + } + set + { + this.comment = value; + } + } + + public GraphvizEdgeDirection Dir + { + get + { + return this.dir; + } + set + { + this.dir = value; + } + } + + public System.Drawing.Font Font + { + get + { + return this.font; + } + set + { + this.font = value; + } + } + + public Color FontColor + { + get + { + return this.fontColor; + } + set + { + this.fontColor = value; + } + } + + public GraphvizEdgeExtremity Head + { + get + { + return this.head; + } + set + { + this.head = value; + } + } + + public GraphvizArrow HeadArrow + { + get + { + return this.headArrow; + } + set + { + this.headArrow = value; + } + } + + public bool IsConstrained + { + get + { + return this.isConstrained; + } + set + { + this.isConstrained = value; + } + } + + public bool IsDecorated + { + get + { + return this.isDecorated; + } + set + { + this.isDecorated = value; + } + } + + public GraphvizEdgeLabel Label + { + get + { + return this.label; + } + set + { + this.label = value; + } + } + + public GraphvizLayer Layer + { + get + { + return this.layer; + } + set + { + this.layer = value; + } + } + + public int MinLength + { + get + { + return this.minLength; + } + set + { + this.minLength = value; + } + } + + public Color StrokeColor + { + get + { + return this.strokeColor; + } + set + { + this.strokeColor = value; + } + } + + public GraphvizEdgeStyle Style + { + get + { + return this.style; + } + set + { + this.style = value; + } + } + + public GraphvizEdgeExtremity Tail + { + get + { + return this.tail; + } + set + { + this.tail = value; + } + } + + public GraphvizArrow TailArrow + { + get + { + return this.tailArrow; + } + set + { + this.tailArrow = value; + } + } + + public string ToolTip + { + get + { + return this.tooltip; + } + set + { + this.tooltip = value; + } + } + + public string Url + { + get + { + return this.url; + } + set + { + this.url = value; + } + } + + public double Weight + { + get + { + return this.weight; + } + set + { + this.weight = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs.meta new file mode 100644 index 0000000..725017d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 03e7be2a799e04f839881ecd901d48fb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs new file mode 100755 index 0000000..46e8703 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs @@ -0,0 +1,13 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizEdgeDirection + { + None, + Forward, + Back, + Both + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs.meta new file mode 100644 index 0000000..0b29ce0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeDirection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 76febed9b6457431f9d64a94f5230065 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs new file mode 100755 index 0000000..e3640c1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs @@ -0,0 +1,149 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Collections; + + public class GraphvizEdgeExtremity + { + private bool isClipped; + private bool isHead; + private string label; + private string logical; + private string same; + private string tooltip; + private string url; + + public GraphvizEdgeExtremity(bool isHead) + { + this.isHead = isHead; + this.url = null; + this.isClipped = true; + this.label = null; + this.tooltip = null; + this.logical = null; + this.same = null; + } + + public void AddParameters(IDictionary dic) + { + if (dic == null) + { + throw new ArgumentNullException("dic"); + } + string text = null; + if (this.IsHead) + { + text = "head"; + } + else + { + text = "tail"; + } + if (this.Url != null) + { + dic.Add(text + "URL", this.Url); + } + if (!this.IsClipped) + { + dic.Add(text + "clip", this.IsClipped); + } + if (this.Label != null) + { + dic.Add(text + "label", this.Label); + } + if (this.ToolTip != null) + { + dic.Add(text + "tooltip", this.ToolTip); + } + if (this.Logical != null) + { + dic.Add("l" + text, this.Logical); + } + if (this.Same != null) + { + dic.Add("same" + text, this.Same); + } + } + + public bool IsClipped + { + get + { + return this.isClipped; + } + set + { + this.isClipped = value; + } + } + + public bool IsHead + { + get + { + return this.isHead; + } + } + + public string Label + { + get + { + return this.label; + } + set + { + this.label = value; + } + } + + public string Logical + { + get + { + return this.logical; + } + set + { + this.logical = value; + } + } + + public string Same + { + get + { + return this.same; + } + set + { + this.same = value; + } + } + + public string ToolTip + { + get + { + return this.tooltip; + } + set + { + this.tooltip = value; + } + } + + public string Url + { + get + { + return this.url; + } + set + { + this.url = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs.meta new file mode 100644 index 0000000..bfa04cc --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeExtremity.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e2a9f944591d745718fba2929655c8f3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs new file mode 100755 index 0000000..f3b6e30 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs @@ -0,0 +1,114 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Collections; + using System.Drawing; + + public class GraphvizEdgeLabel + { + private double angle = -25; + private double distance = 1; + private bool @float = true; + private System.Drawing.Font font = null; + private Color fontColor = Color.Black; + private string value = null; + + public void AddParameters(IDictionary dic) + { + if (this.Value != null) + { + dic["label"] = this.Value; + if (this.Angle != -25) + { + dic["labelangle"] = this.Angle; + } + if (this.Distance != 1) + { + dic["labeldistance"] = this.Distance; + } + if (!this.Float) + { + dic["labelfloat"] = this.Float; + } + if (this.Font != null) + { + dic["labelfontname"] = this.Font.Name; + dic["labelfontsize"] = this.Font.SizeInPoints; + } + } + } + + public double Angle + { + get + { + return this.angle; + } + set + { + this.angle = value; + } + } + + public double Distance + { + get + { + return this.distance; + } + set + { + this.distance = value; + } + } + + public bool Float + { + get + { + return this.@float; + } + set + { + this.@float = value; + } + } + + public System.Drawing.Font Font + { + get + { + return this.font; + } + set + { + this.font = value; + } + } + + public Color FontColor + { + get + { + return this.fontColor; + } + set + { + this.fontColor = value; + } + } + + public string Value + { + get + { + return this.value; + } + set + { + this.value = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs.meta new file mode 100644 index 0000000..faa4d13 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeLabel.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: deadb86f1415f4bc9a22d738f4a1fab6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs new file mode 100755 index 0000000..8804f40 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs @@ -0,0 +1,15 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizEdgeStyle + { + Unspecified, + Invis, + Dashed, + Dotted, + Bold, + Solid + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs.meta new file mode 100644 index 0000000..d4f5f8b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizEdgeStyle.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2cdc83e1727a9415c9d224a90224ee76 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs new file mode 100755 index 0000000..d1f499b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs @@ -0,0 +1,616 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Collections; + using System.Drawing; + using System.IO; + + public class GraphvizGraph + { + private Color backgroundColor = Color.White; + private GraphvizClusterMode clusterRank = GraphvizClusterMode.Local; + private string comment = null; + private System.Drawing.Font font = null; + private Color fontColor = Color.Black; + private bool isCentered = false; + private bool isCompounded = false; + private bool isConcentrated = false; + private bool isLandscape = false; + private bool isNormalized = false; + private bool isReMinCross = false; + private string label = null; + private GraphvizLabelJustification labelJustification = GraphvizLabelJustification.C; + private GraphvizLabelLocation labelLocation = GraphvizLabelLocation.B; + private readonly GraphvizLayerCollection layers = new GraphvizLayerCollection(); + private double mcLimit = 1; + private double nodeSeparation = 0.25; + private int nsLimit = -1; + private int nsLimit1 = -1; + private GraphvizOutputMode outputOrder = GraphvizOutputMode.BreadthFirst; + private GraphvizPageDirection pageDirection = GraphvizPageDirection.BL; + private System.Drawing.Size pageSize = new System.Drawing.Size(0, 0); + private double quantum = 0; + private GraphvizRankDirection rankDirection = GraphvizRankDirection.TB; + private double rankSeparation = 0.5; + private GraphvizRatioMode ratio = GraphvizRatioMode.Auto; + private double resolution = 0.96; + private int rotate = 0; + private int samplePoints = 8; + private int searchSize = 30; + private System.Drawing.Size size = new System.Drawing.Size(0, 0); + private string styleSheet = null; + private string url = null; + + internal string GenerateDot(Hashtable pairs) + { + bool flag = false; + StringWriter writer = new StringWriter(); + foreach (DictionaryEntry entry in pairs) + { + if (flag) + { + writer.Write(", "); + } + else + { + flag = true; + } + if (entry.Value is string) + { + writer.Write("{0}=\"{1}\"", entry.Key.ToString(), entry.Value.ToString()); + continue; + } + if (entry.Value is Color) + { + Color color = (Color) entry.Value; + writer.Write("{0}=\"#{1}{2}{3}{4}\"", new object[] { entry.Key.ToString(), color.R.ToString("x2").ToUpper(), color.G.ToString("x2").ToUpper(), color.B.ToString("x2").ToUpper(), color.A.ToString("x2").ToUpper() }); + continue; + } + if ((entry.Value is GraphvizRankDirection) || (entry.Value is GraphvizPageDirection)) + { + writer.Write("{0}={1};", entry.Key.ToString(), entry.Value.ToString()); + continue; + } + writer.Write(" {0}={1}", entry.Key.ToString(), entry.Value.ToString().ToLower()); + } + return writer.ToString(); + } + + public string ToDot() + { + Hashtable pairs = new Hashtable(); + if (this.Url != null) + { + pairs["URL"] = this.Url; + } + if (this.BackgroundColor != Color.White) + { + pairs["bgcolor"] = this.BackgroundColor; + } + if (this.IsCentered) + { + pairs["center"] = true; + } + if (this.ClusterRank != GraphvizClusterMode.Local) + { + pairs["clusterrank"] = this.ClusterRank.ToString().ToLower(); + } + if (this.Comment != null) + { + pairs["comment"] = this.Comment; + } + if (this.IsCompounded) + { + pairs["compound"] = this.IsCompounded; + } + if (this.IsConcentrated) + { + pairs["concentrated"] = this.IsConcentrated; + } + if (this.Font != null) + { + pairs["fontname"] = this.Font.Name; + pairs["fontsize"] = this.Font.SizeInPoints; + } + if (this.FontColor != Color.Black) + { + pairs["fontcolor"] = this.FontColor; + } + if (this.Label != null) + { + pairs["label"] = this.Label; + } + if (this.LabelJustification != GraphvizLabelJustification.C) + { + pairs["labeljust"] = this.LabelJustification.ToString().ToLower(); + } + if (this.LabelLocation != GraphvizLabelLocation.B) + { + pairs["labelloc"] = this.LabelLocation.ToString().ToLower(); + } + if (this.Layers.Count != 0) + { + pairs["layers"] = this.Layers.ToDot(); + } + if (this.McLimit != 1) + { + pairs["mclimit"] = this.McLimit; + } + if (this.NodeSeparation != 0.25) + { + pairs["nodesep"] = this.NodeSeparation; + } + if (this.IsNormalized) + { + pairs["normalize"] = this.IsNormalized; + } + if (this.NsLimit > 0) + { + pairs["nslimit"] = this.NsLimit; + } + if (this.NsLimit1 > 0) + { + pairs["nslimit1"] = this.NsLimit1; + } + if (this.OutputOrder != GraphvizOutputMode.BreadthFirst) + { + pairs["outputorder"] = this.OutputOrder.ToString().ToLower(); + } + if (!this.PageSize.IsEmpty) + { + pairs["page"] = string.Format("({0},{1})", this.PageSize.Width, this.PageSize.Height); + } + if (this.PageDirection != GraphvizPageDirection.BL) + { + pairs["pagedir"] = this.PageDirection.ToString().ToLower(); + } + if (this.Quantum > 0) + { + pairs["quantum"] = this.Quantum; + } + if (this.RankSeparation != 0.5) + { + pairs["ranksep"] = this.RankSeparation; + } + if (this.Ratio != GraphvizRatioMode.Auto) + { + pairs["ratio"] = this.Ratio.ToString().ToLower(); + } + if (this.IsReMinCross) + { + pairs["remincross"] = this.IsReMinCross; + } + if (this.Resolution != 0.96) + { + pairs["resolution"] = this.Resolution; + } + if (this.Rotate != 0) + { + pairs["rotate"] = this.Rotate; + } + else if (this.IsLandscape) + { + pairs["orientation"] = "[1L]*"; + } + if (this.SamplePoints != 8) + { + pairs["samplepoints"] = this.SamplePoints; + } + if (this.SearchSize != 30) + { + pairs["searchsize"] = this.SearchSize; + } + if (!this.Size.IsEmpty) + { + pairs["size"] = string.Format("({0},{1})", this.Size.Width, this.Size.Height); + } + if (this.StyleSheet != null) + { + pairs["stylesheet"] = this.StyleSheet; + } + if (this.RankDirection != GraphvizRankDirection.TB) + { + pairs["rankdir"] = this.RankDirection; + } + return this.GenerateDot(pairs); + } + + public override string ToString() + { + return this.ToDot(); + } + + public Color BackgroundColor + { + get + { + return this.backgroundColor; + } + set + { + this.backgroundColor = value; + } + } + + public GraphvizClusterMode ClusterRank + { + get + { + return this.clusterRank; + } + set + { + this.clusterRank = value; + } + } + + public string Comment + { + get + { + return this.comment; + } + set + { + this.comment = value; + } + } + + public System.Drawing.Font Font + { + get + { + return this.font; + } + set + { + this.font = value; + } + } + + public Color FontColor + { + get + { + return this.fontColor; + } + set + { + this.fontColor = value; + } + } + + public bool IsCentered + { + get + { + return this.isCentered; + } + set + { + this.isCentered = value; + } + } + + public bool IsCompounded + { + get + { + return this.isCompounded; + } + set + { + this.isCompounded = value; + } + } + + public bool IsConcentrated + { + get + { + return this.isConcentrated; + } + set + { + this.isConcentrated = value; + } + } + + public bool IsLandscape + { + get + { + return this.isLandscape; + } + set + { + this.isLandscape = value; + } + } + + public bool IsNormalized + { + get + { + return this.isNormalized; + } + set + { + this.isNormalized = value; + } + } + + public bool IsReMinCross + { + get + { + return this.isReMinCross; + } + set + { + this.isReMinCross = value; + } + } + + public string Label + { + get + { + return this.label; + } + set + { + this.label = value; + } + } + + public GraphvizLabelJustification LabelJustification + { + get + { + return this.labelJustification; + } + set + { + this.labelJustification = value; + } + } + + public GraphvizLabelLocation LabelLocation + { + get + { + return this.labelLocation; + } + set + { + this.labelLocation = value; + } + } + + public GraphvizLayerCollection Layers + { + get + { + return this.layers; + } + } + + public double McLimit + { + get + { + return this.mcLimit; + } + set + { + this.mcLimit = value; + } + } + + public double NodeSeparation + { + get + { + return this.nodeSeparation; + } + set + { + this.nodeSeparation = value; + } + } + + public int NsLimit + { + get + { + return this.nsLimit; + } + set + { + this.nsLimit = value; + } + } + + public int NsLimit1 + { + get + { + return this.nsLimit1; + } + set + { + this.nsLimit1 = value; + } + } + + public GraphvizOutputMode OutputOrder + { + get + { + return this.outputOrder; + } + set + { + this.outputOrder = value; + } + } + + public GraphvizPageDirection PageDirection + { + get + { + return this.pageDirection; + } + set + { + this.pageDirection = value; + } + } + + public System.Drawing.Size PageSize + { + get + { + return this.pageSize; + } + set + { + this.pageSize = value; + } + } + + public double Quantum + { + get + { + return this.quantum; + } + set + { + this.quantum = value; + } + } + + public GraphvizRankDirection RankDirection + { + get + { + return this.rankDirection; + } + set + { + this.rankDirection = value; + } + } + + public double RankSeparation + { + get + { + return this.rankSeparation; + } + set + { + this.rankSeparation = value; + } + } + + public GraphvizRatioMode Ratio + { + get + { + return this.ratio; + } + set + { + this.ratio = value; + } + } + + public double Resolution + { + get + { + return this.resolution; + } + set + { + this.resolution = value; + } + } + + public int Rotate + { + get + { + return this.rotate; + } + set + { + this.rotate = value; + } + } + + public int SamplePoints + { + get + { + return this.samplePoints; + } + set + { + this.samplePoints = value; + } + } + + public int SearchSize + { + get + { + return this.searchSize; + } + set + { + this.searchSize = value; + } + } + + public System.Drawing.Size Size + { + get + { + return this.size; + } + set + { + this.size = value; + } + } + + public string StyleSheet + { + get + { + return this.styleSheet; + } + set + { + this.styleSheet = value; + } + } + + public string Url + { + get + { + return this.url; + } + set + { + this.url = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs.meta new file mode 100644 index 0000000..f15cab7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6eccec881ba2845fdba888b9c573c476 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs new file mode 100755 index 0000000..e9a88df --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs @@ -0,0 +1,52 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.ComponentModel; + + public enum GraphvizImageType + { + [Description("Client-side imagemaps")] + Cmap = 6, + [Description("Figure format")] + Fig = 0, + [Description("Gd format")] + Gd = 1, + [Description("Gd2 format")] + Gd2 = 2, + [Description("GIF format")] + Gif = 3, + [Description("HP-GL/2 format")] + Hpgl = 4, + [Description("Server-side imagemaps")] + Imap = 5, + [Description("JPEG format")] + Jpeg = 7, + [Description("FrameMaker MIF format")] + Mif = 8, + [Description("MetaPost")] + Mp = 9, + [Description("PCL format")] + Pcl = 10, + [Description("PIC format")] + Pic = 11, + [Description("plain text format")] + PlainText = 12, + [Description("Portable Network Graphics format")] + Png = 13, + [Description("Postscript")] + Ps = 14, + [Description("PostScript for PDF")] + Ps2 = 15, + [Description("Scalable Vector Graphics")] + Svg = 0x10, + [Description("Scalable Vector Graphics, gzipped")] + Svgz = 0x11, + [Description("VRML")] + Vrml = 0x12, + [Description("Visual Thought format")] + Vtx = 0x13, + [Description("Wireless BitMap format")] + Wbmp = 20 + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs.meta new file mode 100644 index 0000000..66cf2be --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizImageType.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 357e7b8455f214844beff6ae8c73dd8d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs new file mode 100755 index 0000000..91423d4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs @@ -0,0 +1,12 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizLabelJustification + { + L, + R, + C + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs.meta new file mode 100644 index 0000000..acb1dc3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelJustification.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b46c056b0a92244f7a13964fdaba69b4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs new file mode 100755 index 0000000..a6bd802 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs @@ -0,0 +1,11 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizLabelLocation + { + T, + B + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs.meta new file mode 100644 index 0000000..ce6cf8d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLabelLocation.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e49b9dfdb1ddd47cc8db80ce9bf20ba5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs new file mode 100755 index 0000000..5daa3f5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs @@ -0,0 +1,35 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public class GraphvizLayer + { + private string name; + + public GraphvizLayer(string name) + { + if ((name == null) || (name.Length == 0)) + { + throw new ArgumentNullException("name"); + } + if (name.Length == 0) + { + throw new ArgumentException("name is empty"); + } + this.name = name; + } + + public string Name + { + get + { + return this.name; + } + set + { + this.name = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs.meta new file mode 100644 index 0000000..55c9b3c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b863f8cf92134466980f9d45d12b9ff +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs new file mode 100755 index 0000000..14cc593 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs @@ -0,0 +1,72 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.IO; + using System.Reflection; + using System.Collections.ObjectModel; + + public class GraphvizLayerCollection : Collection + { + private string m_Separators = ":"; + + public GraphvizLayerCollection() + {} + + public GraphvizLayerCollection(GraphvizLayer[] items) + :base(items) + {} + + public GraphvizLayerCollection(GraphvizLayerCollection items) + :base(items) + {} + + public string ToDot() + { + if (base.Count == 0) + { + return null; + } + using (StringWriter writer = new StringWriter()) + { + writer.Write("layers=\""); + bool flag = false; + foreach (GraphvizLayer layer in this) + { + if (flag) + { + writer.Write(this.Separators); + } + else + { + flag = true; + } + writer.Write(layer.Name); + } + writer.WriteLine("\";"); + writer.WriteLine("layersep=\"{0}\"", this.Separators); + return writer.ToString(); + } + } + + public string Separators + { + get + { + return this.m_Separators; + } + set + { + if (value == null) + { + throw new ArgumentNullException("separator is null"); + } + if (value.Length == 0) + { + throw new ArgumentException("separator is empty"); + } + this.m_Separators = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs.meta new file mode 100644 index 0000000..0012731 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizLayerCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a01c5b7be85a4170a69f3e97d7aa3ac +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs new file mode 100755 index 0000000..aa79e89 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs @@ -0,0 +1,12 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizOutputMode + { + BreadthFirst, + NodesFirst, + EdgesFirst + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs.meta new file mode 100644 index 0000000..1741ba9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizOutputMode.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed23e5418aede44d995a4dd54f49e7cd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs new file mode 100755 index 0000000..8e3a19e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs @@ -0,0 +1,17 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizPageDirection + { + BL, + BR, + TL, + TR, + RB, + RT, + LB, + LT + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs.meta new file mode 100644 index 0000000..1c2753c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizPageDirection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b3677c5b03c949ec9943343e74e6ca9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs new file mode 100755 index 0000000..9d673de --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs @@ -0,0 +1,11 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizRankDirection + { + LR, + TB + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs.meta new file mode 100644 index 0000000..86f85cb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRankDirection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0c464faf3822845af934718e48bd1c19 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs new file mode 100755 index 0000000..85211e7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs @@ -0,0 +1,12 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizRatioMode + { + Fill, + Compress, + Auto + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs.meta new file mode 100644 index 0000000..2782c57 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRatioMode.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 34d7b75ac4a9f4097b6a3cbd43341393 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs new file mode 100755 index 0000000..6d0c30f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs @@ -0,0 +1,45 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Text; + + public class GraphvizRecord + { + private readonly GraphvizRecordCellCollection cells = new GraphvizRecordCellCollection(); + + public string ToDot() + { + if (this.Cells.Count == 0) + { + return ""; + } + StringBuilder builder = new StringBuilder(); + bool flag = false; + foreach (GraphvizRecordCell cell in this.Cells) + { + if (flag) + { + builder.AppendFormat(" | {0}", cell.ToDot()); + continue; + } + builder.Append(cell.ToDot()); + flag = true; + } + return builder.ToString(); + } + + public override string ToString() + { + return this.ToDot(); + } + + public GraphvizRecordCellCollection Cells + { + get + { + return this.cells; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs.meta new file mode 100644 index 0000000..ed5d523 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecord.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3d48b75b0d43446f9be7aed61a13be3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs new file mode 100755 index 0000000..aaaa510 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs @@ -0,0 +1,113 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Text; + + public class GraphvizRecordCell + { + private readonly GraphvizRecordCellCollection cells = new GraphvizRecordCellCollection(); + private GraphvizRecordEscaper escaper = new GraphvizRecordEscaper(); + private string port = null; + private string text = null; + + public string ToDot() + { + StringBuilder builder = new StringBuilder(); + if (this.HasPort) + { + builder.AppendFormat("<{0}> ", this.Escaper.Escape(this.Port)); + } + if (this.HasText) + { + builder.AppendFormat("{0}", this.Escaper.Escape(this.Text)); + } + if (this.Cells.Count > 0) + { + builder.Append(" { "); + bool flag = false; + foreach (GraphvizRecordCell cell in this.Cells) + { + if (flag) + { + builder.AppendFormat(" | {0}", cell.ToDot()); + continue; + } + builder.Append(cell.ToDot()); + flag = true; + } + builder.Append(" } "); + } + return builder.ToString(); + } + + public override string ToString() + { + return this.ToDot(); + } + + public GraphvizRecordCellCollection Cells + { + get + { + return this.cells; + } + } + + protected GraphvizRecordEscaper Escaper + { + get + { + return this.escaper; + } + } + + public bool HasPort + { + get + { + if (this.Port != null) + { + return (this.Port.Length > 0); + } + return false; + } + } + + public bool HasText + { + get + { + if (this.text != null) + { + return (this.text.Length > 0); + } + return false; + } + } + + public string Port + { + get + { + return this.port; + } + set + { + this.port = value; + } + } + + public string Text + { + get + { + return this.text; + } + set + { + this.text = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs.meta new file mode 100644 index 0000000..4bb21e8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCell.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1073b5222cbcb4774b9514be3e6c77fb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs new file mode 100755 index 0000000..3498d2d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs @@ -0,0 +1,21 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Reflection; + using System.Collections.ObjectModel; + + public sealed class GraphvizRecordCellCollection : Collection + { + public GraphvizRecordCellCollection() + {} + + public GraphvizRecordCellCollection(GraphvizRecordCell[] items) + :base(items) + {} + + public GraphvizRecordCellCollection(GraphvizRecordCellCollection items) + :base(items) + {} + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs.meta new file mode 100644 index 0000000..53d0352 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordCellCollection.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5893afdcdc59047b2a1a138a2c634efa +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs new file mode 100755 index 0000000..8b1ae05 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs @@ -0,0 +1,29 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Text.RegularExpressions; + + public sealed class GraphvizRecordEscaper + { + private Regex escapeRegExp = new Regex("(?\\n)|(?\\[|\\]|\\||<|>|\"| )", RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.Multiline); + + public string Escape(string text) + { + if (text == null) + { + throw new ArgumentNullException("text"); + } + return this.escapeRegExp.Replace(text, new System.Text.RegularExpressions.MatchEvaluator(this.MatchEvaluator)); + } + + public string MatchEvaluator(Match m) + { + if (m.Groups["Common"] != null) + { + return string.Format(@"\{0}", m.Value); + } + return @"\n"; + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs.meta new file mode 100644 index 0000000..9c4a9dd --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizRecordEscaper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 63f78a066da214d84ae8a23a83de6d0b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs new file mode 100755 index 0000000..dece249 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs @@ -0,0 +1,487 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + using System.Collections; + using System.Drawing; + using System.IO; + + public class GraphvizVertex + { + private string bottomLabel = null; + private string comment = null; + private double distorsion = 0; + private Color fillColor = Color.White; + private bool fixedSize = false; + private System.Drawing.Font font = null; + private Color fontColor = Color.Black; + private string group = null; + private string label = null; + private GraphvizLayer layer = null; + private double orientation = 0; + private int peripheries = -1; + private GraphvizRecord record = new GraphvizRecord(); + private bool regular = false; + private GraphvizVertexShape shape = GraphvizVertexShape.Unspecified; + private int sides = 4; + private SizeF size = new SizeF(0f, 0f); + private double skew = 0; + private Color strokeColor = Color.Black; + private GraphvizVertexStyle style = GraphvizVertexStyle.Unspecified; + private string toolTip = null; + private string topLabel = null; + private string url = null; + private double z = -1; + + internal string GenerateDot(Hashtable pairs) + { + bool flag = false; + StringWriter writer = new StringWriter(); + foreach (DictionaryEntry entry in pairs) + { + if (flag) + { + writer.Write(", "); + } + else + { + flag = true; + } + if (entry.Value is string) + { + writer.Write("{0}=\"{1}\"", entry.Key.ToString(), entry.Value.ToString()); + continue; + } + if (entry.Value is GraphvizVertexShape) + { + writer.Write("{0}={1}", entry.Key.ToString(), ((GraphvizVertexShape) entry.Value).ToString().ToLower()); + continue; + } + if (entry.Value is GraphvizVertexStyle) + { + writer.Write("{0}={1}", entry.Key.ToString(), ((GraphvizVertexStyle) entry.Value).ToString().ToLower()); + continue; + } + if (entry.Value is Color) + { + Color color = (Color) entry.Value; + writer.Write("{0}=\"#{1}{2}{3}{4}\"", new object[] { entry.Key.ToString(), color.R.ToString("x2").ToUpper(), color.G.ToString("x2").ToUpper(), color.B.ToString("x2").ToUpper(), color.A.ToString("x2").ToUpper() }); + continue; + } + if (entry.Value is GraphvizRecord) + { + writer.WriteLine("{0}=\"{1}\"", entry.Key.ToString(), ((GraphvizRecord) entry.Value).ToDot()); + continue; + } + writer.Write(" {0}={1}", entry.Key.ToString(), entry.Value.ToString().ToLower()); + } + return writer.ToString(); + } + + public string ToDot() + { + Hashtable pairs = new Hashtable(); + if (this.Font != null) + { + pairs["fontname"] = this.Font.Name; + pairs["fontsize"] = this.Font.SizeInPoints; + } + if (this.FontColor != Color.Black) + { + pairs["fontcolor"] = this.FontColor; + } + if (this.Shape != GraphvizVertexShape.Unspecified) + { + pairs["shape"] = this.Shape; + } + if (this.Style != GraphvizVertexStyle.Unspecified) + { + pairs["style"] = this.Style; + } + if (this.Shape == GraphvizVertexShape.Record) + { + pairs["label"] = this.Record; + } + else if (this.Label != null) + { + pairs["label"] = this.Label; + } + if (this.FixedSize) + { + pairs["fixedsize"] = true; + if (this.Size.Height > 0f) + { + pairs["height"] = this.Size.Height; + } + if (this.Size.Width > 0f) + { + pairs["width"] = this.Size.Width; + } + } + if (this.StrokeColor != Color.Black) + { + pairs["color"] = this.StrokeColor; + } + if (this.FillColor != Color.White) + { + pairs["fillcolor"] = this.FillColor; + } + if (this.Regular) + { + pairs["regular"] = this.Regular; + } + if (this.Url != null) + { + pairs["URL"] = this.Url; + } + if (this.ToolTip != null) + { + pairs["tooltip"] = this.ToolTip; + } + if (this.Comment != null) + { + pairs["comment"] = this.Comment; + } + if (this.Group != null) + { + pairs["group"] = this.Group; + } + if (this.Layer != null) + { + pairs["layer"] = this.Layer.Name; + } + if (this.Orientation > 0) + { + pairs["orientation"] = this.Orientation; + } + if (this.Peripheries >= 0) + { + pairs["peripheries"] = this.Peripheries; + } + if (this.Z > 0) + { + pairs["z"] = this.Z; + } + if (((this.Style == GraphvizVertexStyle.Diagonals) || (this.Shape == GraphvizVertexShape.MCircle)) || ((this.Shape == GraphvizVertexShape.MDiamond) || (this.Shape == GraphvizVertexShape.MSquare))) + { + if (this.TopLabel != null) + { + pairs["toplabel"] = this.TopLabel; + } + if (this.BottomLabel != null) + { + pairs["bottomlable"] = this.BottomLabel; + } + } + if (this.Shape == GraphvizVertexShape.Polygon) + { + if (this.Sides != 0) + { + pairs["sides"] = this.Sides; + } + if (this.Skew != 0) + { + pairs["skew"] = this.Skew; + } + if (this.Distorsion != 0) + { + pairs["distorsion"] = this.Distorsion; + } + } + return this.GenerateDot(pairs); + } + + public override string ToString() + { + return this.ToDot(); + } + + public string BottomLabel + { + get + { + return this.bottomLabel; + } + set + { + this.bottomLabel = value; + } + } + + public string Comment + { + get + { + return this.comment; + } + set + { + this.comment = value; + } + } + + public double Distorsion + { + get + { + return this.distorsion; + } + set + { + this.distorsion = value; + } + } + + public Color FillColor + { + get + { + return this.fillColor; + } + set + { + this.fillColor = value; + } + } + + public bool FixedSize + { + get + { + return this.fixedSize; + } + set + { + this.fixedSize = value; + } + } + + public System.Drawing.Font Font + { + get + { + return this.font; + } + set + { + this.font = value; + } + } + + public Color FontColor + { + get + { + return this.fontColor; + } + set + { + this.fontColor = value; + } + } + + public string Group + { + get + { + return this.group; + } + set + { + this.group = value; + } + } + + public string Label + { + get + { + return this.label; + } + set + { + this.label = value; + } + } + + public GraphvizLayer Layer + { + get + { + return this.layer; + } + set + { + this.layer = value; + } + } + + public double Orientation + { + get + { + return this.orientation; + } + set + { + this.orientation = value; + } + } + + public int Peripheries + { + get + { + return this.peripheries; + } + set + { + this.peripheries = value; + } + } + + public GraphvizRecord Record + { + get + { + return this.record; + } + set + { + this.record = value; + } + } + + public bool Regular + { + get + { + return this.regular; + } + set + { + this.regular = value; + } + } + + public GraphvizVertexShape Shape + { + get + { + return this.shape; + } + set + { + this.shape = value; + } + } + + public int Sides + { + get + { + return this.sides; + } + set + { + this.sides = value; + } + } + + public SizeF Size + { + get + { + return this.size; + } + set + { + this.size = value; + } + } + + public double Skew + { + get + { + return this.skew; + } + set + { + this.skew = value; + } + } + + public Color StrokeColor + { + get + { + return this.strokeColor; + } + set + { + this.strokeColor = value; + } + } + + public GraphvizVertexStyle Style + { + get + { + return this.style; + } + set + { + this.style = value; + } + } + + public string ToolTip + { + get + { + return this.toolTip; + } + set + { + this.toolTip = value; + } + } + + public string TopLabel + { + get + { + return this.topLabel; + } + set + { + this.topLabel = value; + } + } + + public string Url + { + get + { + return this.url; + } + set + { + this.url = value; + } + } + + public double Z + { + get + { + return this.z; + } + set + { + this.z = value; + } + } + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs.meta new file mode 100644 index 0000000..af7ff5f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertex.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 894af1cb17e7b4970b163fb493fdd1b8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs new file mode 100755 index 0000000..cda007a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs @@ -0,0 +1,38 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizVertexShape + { + Unspecified, + Box, + Polygon, + Ellipse, + Circle, + Point, + Egg, + Triangle, + Plaintext, + Diamond, + Trapezium, + Parallelogram, + House, + Pentagon, + Hexagon, + Septagon, + Octagon, + DoubleCircle, + DoubleOctagon, + TripleOctagon, + InvTriangle, + InvTrapezium, + InvHouse, + MDiamond, + MSquare, + MCircle, + Rect, + Rectangle, + Record + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs.meta new file mode 100644 index 0000000..987a313 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexShape.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5748259e4140c46febee177b59066283 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs new file mode 100755 index 0000000..d47dd43 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs @@ -0,0 +1,18 @@ +namespace QuickGraph.Graphviz.Dot +{ + using System; + + public enum GraphvizVertexStyle + { + Unspecified, + Filled, + Diagonals, + Rounded, + Invis, + Dashed, + Dotted, + Bold, + Solid + } +} + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs.meta new file mode 100644 index 0000000..6f7ae56 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/Dot/GraphvizVertexStyle.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d0ca4736d3cf46e6a81afe352df990e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs new file mode 100755 index 0000000..aa9f761 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; +using QuickGraph.Algorithms.Condensation; + +namespace QuickGraph.Graphviz +{ + public class EdgeMergeCondensatedGraphRenderer : + GraphRendererBase> + where TEdge : IEdge + { + public EdgeMergeCondensatedGraphRenderer( + IVertexAndEdgeListGraph> visitedGraph) + :base(visitedGraph) + { } + + protected override void Initialize() + { + base.Initialize(); + this.Graphviz.FormatVertex += new FormatVertexEventHandler(Graphviz_FormatVertex); + this.Graphviz.FormatEdge += new FormatEdgeEventHandler>(Graphviz_FormatEdge); + } + + void Graphviz_FormatEdge(object sender, FormatEdgeEventArgs> e) + { + StringWriter sw = new StringWriter(); + sw.WriteLine("{0}", e.Edge.Edges.Count); + foreach (var edge in e.Edge.Edges) + sw.WriteLine(" {0}", edge); + e.EdgeFormatter.Label.Value = this.Graphviz.Escape(sw.ToString()); + } + + void Graphviz_FormatVertex(Object sender, FormatVertexEventArgs e) + { + e.VertexFormatter.Label = e.Vertex.ToString(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs.meta new file mode 100644 index 0000000..91106db --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/EdgeMergeCondensatedGraphRenderer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9a64c9ffbdad4f17b4b2fcc05b18674 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs new file mode 100755 index 0000000..2400145 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Graphviz.Dot; +using System.IO; + +namespace QuickGraph.Graphviz +{ + /// + /// Default dot engine implementation, writes dot code to disk + /// + public sealed class FileDotEngine : IDotEngine + { + public string Run(GraphvizImageType imageType, string dot, string outputFileName) + { + string output = outputFileName + ".dot"; + File.WriteAllText(output, dot); + return output; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs.meta new file mode 100644 index 0000000..dbbb207 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FileDotEngine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0750f6e22b0394f039345116b3ff2588 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs new file mode 100755 index 0000000..53585b2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs @@ -0,0 +1,35 @@ +using System; +using QuickGraph.Graphviz.Dot; + +namespace QuickGraph.Graphviz +{ + public sealed class FormatEdgeEventArgs : EdgeEventArgs + where E : IEdge + { + private GraphvizEdge edgeFormatter; + + public FormatEdgeEventArgs(GraphvizEdge edgeFormatter, E e) + : base(e) + { + if (edgeFormatter == null) + throw new ArgumentNullException("edgeFormatter"); + this.edgeFormatter = edgeFormatter; + } + + /// + /// Edge formatter + /// + public GraphvizEdge EdgeFormatter + { + get + { + return edgeFormatter; + } + } + } + + public delegate void FormatEdgeEventHandler( + object sender, + FormatEdgeEventArgs e) + where TEdge : IEdge; +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs.meta new file mode 100644 index 0000000..b46cfd3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatEdgeEventArgs.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a975a28380cd424f8c71ec9eb987cca +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs new file mode 100755 index 0000000..dd542cc --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs @@ -0,0 +1,30 @@ +using System; +using QuickGraph.Graphviz.Dot; + +namespace QuickGraph.Graphviz +{ + public sealed class FormatVertexEventArgs : VertexEventArgs + { + private GraphvizVertex vertexFormatter; + + public FormatVertexEventArgs(GraphvizVertex vertexFormatter, V v) + : base(v) + { + if (vertexFormatter == null) + throw new ArgumentNullException("vertexFormatter"); + this.vertexFormatter = vertexFormatter; + } + + public GraphvizVertex VertexFormatter + { + get + { + return vertexFormatter; + } + } + } + + public delegate void FormatVertexEventHandler( + Object sender, + FormatVertexEventArgs e); +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs.meta new file mode 100644 index 0000000..ff72aac --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/FormatVertexEventArgs.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 607ce1dc3ac0343459fc883904f63155 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs new file mode 100755 index 0000000..4eafb11 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs @@ -0,0 +1,44 @@ +using System; +using System.Drawing; +using QuickGraph.Graphviz.Dot; + +namespace QuickGraph.Graphviz +{ + public abstract class GraphRendererBase + where TEdge : IEdge + { + private GraphvizAlgorithm graphviz; + + public GraphRendererBase( + IVertexAndEdgeSet visitedGraph) + { + this.graphviz = new GraphvizAlgorithm(visitedGraph); + this.Initialize(); + } + + protected virtual void Initialize() + { + this.graphviz.CommonVertexFormat.Style = GraphvizVertexStyle.Filled; + this.graphviz.CommonVertexFormat.FillColor = System.Drawing.Color.LightYellow; + this.graphviz.CommonVertexFormat.Font = new System.Drawing.Font("Tahoma", 8.25F); + this.graphviz.CommonVertexFormat.Shape = GraphvizVertexShape.Box; + + this.graphviz.CommonEdgeFormat.Font = new System.Drawing.Font("Tahoma", 8.25F); + } + + public GraphvizAlgorithm Graphviz + { + get { return this.graphviz; } + } + + public IVertexAndEdgeSet VisitedGraph + { + get { return this.graphviz.VisitedGraph; } + } + + public string Generate(IDotEngine dot, string fileName) + { + return this.graphviz.Generate(dot, fileName); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs.meta new file mode 100644 index 0000000..55376ff --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphRendererBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 20fe7f72aa5b44d56a76dfb99e42b2f7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs new file mode 100755 index 0000000..fc0551f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs @@ -0,0 +1,236 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Collections.Generic; +using QuickGraph.Graphviz.Dot; + +namespace QuickGraph.Graphviz +{ + public sealed class GraphvizAlgorithm + where TEdge : IEdge + { + private readonly static Regex writeLineReplace = new Regex("\n", RegexOptions.Compiled | RegexOptions.Multiline); + private IVertexAndEdgeSet visitedGraph; + private StringWriter output; + private GraphvizImageType imageType; + private readonly Dictionary vertexIds = new Dictionary(); + + private GraphvizGraph graphFormat; + private GraphvizVertex commonVertexFormat; + private GraphvizEdge commonEdgeFormat; + + public GraphvizAlgorithm(IVertexAndEdgeSet g) + :this(g,".",GraphvizImageType.Png) + {} + + public GraphvizAlgorithm( + IVertexAndEdgeSet g, + String path, + GraphvizImageType imageType + ) + { + if (g == null) + throw new ArgumentNullException("g"); + if (path == null) + throw new ArgumentNullException("path"); + this.visitedGraph = g; + this.imageType = imageType; + this.graphFormat = new GraphvizGraph(); + this.commonVertexFormat = new GraphvizVertex(); + this.commonEdgeFormat = new GraphvizEdge(); + } + + public string Escape(string value) + { + return writeLineReplace.Replace(value, "\\n"); + } + + public GraphvizGraph GraphFormat + { + get + { + return graphFormat; + } + } + + public GraphvizVertex CommonVertexFormat + { + get + { + return commonVertexFormat; + } + } + + public GraphvizEdge CommonEdgeFormat + { + get + { + return commonEdgeFormat; + } + } + + public IVertexAndEdgeSet VisitedGraph + { + get + { + return visitedGraph; + } + set + { + if (value == null) + throw new ArgumentNullException("graph"); + visitedGraph = value; + } + } + + /// + /// Dot output stream. + /// + public StringWriter Output + { + get + { + return output; + } + } + + /// + /// Current image output type + /// + public GraphvizImageType ImageType + { + get + { + return imageType; + } + set + { + imageType = value; + } + } +/* + /// + /// Event raised while drawing a cluster + /// + public event FormatClusterEventHandler FormatCluster; + private void OnFormatCluster(IVertexAndEdgeListGraph cluster) + { + if (FormatCluster != null) + { + FormatClusterEventArgs args = + new FormatClusterEventArgs(cluster, new GraphvizGraph()); + FormatCluster(this, args); + string s = args.GraphFormat.ToDot(); + if (s.Length != 0) + Output.WriteLine(s); + } + } +*/ + public event FormatVertexEventHandler FormatVertex; + private void OnFormatVertex(TVertex v) + { + Output.Write("{0} ", this.vertexIds[v]); + if (FormatVertex != null) + { + GraphvizVertex gv = new GraphvizVertex(); + gv.Label = v.ToString(); + FormatVertex(this, new FormatVertexEventArgs(gv, v)); + + string s = gv.ToDot(); + if (s.Length != 0) + Output.Write("[{0}]", s); + } + Output.WriteLine(";"); + } + + public event FormatEdgeEventHandler FormatEdge; + private void OnFormatEdge(TEdge e) + { + if (FormatEdge != null) + { + GraphvizEdge ev = new GraphvizEdge(); + FormatEdge(this, new FormatEdgeEventArgs(ev, e)); + Output.Write(" {0}", ev.ToDot()); + } + } + + public string Generate(IDotEngine dot, string outputFileName) + { + if (dot == null) + throw new ArgumentNullException("dot"); + if (outputFileName == null) + throw new ArgumentNullException("outputFileName"); + + this.vertexIds.Clear(); + + this.output = new StringWriter(); + + // build vertex id map + int i=0; + foreach(TVertex v in this.VisitedGraph.Vertices) + this.vertexIds.Add(v,i++); + + Output.WriteLine("digraph G {"); + + String gf = GraphFormat.ToDot(); + if (gf.Length > 0) + Output.WriteLine(gf); + String vf = CommonVertexFormat.ToDot(); + if (vf.Length > 0) + Output.WriteLine("node [{0}];", vf); + String ef = CommonEdgeFormat.ToDot(); + if (ef.Length > 0) + Output.WriteLine("edge [{0}];", ef); + + // initialize vertex map + IDictionary colors = new Dictionary(); + foreach (var v in VisitedGraph.Vertices) + colors[v] = GraphColor.White; + IDictionary edgeColors = new Dictionary(); + foreach (var e in VisitedGraph.Edges) + edgeColors[e] = GraphColor.White; + + WriteVertices(colors, VisitedGraph.Vertices); + WriteEdges(edgeColors, VisitedGraph.Edges); + + Output.WriteLine("}"); + + return dot.Run(ImageType, Output.ToString(), outputFileName); + } + + private void WriteVertices( + IDictionary colors, + IEnumerable vertices) + { + foreach (var v in vertices) + { + if (colors[v] == GraphColor.White) + { + OnFormatVertex(v); + colors[v] = GraphColor.Black; + } + } + } + + private void WriteEdges( + IDictionary edgeColors, + IEnumerable edges) + { + foreach (var e in edges) + { + if (edgeColors[e] != GraphColor.White) + continue; + + Output.Write("{0} -> {1} [", + this.vertexIds[e.Source], + this.vertexIds[e.Target] + ); + + OnFormatEdge(e); + Output.WriteLine("];"); + + edgeColors[e] = GraphColor.Black; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs.meta new file mode 100644 index 0000000..83aead3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/GraphvizAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 133f65bbc0db04d38bfb9d7a93da4a53 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs new file mode 100755 index 0000000..e69e651 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Graphviz.Dot; + +namespace QuickGraph.Graphviz +{ + public interface IDotEngine + { + string Run( + GraphvizImageType imageType, + string dot, + string outputFileName); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs.meta new file mode 100644 index 0000000..7b0e987 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/IDotEngine.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 24892f975659a4ea3ae986f9275af5ea +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj new file mode 100755 index 0000000..32d274e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj @@ -0,0 +1,111 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {595D6322-637A-4A36-97F1-D53F3F9ECEA7} + Library + Properties + QuickGraph.Graphviz + QuickGraph.Graphviz + SAK + SAK + SAK + SAK + true + quickgraph.snk + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + Off + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Off + + + + + + + + + + Properties\version.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {A9A5C115-0680-44B3-A87E-5ECF4C93814E} + QuickGraph + + + + + + + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.meta new file mode 100644 index 0000000..be59cf6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 7914e1131f4bf4b4c9fa8130cef18240 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc new file mode 100755 index 0000000..feffdec --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc.meta new file mode 100644 index 0000000..79ddeb4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/QuickGraph.Graphviz.csproj.vspscc.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: a20eeb04951d649db802d159d7484e8b +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs new file mode 100755 index 0000000..be98aa7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs @@ -0,0 +1,65 @@ +using System; +using System.Drawing; +using System.IO; +using System.Text.RegularExpressions; + +namespace QuickGraph.Graphviz +{ + public static class SvgHtmlWrapper + { + private readonly static Regex sizeRegex = new Regex("\\d+)px\" height=\"(?\\d+)px", + RegexOptions.ExplicitCapture + | RegexOptions.Multiline + | RegexOptions.Compiled + ); + + /// + /// Creates a HTML file that wraps the SVG and returns the file name + /// + /// + /// + public static string WrapSvg(string svgFileName) + { + using (StreamReader reader = new StreamReader(svgFileName)) + { + Size size = ParseSize(reader.ReadToEnd()); + reader.Close(); + return DumpHtml(size, svgFileName); + } + } + + public static Size ParseSize(string svg) + { + Match m = sizeRegex.Match(svg); + if (!m.Success) + return new Size(400, 400); + else + { + int size = int.Parse(m.Groups["Width"].Value); + int height = int.Parse(m.Groups["Height"].Value); + return new Size(size, height); + } + } + + public static string DumpHtml(Size size, string svgFileName) + { + string outputFile = String.Format("{0}.html",svgFileName); + using (StreamWriter html = new StreamWriter(outputFile)) + { + html.WriteLine(""); + html.WriteLine(""); + html.WriteLine("", + svgFileName,size.Width,size.Height); + html.WriteLine(" ", + svgFileName,size.Width,size.Height); + html.WriteLine("If you see this, you need to install a SVG viewer"); + html.WriteLine(" "); + html.WriteLine(""); + html.WriteLine(""); + html.WriteLine(""); + } + + return outputFile; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs.meta new file mode 100644 index 0000000..4b4d37b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/SvgHtmlWrapper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7884a021a52454423bd82448feaf9634 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/quickgraph.snk b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/quickgraph.snk new file mode 100755 index 0000000000000000000000000000000000000000..a630ef50c86fa24e26a52eec015fa55208e88f88 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098C00=AIu009kK;!dACRXV-KH)dj;nb`? zQ-=oWiUP?hh*WlnvfVGfm9#9y3TlZ|`s83+8-J3WMR2A z=(@EZk;?n=R>be9Rx*auG5x-%)9XA~D_w_2_|t+K16R$vK4oKp(9|K;Hjx2NDzuZZ&_)S*sKMY5pd*oMVL^RY7a>LF)jWaD zH9+7eB}>7|QdR8LGqPH(c?4W_-Zl{b(M|kwR&4er(F;*P-Z(LSEDmFar`aqbIZM%6 zw)(nzh2eWNj--p4f84EudoAu?TDH4kOeNxk{9`(IPx;9YXQl5(Ka9&b?c;|mU04rN z;2YM972RJ?l%aG3p`TCVBgEtsqB;;xUn?(_NJ}fTk@tJCdf!LrWd@ikgm3K{=HtB zzaG%6^UQJ>-L@jy`SMVEVAnMS4b zz{rCok_J%M80o1MkST42B@}*!gK(`UND()vgy*%*qU`n-fDxg7McjZBIF!xWZvQ#J i7M{3*W_%R=cpVx!)OoGh(&7BFE!7GIWyT37q2QHHg&b@E literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/quickgraph.snk.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/quickgraph.snk.meta new file mode 100644 index 0000000..34d5ef4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Graphviz/quickgraph.snk.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 0436fcef465f04d0e89f62c92301d59c +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap.meta new file mode 100644 index 0000000..30bf12d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 31d7cdec45c8648d0a04c06442c9736f +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data.meta new file mode 100644 index 0000000..76c1d6f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 989bd6703eb104c29a2d2c7011f49f5c +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs new file mode 100755 index 0000000..23d637c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace QuickGraph.Heap.Data +{ + public sealed class GcHeapParser + { + private readonly GcObjectGraph objectGraph; + + public GcHeapParser(GcObjectGraph objectGraph) + { + this.objectGraph = objectGraph; + } + + public GcObjectGraph ObjectGraph + { + get { return this.objectGraph; } + } + + public void Parse(string fileName) + { + if (string.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + + using (StreamReader reader = new StreamReader(fileName)) + { + while (!reader.EndOfStream) + { + string line = reader.ReadLine(); + ParseLine(line); + } + } + } + + private IEnumerable SplitLine(string line) + { + foreach (string item in line.Split(' ')) + { + string trimmed = item.Trim(); + if (!String.IsNullOrEmpty(trimmed)) + yield return trimmed; + } + } + + public void ParseLine(string line) + { + if (line == null) + return; + string l = line.Trim(); + if (string.IsNullOrEmpty(l)) + return; + + // this should contain the address + List elements = new List(SplitLine(l)); + if (!elements[0].ToLowerInvariant().StartsWith("0x")) + return; + int address = int.Parse(elements[0].Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier); + + // element[3] contains the gen + int gen; + if (!int.TryParse(elements[3], out gen)) + return; + + // we can update the object + GcObjectVertex v = this.ObjectGraph.FromAddress(address); + if (v == null) + return; + + v.Gen = gen; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs.meta new file mode 100644 index 0000000..8068e4f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcHeapParser.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 825d1d3e26bce438fab763d3488737be +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs new file mode 100755 index 0000000..1104d05 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Heap.Data +{ + public sealed class AddressList : List + { + public AddressList() + : base(0) + { } + } + + public sealed class GcObject + { + private readonly long address; + private readonly int typeID; + private readonly int size; + private AddressList members; + + public GcObject(long address, int typeID, int size) + { + this.address = address; + this.typeID = typeID; + this.size = size; + } + + public long Address + { + get { return this.address; } + } + + public int TypeID + { + get { return this.typeID; } + } + + public int Size + { + get { return this.size; } + } + + public AddressList Members + { + get + { + if (this.members == null) + this.members = new AddressList(); + return this.members; + } + } + + public override string ToString() + { + return String.Format("{0}({1})", this.address, this.TypeID); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs.meta new file mode 100644 index 0000000..b4c223f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcObject.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55b5020150e5e4477957f7fe786909ca +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs new file mode 100755 index 0000000..b12e846 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs @@ -0,0 +1,31 @@ +using System; + +namespace QuickGraph.Heap.Data +{ + public struct GcRoot + { + private readonly long address; + private readonly string kind; + + public GcRoot(long address, string kind) + { + this.address = address; + this.kind = kind; + } + + public long Address + { + get { return this.address; } + } + + public string Kind + { + get { return this.kind; } + } + + public override string ToString() + { + return String.Format("{0}({1})", this.Address, this.Kind); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs.meta new file mode 100644 index 0000000..0b26a8f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcRoot.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5aa4a886d374b46d7bce540632032c6b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs new file mode 100755 index 0000000..2f563d0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs @@ -0,0 +1,32 @@ +using System; +using System.Xml.Serialization; + +namespace QuickGraph.Heap.Data +{ + public struct GcType + { + private readonly int id; + private readonly string name; + + public GcType(int id, string name) + { + this.id = id; + this.name = name; + } + + public int ID + { + get { return this.id; } + } + + public string Name + { + get { return this.name; } + } + + public override string ToString() + { + return string.Format("{0}({1})", this.Name, this.ID); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs.meta new file mode 100644 index 0000000..89027eb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/Data/GcType.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a87c8394e89e4d1594c5b1b7003e022 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs new file mode 100755 index 0000000..e9e6d01 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace QuickGraph.Heap +{ + /// + /// A generic string filtering interface + /// + internal interface IFilter + { + /// + /// Gets a value indicating wheter the value is matched by + /// the filter + /// + /// The value. + /// + bool Match(string value); + } + + /// + /// Static helper methods to create simple string filters + /// + internal static class FilterHelper + { + /// + /// Creates a regex from a string, supporting + /// * and ? wildcards. + /// + /// + /// + public static IFilter ToFilter(string name) + { + if (String.IsNullOrEmpty(name)) + return new AnyFilter(); + + foreach (char c in name) + switch (c) + { + case ',': + case ';': + case '?': + case '*': + // this code will trigger a lot of jitting/computation + string rx = Regex.Escape(name); + // ,; -> | + rx = rx.Replace(',', '|').Replace(';', '|'); + // ? -> . + rx = Regex.Replace(rx, @"\?", "."); + // * -> .*? + rx = Regex.Replace(rx, @"\*", ".*?"); + return new RegexFilter(new Regex(rx)); + } + return new ContainsFilter(name); + } + + private sealed class AnyFilter : IFilter + { + public bool Match(string value) + { + return true; + } + + public override string ToString() + { + return "any"; + } + } + + private sealed class RegexFilter : IFilter + { + private readonly Regex rx; + public RegexFilter(Regex rx) + { + this.rx = rx; + } + + public bool Match(string value) + { + if (String.IsNullOrEmpty(value)) + return false; + + Match m = rx.Match(value); + return m.Success; + } + + public override string ToString() + { + return String.Format("regex {0}", rx); + } + } + + private sealed class ContainsFilter : IFilter + { + private readonly string substring; + public ContainsFilter(string substring) + { + this.substring = substring; + } + + public bool Match(string value) + { + if (String.IsNullOrEmpty(value)) + return false; + + return value.Contains(substring); + } + + public override string ToString() + { + return String.Format("substring '{0}'", this.substring); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs.meta new file mode 100644 index 0000000..85bf021 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FilterHelper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b1d18c30e25e84251a481e7feaf82913 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs new file mode 100755 index 0000000..32b215d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Heap +{ + internal static class FormatHelper + { + public static string ToSize(int size) + { + if (size < 1000) + return String.Format("{0}b", size); + else if (size < 1000000) + return String.Format("{0}Kb", size / 1000); + else + return String.Format("{0}Mb", size / 1000000); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs.meta new file mode 100644 index 0000000..8cbf61f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/FormatHelper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10e5ec77a2eea42edb6b99e75d2c5c19 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs new file mode 100755 index 0000000..7dc7ac5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace QuickGraph.Heap +{ + public sealed class GcObjectGraph : + BidirectionalGraph> + { + private readonly Dictionary addressObjects; + private readonly List roots; + + public GcObjectGraph(int objectCount, int rootCount) + : base(false, objectCount) + { + this.addressObjects = new Dictionary(objectCount); + this.roots = new List(rootCount); + } + + public ICollection Roots + { + get { return this.roots; } + } + + public GcObjectVertex FromAddress(int address) + { + GcObjectVertex vertex; + if (this.addressObjects.TryGetValue(address, out vertex)) + return vertex; + else + return null; + } + + public GcObjectVertex AddVertex( + GcType type, + int address, + int size + ) + { + GcObjectVertex v = new GcObjectVertex( + type, + address, + size); + this.AddVertex(v); + return v; + } + + public override void AddVertex(GcObjectVertex v) + { + base.AddVertex(v); + this.addressObjects.Add(v.Address, v); + } + + public void SetAsRoot(GcRoot root) + { + GcObjectVertex v = this.FromAddress(root.Address); + if (v != null) + { + v.Kind = root.Kind; + this.roots.Add(v); + } + } + + public override bool RemoveVertex(GcObjectVertex v) + { + this.addressObjects.Remove(v.Address); + return base.RemoveVertex(v); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs.meta new file mode 100644 index 0000000..3dc01e0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5aeba8cf6b3664852b346b18566eb3b4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs new file mode 100755 index 0000000..905d487 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs @@ -0,0 +1,71 @@ +using System; +using QuickGraph.Heap.Data; + +namespace QuickGraph.Heap +{ + public struct GcObjectVertex + { + private readonly GcType type; + private readonly long address; + private readonly int size; + private readonly string kind; + private readonly int gen; + private readonly string value; + + public GcObjectVertex( + GcType type, + long address, + int size, + string kind, + int gen, + string value + ) + { + this.type = type; + this.address = address; + this.size = size; + this.kind = kind; + this.gen = gen; + this.value = value; + } + + public GcType Type + { + get { return this.type; } + } + + public long Address + { + get { return this.address; } + } + + public int Size + { + get { return this.size; } + } + + public string Kind + { + get { return this.kind; } + } + + public int Gen + { + get { return this.gen; } + } + + public string Value + { + get { return this.value; } + } + + public override string ToString() + { + return String.Format("0x{0:x}-{1}-{2}", + this.Address, + this.Type.Name, + this.Size + ); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs.meta new file mode 100644 index 0000000..dc72bc4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcObjectVertex.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bac1ba01342ed407cb50eddcc06d63c4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs new file mode 100755 index 0000000..23f02c0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph; + +namespace QuickGraph.Heap +{ + public sealed class GcType : IEquatable + { + public readonly int ID; + public readonly string Name; + public bool Root; + public int Count; + public int Size; + private int genCount; + private int genSum; + + + internal GcType(int id, string name) + { + this.ID = id; + this.Name = name; + this.Root = false; + this.Count = 0; + this.Size = 0; + } + + public bool Equals(GcType other) + { + return this.ID == other.ID; + } + + public override int GetHashCode() + { + return this.ID; + } + + public override bool Equals(object obj) + { + return (object)obj != null && this.Equals(obj as GcType); + } + + public override string ToString() + { + return String.Format("{0}\t{1}\t{2:0.0}\t{3}", + this.Count, + FormatHelper.ToSize(this.Size), + this.Gen, + this.Name); + } + + public double Gen + { + get + { + if (this.genCount == 0) + return -1; + else + return this.genSum / (double)this.genCount; + } + } + + public void AddObjectGeneration(int gen) + { + this.genCount++; + this.genSum += gen; + } + } + + public sealed class GcTypeCollection : QueryableList + { + internal GcTypeCollection(int capacity) + :base(capacity) + { + } + internal GcTypeCollection(IEnumerable types) + : base(types) + { } + + protected override QueryableList Create(int capacity) + { + return new GcTypeCollection(capacity); + } + + public GcTypeCollection SortSize() + { + GcTypeCollection clone = new GcTypeCollection(this); + clone.Sort((left, right) => -left.Size.CompareTo(right.Size)); + return clone; + } + + public GcTypeCollection SortCount() + { + GcTypeCollection clone = new GcTypeCollection(this); + clone.Sort((left, right) => -left.Count.CompareTo(right.Count)); + return clone; + } + + public GcTypeCollection SortGen() + { + GcTypeCollection clone = new GcTypeCollection(this); + clone.Sort((left, right) => left.Gen.CompareTo(right.Gen)); + return clone; + } + + public GcTypeCollection MinimumSize(int size) + { + GcTypeCollection clone = new GcTypeCollection(this.Count); + foreach (GcType type in this) + if (type.Size >= size) + clone.Add(type); + clone.TrimExcess(); + return clone; + } + } + + public sealed class GcTypeEdge : Edge + { + public int Count; + + internal GcTypeEdge(GcType source, GcType target) + : base(source, target) + { } + + public override string ToString() + { + return String.Format("{0}\t{1} -> {2}", + this.Count, + this.Source.Name, + this.Target.Name); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs.meta new file mode 100644 index 0000000..75f7631 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcType.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4fc1943a2828e4cca8759aab6eb4f57c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs new file mode 100755 index 0000000..e8aa298 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph; +using System.IO; + +namespace QuickGraph.Heap +{ + internal sealed class GcTypeGraphReader : GcHeapXmlReader + { + readonly BidirectionalGraph graph = new BidirectionalGraph(); + // id -> type + readonly Dictionary types = new Dictionary(); + // adress -> root + readonly Dictionary roots = new Dictionary(); + // adress -> type + readonly Dictionary objectTypes = new Dictionary(); + readonly List unresolvedMembers = new List(); + + public GcTypeGraphReader() + {} + + public BidirectionalGraph Graph + { + get { return this.graph; } + } + + // remeber type and roots + protected override void VisitType(int id, string name) + { + GcType type = new GcType(id, name); + + this.types.Add(type.ID, type); + this.graph.AddVertex(type); + } + + protected override void VisitRoot(string kind, int address) + { + if (kind == "stack") return; // skip stack roots + this.roots[address] = new GcRoot(kind, address); + } + + GcType current; + protected override void VisitStartObject(int address, int typeid, int size) + { + if (!this.types.TryGetValue(typeid, out this.current)) + throw new InvalidOperationException("unknown typeid " + typeid); + + this.current.Count++; + this.current.Size += size; + if (!this.current.Root) // lazy check if rooted + this.current.Root = this.roots.ContainsKey(address); + + this.objectTypes.Add(address, this.current); + } + + protected override void VisitMember(int address) + { + GcType target; + if (!this.objectTypes.TryGetValue(address, out target)) + { + // object type not loaded yet, + // store member + this.unresolvedMembers.Add(new GcMember(this.current, address)); + } + else + { + AddTypeEdge(target, this.current); + } + } + + private void AddTypeEdge(GcType source, GcType target) + { + GcTypeEdge edge; + if (!this.graph.TryGetEdge(source, target, out edge)) + this.graph.AddEdge(edge = new GcTypeEdge(source, target)); + edge.Count++; + } + + // process unresolved members + protected override void VisitEndObjects() + { + FlushUnresolvedMembers(); + } + + private void FlushUnresolvedMembers() + { + foreach (GcMember member in this.unresolvedMembers) + { + GcType target = member.Referer; + GcType source; + if (this.objectTypes.TryGetValue(member.Address, out source)) + this.AddTypeEdge(source, target); + } + this.unresolvedMembers.Clear(); + } + + public void ParseDump(StreamReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + while (!reader.EndOfStream) + this.ParseDumpLine(reader.ReadLine()); + } + + private static IEnumerable SplitLine(string line) + { + foreach (string item in line.Split(' ')) + { + string trimmed = item.Trim(); + if (!String.IsNullOrEmpty(trimmed)) + yield return trimmed; + } + } + + private void ParseDumpLine(string line) + { + if (line == null) + return; + string l = line.Trim(); + if (string.IsNullOrEmpty(l)) + return; + + // this should contain the address + List elements = new List(SplitLine(l)); + if (!elements[0].ToLowerInvariant().StartsWith("0x")) + return; + int address; + if (!TryParseAddress(elements[0].Substring(2), out address)) + { + Console.WriteLine("failed to parse address {0}", elements[0].Substring(2)); + return; + } + + // element[3] contains the gen + int gen; + if (!int.TryParse(elements[3], out gen)) + { + Console.WriteLine("failed to parse gen {0}", elements[3]); + return; + } + + // we can update the object + GcType type; + if (this.objectTypes.TryGetValue(address, out type)) + type.AddObjectGeneration(gen); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs.meta new file mode 100644 index 0000000..214a3ec --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeGraphReader.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ac79ecd4c354043eab93aa154d70f95d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs new file mode 100755 index 0000000..2940bc7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs @@ -0,0 +1,346 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph; +using System.IO; +using System.Xml; +using QuickGraph.Algorithms.Search; +using QuickGraph.Glee; +using Microsoft.Glee.GraphViewerGdi; +using QuickGraph.Algorithms; +using QuickGraph.Algorithms.Condensation; +using System.Windows.Forms; +using System.Text.RegularExpressions; + +namespace QuickGraph.Heap +{ + /// + /// + /// + /// + /// http://www.cs.utexas.edu/users/speedway/DaCapo/papers/cork-popl-2007.pdf + /// + public sealed class GcTypeHeap + { + private readonly BidirectionalGraph graph; + private int size = -1; + private Form viewerForm; + private GViewer viewer; + + internal GcTypeHeap(BidirectionalGraph graph) + { + if (graph == null) + throw new ArgumentNullException("graph"); + + this.graph = graph; + } + + public int Size + { + get + { + if (this.size < 0) + { + int s = 0; + foreach (GcType type in this.graph.Vertices) + s += type.Size; + this.size = s; + } + return this.size; + } + } + + /// + /// Loads the specified heap XML file name. + /// + /// Name of the heap XML file. + /// + public static GcTypeHeap Load(string heapXmlFileName) + { + return Load(heapXmlFileName, null); + } + + private readonly static Regex regex = new Regex( + "name=\"(?[^\"]*)\"", + RegexOptions.IgnoreCase + | RegexOptions.CultureInvariant + | RegexOptions.IgnorePatternWhitespace + | RegexOptions.Compiled + ); + + private static string EscapeXmlAttribute(Match m) + { + string value = m.Groups["Type"].Value; + return String.Format("name=\"{0}\"", + value.Replace("<", "<") + .Replace(">", ">") + ); + } + + /// + /// Loads the specified heap XML file name. + /// + /// Name of the heap XML file. + /// Name of the dump file. + /// + public static GcTypeHeap Load(string heapXmlFileName, string dumpFileName) + { + if (String.IsNullOrEmpty(heapXmlFileName)) + throw new ArgumentNullException("heapXmlFileName"); + if (!File.Exists(heapXmlFileName)) + throw new FileNotFoundException("could not find heap file", heapXmlFileName); + + Console.WriteLine("loading {0}", heapXmlFileName); + GcTypeGraphReader greader = new GcTypeGraphReader(); + + try + { + using (XmlReader reader = XmlReader.Create(heapXmlFileName)) + greader.Read(reader); + } + catch (XmlException) + { + Console.WriteLine("fixing up xml file (incorrect xml with generics)"); + // fix the xml and save back to disk. + File.WriteAllText( + heapXmlFileName, + regex.Replace( + File.ReadAllText(heapXmlFileName), + EscapeXmlAttribute) + ); + // try again + greader = new GcTypeGraphReader(); + using (XmlReader reader = XmlReader.Create(heapXmlFileName)) + greader.Read(reader); + } + + if (!String.IsNullOrEmpty(dumpFileName)) + { + if (!File.Exists(dumpFileName)) + throw new FileNotFoundException("could not find dump file", dumpFileName); + using (StreamReader reader = new StreamReader(File.OpenRead(dumpFileName))) + greader.ParseDump(reader); + } + + GcTypeHeap heap = new GcTypeHeap(greader.Graph).RemoveDefault(); ; + Console.WriteLine("heap: {0}", heap); + return heap; + } + + public override string ToString() + { + return String.Format("{0} types, {1} edges, {2}", + this.graph.VertexCount, + this.graph.EdgeCount, + FormatHelper.ToSize(this.Size)); + } + + /// + /// Gets the list of types in the graph + /// + public GcTypeCollection Types + { + get + { + return new GcTypeCollection(this.graph.Vertices).SortSize(); + } + } + + /// + /// Gets the list of root types + /// + public GcTypeCollection Roots + { + get + { + GcTypeCollection roots = new GcTypeCollection(this.graph.Vertices); + foreach (GcType type in this.graph.Vertices) + if (type.Root) + roots.Add(type); + return roots; + } + } + + public GcTypeHeap Clone() + { + return new GcTypeHeap(this.graph.Clone()); + } + + #region Rendering + public GcTypeHeap Render() + { + Console.WriteLine("rendering..."); + if (this.graph.VertexCount > 500) + { + Console.WriteLine("too many vertices "); + return this; + } + + GleeGraphPopulator populator = GleeGraphUtility.Create(this.graph); + try + { + populator.NodeAdded += new GleeVertexNodeEventHandler(populator_NodeAdded); + populator.EdgeAdded += new GleeEdgeEventHandler(populator_EdgeAdded); + populator.Compute(); + + if (viewer == null) + { + viewerForm = new Form(); + viewer = new GViewer(); + viewer.Dock = DockStyle.Fill; + viewerForm.Controls.Add(viewer); + } + viewer.Graph = populator.GleeGraph; + viewerForm.ShowDialog(); + } + finally + { + populator.NodeAdded -= new GleeVertexNodeEventHandler(populator_NodeAdded); + populator.EdgeAdded -= new GleeEdgeEventHandler(populator_EdgeAdded); + } + + return this; + } + + void populator_EdgeAdded(object sender, GleeEdgeEventArgs e) + { + e.GEdge.Attr.Label = e.Edge.Count.ToString(); + } + + void populator_NodeAdded(object sender, GleeVertexEventArgs args) + { + args.Node.Attr.Shape = Microsoft.Glee.Drawing.Shape.Box; + double gen = args.Vertex.Gen; + if (gen > 2) + args.Node.Attr.Fillcolor = Microsoft.Glee.Drawing.Color.LightBlue; + else if (gen > 1) + args.Node.Attr.Fillcolor = Microsoft.Glee.Drawing.Color.LightGoldenrodYellow; + else if (gen >= 0) + args.Node.Attr.Fillcolor = Microsoft.Glee.Drawing.Color.LightPink; + else + args.Node.Attr.Fillcolor = Microsoft.Glee.Drawing.Color.LightSalmon; + + // root -> other color + if (args.Vertex.Root) + args.Node.Attr.AddStyle(Microsoft.Glee.Drawing.Style.Dashed); + + // label + args.Node.Attr.Label = + String.Format("{0}\nc:{1} g:{2:0.0} s:{3}", + args.Vertex.Name, + args.Vertex.Count, + args.Vertex.Gen, + FormatHelper.ToSize(args.Vertex.Size) + ); + } + #endregion + + #region Filtering + private GcTypeHeap RemoveDefault() + { + // remove default types + this.graph.RemoveVertexIf( + delegate(GcType type) + { + switch (type.Name) + { + case "System.OutOfMemoryException": + case "System.StackOverflowException": + case "System.ExecutionEngineException": + case "System.RuntimeType": + case "System.Reflection.Missing": + case "System.IO.TextReader/SyncTextReader": + case "System.AppDomain": + case "System.AppDomainSetup": + case "System.IO.Stream/NullStream": + case "System.Text.UTF8Encoding": + case "System.__Filters": + case "System.Reflection.MemberFilter": + case "System.Text.CodePageEncoding": + case "System.IO.TextWriter/NullTextWriter": + case "System.Text.UTF8Encoding/UTF8Encoder": + case "System.IO.TextReader/NullTextReader": + case "System.IO.StreamReader/NullStreamReader": + case "System.Text.CodePageEncoding/Decoder": + case "System.IO.__ConsoleStream": + case "System.Text.Encoding/DefaultEncoder": + case "System.IO.TextWriter/SyncTextWriter": + return true; + default: + return false; + } + }); + return this; + } + + public GcTypeHeap Touching(string typeNames) + { + if (String.IsNullOrEmpty(typeNames)) + throw new ArgumentNullException("typeNames"); + + return this.Clone().TouchingInPlace(typeNames); + } + + private GcTypeHeap TouchingInPlace(string typeNames) + { + if (String.IsNullOrEmpty(typeNames)) + throw new ArgumentNullException("typeNames"); + + var filter = FilterHelper.ToFilter(typeNames); + Console.WriteLine("filtering nodes not connected to type matching '{0}'", filter); + var colors = new Dictionary(this.graph.VertexCount); + foreach (var type in this.graph.Vertices) + colors.Add(type, GraphColor.White); + + var rgraph = new ReversedBidirectionalGraph(graph); + foreach (var type in this.graph.Vertices) + { + if (filter.Match(type.Name)) + { + { // parents + var dfs = + new DepthFirstSearchAlgorithm>(rgraph, colors); + dfs.Visit(type, -1); + } + { // children + var dfs = new DepthFirstSearchAlgorithm(graph, colors); + dfs.Visit(type, -1); + } + } + } + // remove all white vertices + this.graph.RemoveVertexIf(t => colors[t] == GraphColor.White); + Console.WriteLine("resulting {0} types, {1} edges", graph.VertexCount, graph.EdgeCount); + return this; + } + + public GcTypeHeap Merge(int minimumSize) + { + var merged = new BidirectionalGraph>(false, this.graph.VertexCount); + var merger = new EdgeMergeCondensationGraphAlgorithm( + this.graph, + merged, + delegate(GcType type) + { + return type.Size >= minimumSize; + }); + merger.Compute(); + var clone = new BidirectionalGraph( + false, + merged.VertexCount); + foreach (var type in merged.Vertices) + clone.AddVertex(type); + foreach (var medge in merged.Edges) + { + GcTypeEdge edge = new GcTypeEdge(medge.Source, medge.Target); + foreach (GcTypeEdge e in medge.Edges) + edge.Count += e.Count; + clone.AddEdge(edge); + } + + Console.WriteLine("resulting {0} types, {1} edges", clone.VertexCount, clone.EdgeCount); + return new GcTypeHeap(clone); + } + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs.meta new file mode 100644 index 0000000..723dfd7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/GcTypeHeap.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0b841e517ab24bbbb6059c95f66b60a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs new file mode 100755 index 0000000..f12885d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.Globalization; + +namespace QuickGraph.Heap +{ + internal struct GcRoot + { + public readonly string Kind; + public readonly int Address; + public GcRoot(string kind, int address) + { + this.Kind = kind; + this.Address = address; + } + } + + internal struct GcMember + { + public readonly GcType Referer; + public readonly int Address; + public GcMember(GcType referer, int address) + { + this.Referer = referer; + this.Address = address; + } + } + + internal abstract class GcHeapXmlReader + { + public void Read(XmlReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + while (reader.Read()) + { + switch (reader.NodeType) + { + case XmlNodeType.Element: + this.ReadElement(reader); + break; + case XmlNodeType.EndElement: + this.ReadEndElement(reader); + break; + default: // skip the rest + break; + } + } + } + + private void ReadElement(XmlReader reader) + { + switch (reader.Name) + { + case "gcheap": + // top level element, continue + this.VisitStartGcHeap(); + break; + case "types": + // top level types, + this.VisitStartTypes(); + break; + case "type": + { + int id; + // type element + if (!int.TryParse(reader.GetAttribute("id"), out id)) + throw new XmlException("could not parse gcheap/types/type/@id"); + string name = reader.GetAttribute("name"); + this.VisitType(id, name); + + // move to next + reader.Skip(); + break; + } + case "roots": + this.VisitStartRoots(); + break; + case "root": + { + string kind = reader.GetAttribute("kind"); + int address; + if (!TryParseAddress(reader.GetAttribute("address"), out address)) + throw new XmlException("could not parse gcheap/roots/root/@address"); + + this.VisitRoot(kind, address); + + // move to next + reader.Skip(); + break; + } + case "objects": + this.VisitStartObjects(); + break; + case "object": + { + int size; + int typeid; + int address; + if (!TryParseAddress(reader.GetAttribute("address"), out address)) + throw new XmlException("could not parse gcheap/objects/object/@address"); + if (!int.TryParse(reader.GetAttribute("typeid"), out typeid)) + throw new XmlException("could not parse gcheap/objects/object/@typeid"); + if (!int.TryParse(reader.GetAttribute("size"), out size)) + throw new XmlException("could not parse gcheap/objects/object/@size"); + this.VisitStartObject(address, typeid, size); + break; + } + case "member": + { + int address; + if (!TryParseAddress(reader.GetAttribute("address"), out address)) + throw new XmlException("could not parse gcheap/objects/object/member/@address"); + this.VisitMember(address); + // read node + reader.Skip(); + break; + } + default: + throw new XmlException("unknown element " + reader.Name); + } + } + + private void ReadEndElement(XmlReader reader) + { + switch (reader.Name) + { + case "gcheap": + // top level element, continue + this.VisitEndGcHeap(); + break; + case "types": + // top level types, + this.VisitEndTypes(); + break; + case "roots": + this.VisitEndRoots(); + break; + case "objects": + this.VisitEndObjects(); + break; + case "object": + this.VisitEndObject(); + break; + case "member": + default: + throw new XmlException("unexpected end element " + reader.Name); + } + } + + protected static bool TryParseAddress(string value, out int address) + { + address = 0; + return + value != null && + value.StartsWith("0x") && + int.TryParse(value.Substring(2), NumberStyles.HexNumber, null, out address); + } + + protected virtual void VisitStartGcHeap() {} + + protected virtual void VisitEndGcHeap() {} + + protected virtual void VisitStartTypes() {} + + protected virtual void VisitEndTypes() {} + + protected virtual void VisitType(int id, string name) {} + + protected virtual void VisitRoot(string kind, int address) {} + + protected virtual void VisitEndRoots() {} + + protected virtual void VisitStartRoots() {} + + protected virtual void VisitStartObjects() {} + + protected virtual void VisitEndObjects() {} + + protected virtual void VisitStartObject(int address, int typeid, int size) {} + + protected virtual void VisitEndObject() { } + + protected virtual void VisitMember(int address) {} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs.meta new file mode 100644 index 0000000..c01b835 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/HeapXmlReader.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 05370d0ccf1b145eb958e9fc45c7af85 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs new file mode 100755 index 0000000..a860075 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace QuickGraph.Heap +{ + public abstract class QueryableList : List + { + protected QueryableList(IEnumerable items) + : base(items) + { } + + protected QueryableList(int capacity) + : base(capacity) + { } + + protected abstract QueryableList Create(int capacity); + + public QueryableList Top(int count) + { + if (count <= 0) + throw new ArgumentOutOfRangeException("must be posivite", "count"); + + QueryableList list = this.Create(count); + int len = Math.Min(count, this.Count); + for (int i = 0; i < len; ++i) + list.Add(this[i]); + return list; + } + + public QueryableList Bottom(int count) + { + if (count <= 0) + throw new ArgumentOutOfRangeException("must be posivite", "count"); + + QueryableList list = this.Create(count); + int len = Math.Max(this.Count - count, 0); + for (int i = this.Count - 1; i >= len; --i) + list.Add(this[i]); + return list; + } + + public override string ToString() + { + using (StringWriter writer = new StringWriter()) + { + for(int i = this.Count -1;i>=0;--i) + writer.WriteLine(this[i]); + return writer.ToString(); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs.meta new file mode 100644 index 0000000..138db45 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QueryableList.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 099aa5eac85d0436c9c33e386d94b049 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj new file mode 100755 index 0000000..eca272c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj @@ -0,0 +1,109 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {2DEC7C6E-68DF-47EC-A75E-2C1238986B8E} + Library + Properties + QuickGraph.Heap + QuickGraph.Heap + SAK + SAK + SAK + SAK + true + quickgraph.snk + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + Off + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Off + + + + False + ..\external\Glee\Microsoft.GLEE.dll + + + False + ..\external\Glee\Microsoft.GLEE.Drawing.dll + + + False + ..\external\Glee\Microsoft.GLEE.GraphViewerGDI.dll + + + + + + + + + Properties\version.cs + + + + + + + + + + + + + Always + + + + + {ACDD0973-E5D9-4C2B-9EAF-B5B5DF44EDDD} + QuickGraph.Glee + + + {A9A5C115-0680-44B3-A87E-5ECF4C93814E} + QuickGraph + + + + + Always + + + Always + + + + + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.meta new file mode 100644 index 0000000..f6489e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 8fd87fbca4d984a9cbf667f258ed75fd +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc new file mode 100755 index 0000000..feffdec --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc.meta new file mode 100644 index 0000000..d6c3687 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/QuickGraph.Heap.csproj.vspscc.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 1ac6b1240dbe94a8d826a80b80fbb44a +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd new file mode 100755 index 0000000..e1a199a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd @@ -0,0 +1,2 @@ +rem usage: dumpheap PID +cdb -p %1 -c "$$>< dumpheap.txt" \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd.meta new file mode 100644 index 0000000..9146426 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.cmd.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: b65f713509c8148429dda47211a9cb08 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt new file mode 100755 index 0000000..8fc96f8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt @@ -0,0 +1,7 @@ +.echo dumping process managed heap, this might take a while... +.loadby sos mscorwks +!TraverseHeap -xml heap.xml +!TraverseHeap heap.txt +.detach +q + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt.meta new file mode 100644 index 0000000..cbc481d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/dumpheap.txt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 1431df0e1ac814d07b56baedbe71800e +TextScriptImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py new file mode 100755 index 0000000..5feea11 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py @@ -0,0 +1,4 @@ +import clr +clr.AddReferenceToFile("QuickGraph.Heap") +import QuickGraph.Heap +from QuickGraph.Heap import GcTypeHeap diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py.meta new file mode 100644 index 0000000..28fea42 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/heap.py.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 51997ea1921d2456ebedbdb4ab4ab592 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/quickgraph.snk b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/quickgraph.snk new file mode 100755 index 0000000000000000000000000000000000000000..a630ef50c86fa24e26a52eec015fa55208e88f88 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098C00=AIu009kK;!dACRXV-KH)dj;nb`? zQ-=oWiUP?hh*WlnvfVGfm9#9y3TlZ|`s83+8-J3WMR2A z=(@EZk;?n=R>be9Rx*auG5x-%)9XA~D_w_2_|t+K16R$vK4oKp(9|K;Hjx2NDzuZZ&_)S*sKMY5pd*oMVL^RY7a>LF)jWaD zH9+7eB}>7|QdR8LGqPH(c?4W_-Zl{b(M|kwR&4er(F;*P-Z(LSEDmFar`aqbIZM%6 zw)(nzh2eWNj--p4f84EudoAu?TDH4kOeNxk{9`(IPx;9YXQl5(Ka9&b?c;|mU04rN z;2YM972RJ?l%aG3p`TCVBgEtsqB;;xUn?(_NJ}fTk@tJCdf!LrWd@ikgm3K{=HtB zzaG%6^UQJ>-L@jy`SMVEVAnMS4b zz{rCok_J%M80o1MkST42B@}*!gK(`UND()vgy*%*qU`n-fDxg7McjZBIF!xWZvQ#J i7M{3*W_%R=cpVx!)OoGh(&7BFE!7GIWyT37q2QHHg&b@E literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/quickgraph.snk.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/quickgraph.snk.meta new file mode 100644 index 0000000..23e3064 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.Heap/quickgraph.snk.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 1fa4820fcd1f4464ab17329c67c2bccc +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph.meta new file mode 100644 index 0000000..e5b61fb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 27bec876861c64bfaa58419bdc7cdd44 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs new file mode 100755 index 0000000..6e24def --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs @@ -0,0 +1,467 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace QuickGraph +{ + [Serializable] + public class AdjacencyGraph : + IVertexAndEdgeListGraph, + IEdgeListAndIncidenceGraph, + IMutableEdgeListGraph, + IMutableIncidenceGraph, + IMutableVertexListGraph, + IMutableVertexAndEdgeListGraph + where TEdge : IEdge + { + private readonly bool isDirected = true; + private readonly bool allowParallelEdges; + private readonly VertexEdgeDictionary vertexEdges; + private int edgeCount = 0; + private int edgeCapacity = -1; + + public AdjacencyGraph() + :this(true) + {} + + public AdjacencyGraph(bool allowParallelEdges) + :this(allowParallelEdges,-1) + { + } + + public AdjacencyGraph(bool allowParallelEdges, int capacity) + { + this.allowParallelEdges = allowParallelEdges; + if (capacity > -1) + this.vertexEdges = new VertexEdgeDictionary(capacity); + else + this.vertexEdges = new VertexEdgeDictionary(); + } + + public bool IsDirected + { + get { return this.isDirected; } + } + + public bool AllowParallelEdges + { + get { return this.allowParallelEdges; } + } + + public int EdgeCapacity + { + get { return this.edgeCapacity; } + set { this.edgeCapacity = value; } + } + + public static Type VertexType + { + get { return typeof(TVertex); } + } + + public static Type EdgeType + { + get { return typeof(TEdge); } + } + + public bool IsVerticesEmpty + { + get { return this.vertexEdges.Count == 0; } + } + + public int VertexCount + { + get { return this.vertexEdges.Count; } + } + + public IEnumerable Vertices + { + get { return this.vertexEdges.Keys; } + } + + public bool ContainsVertex(TVertex v) + { + GraphContracts.AssumeNotNull(v, "v"); + return this.vertexEdges.ContainsKey(v); + } + + public bool IsOutEdgesEmpty(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexEdges[v].Count == 0; + } + + public int OutDegree(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexEdges[v].Count; + } + + public IEnumerable OutEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexEdges[v]; + } + + public TEdge OutEdge(TVertex v, int index) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexEdges[v][index]; + } + + /// + /// Gets a value indicating whether this instance is edges empty. + /// + /// + /// true if this instance is edges empty; otherwise, false. + /// + public bool IsEdgesEmpty + { + get { return this.edgeCount == 0; } + } + + /// + /// Gets the edge count. + /// + /// The edge count. + public int EdgeCount + { + get + { + GraphContracts.Assert(this.edgeCount >= 0); + return this.edgeCount; + } + } + + /// + /// Gets the edges. + /// + /// The edges. + public IEnumerable Edges + { + get + { + foreach (EdgeList edges in this.vertexEdges.Values) + foreach (var edge in edges) + yield return edge; + } + } + + public bool ContainsEdge(TVertex source, TVertex target) + { + GraphContracts.AssumeInVertexSet(this, source, "source"); + GraphContracts.AssumeInVertexSet(this, target, "target"); + foreach (var outEdge in this.OutEdges(source)) + if (outEdge.Target.Equals(target)) + return true; + return false; + } + + public bool ContainsEdge(TEdge edge) + { + GraphContracts.AssumeInVertexSet(this, edge, "edge"); + return this.vertexEdges[edge.Source].Contains(edge); + } + + public bool TryGetEdge( + TVertex source, + TVertex target, + out TEdge edge) + { + GraphContracts.AssumeInVertexSet(this, source, "source"); + GraphContracts.AssumeInVertexSet(this, target, "target"); + + EdgeList edgeList; + if (this.vertexEdges.TryGetValue(source, out edgeList) && + edgeList.Count > 0) + { + foreach (var e in edgeList) + { + if (e.Target.Equals(target)) + { + edge = e; + return true; + } + } + } + edge = default(TEdge); + return false; + } + + public bool TryGetEdges( + TVertex source, + TVertex target, + out IEnumerable edges) + { + GraphContracts.AssumeInVertexSet(this, source, "source"); + GraphContracts.AssumeInVertexSet(this, target, "target"); + + EdgeList outEdges; + if (this.vertexEdges.TryGetValue(source, out outEdges)) + { + List list = new List(outEdges.Count); + foreach (var edge in outEdges) + if (edge.Target.Equals(target)) + list.Add(edge); + + edges = list; + return true; + } + else + { + edges = null; + return false; + } + } + + public virtual void AddVertex(TVertex v) + { + GraphContracts.AssumeNotInVertexSet(this, v, "v"); + if (this.EdgeCapacity>0) + this.vertexEdges.Add(v, new EdgeList(this.EdgeCapacity)); + else + this.vertexEdges.Add(v, new EdgeList()); + this.OnVertexAdded(new VertexEventArgs(v)); + } + + public virtual void AddVertexRange(IEnumerable vertices) + { + GraphContracts.AssumeNotNull(vertices, "vertices"); + foreach (var v in vertices) + this.AddVertex(v); + } + + public event VertexEventHandler VertexAdded; + protected virtual void OnVertexAdded(VertexEventArgs args) + { + VertexEventHandler eh = this.VertexAdded; + if (eh != null) + eh(this, args); + } + + public virtual bool RemoveVertex(TVertex v) + { + GraphContracts.AssumeNotNull(v, "v"); + if (!this.ContainsVertex(v)) + return false; + // remove outedges + { + EdgeList edges = this.vertexEdges[v]; + if (this.EdgeRemoved != null) // lazily notify + { + foreach (var edge in edges) + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + } + this.edgeCount -= edges.Count; + edges.Clear(); + } + + // iterage over edges and remove each edge touching the vertex + EdgeList edgeToRemove = new EdgeList(); + foreach (var kv in this.vertexEdges) + { + if (kv.Key.Equals(v)) continue; // we've already + // collect edge to remove + foreach(var edge in kv.Value) + { + if (edge.Target.Equals(v)) + edgeToRemove.Add(edge); + } + + // remove edges + foreach (var edge in edgeToRemove) + { + kv.Value.Remove(edge); + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + } + // update count + this.edgeCount -= edgeToRemove.Count; + edgeToRemove.Clear(); + } + + System.Diagnostics.Debug.Assert(this.edgeCount >= 0); + this.vertexEdges.Remove(v); + this.OnVertexRemoved(new VertexEventArgs(v)); + + return true; + } + + public event VertexEventHandler VertexRemoved; + protected virtual void OnVertexRemoved(VertexEventArgs args) + { + VertexEventHandler eh = this.VertexRemoved; + if (eh != null) + eh(this, args); + } + + public int RemoveVertexIf(VertexPredicate predicate) + { + GraphContracts.AssumeNotNull(predicate, "predicate"); + VertexList vertices = new VertexList(); + foreach (var v in this.Vertices) + if (predicate(v)) + vertices.Add(v); + + foreach (var v in vertices) + this.RemoveVertex(v); + + return vertices.Count; + } + + public virtual bool AddVerticesAndEdge(TEdge e) + { + GraphContracts.AssumeNotNull(e, "e"); + if (!this.ContainsVertex(e.Source)) + this.AddVertex(e.Source); + if (!this.ContainsVertex(e.Target)) + this.AddVertex(e.Target); + + return this.AddEdge(e); + } + + public virtual bool AddEdge(TEdge e) + { + GraphContracts.AssumeInVertexSet(this, e, "e"); + if (!this.AllowParallelEdges) + { + if (this.ContainsEdge(e.Source, e.Target)) + return false; + } + this.vertexEdges[e.Source].Add(e); + this.edgeCount++; + + this.OnEdgeAdded(new EdgeEventArgs(e)); + + return true; + } + + public void AddEdgeRange(IEnumerable edges) + { + GraphContracts.AssumeNotNull(edges, "edges"); + foreach (var edge in edges) + this.AddEdge(edge); + } + + public event EdgeEventHandler EdgeAdded; + protected virtual void OnEdgeAdded(EdgeEventArgs args) + { + var eh = this.EdgeAdded; + if (eh != null) + eh(this, args); + } + + public virtual bool RemoveEdge(TEdge e) + { + GraphContracts.AssumeInVertexSet(this, e, "e"); + if (this.vertexEdges[e.Source].Remove(e)) + { + this.edgeCount--; + System.Diagnostics.Debug.Assert(this.edgeCount >= 0); + this.OnEdgeRemoved(new EdgeEventArgs(e)); + return true; + } + else + return false; + } + + public event EdgeEventHandler EdgeRemoved; + protected virtual void OnEdgeRemoved(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeRemoved; + if (eh != null) + eh(this, args); + } + + public int RemoveEdgeIf(EdgePredicate predicate) + { + GraphContracts.AssumeNotNull(predicate, "predicate"); + + var edges = new EdgeList(); + foreach (var edge in this.Edges) + if (predicate(edge)) + edges.Add(edge); + + foreach (var edge in edges) + this.RemoveEdge(edge); + + GraphContracts.Assert(this.edgeCount >= 0); + return edges.Count; + } + + public void ClearOutEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + + var edges = this.vertexEdges[v]; + int count = edges.Count; + if (this.EdgeRemoved != null) // call only if someone is listening + { + foreach (var edge in edges) + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + } + edges.Clear(); + this.edgeCount -= count; + GraphContracts.Assert(this.edgeCount >= 0); + } + + public int RemoveOutEdgeIf(TVertex v, EdgePredicate predicate) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + GraphContracts.AssumeNotNull(predicate, "predicate"); + + var edges = this.vertexEdges[v]; + var edgeToRemove = new EdgeList(edges.Count); + foreach (var edge in edges) + if (predicate(edge)) + edgeToRemove.Add(edge); + + foreach (var edge in edgeToRemove) + { + edges.Remove(edge); + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + } + this.edgeCount -= edgeToRemove.Count; + GraphContracts.Assert(this.edgeCount >= 0); + + return edgeToRemove.Count; + } + + public void TrimEdgeExcess() + { + foreach (var edges in this.vertexEdges.Values) + edges.TrimExcess(); + } + + public void Clear() + { + this.vertexEdges.Clear(); + this.edgeCount = 0; + } + + [Serializable] + public sealed class VertexList : List + { + internal VertexList() { } + internal VertexList(int capacity) + : base(capacity) { } + } + + [Serializable] + public sealed class EdgeList : List + { + internal EdgeList() { } + internal EdgeList(int capacity) + : base(capacity) + { } + } + + [Serializable] + public sealed class VertexEdgeDictionary : Dictionary + { + internal VertexEdgeDictionary() { } + internal VertexEdgeDictionary(int capacity) + : base(capacity) + { } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs.meta new file mode 100644 index 0000000..9807e7c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/AdjacencyGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b45a62cffe9a3443286a86a6108aa7bc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms.meta new file mode 100644 index 0000000..d977ce3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 8efbc7acf46fa45b585beefac447a361 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs new file mode 100755 index 0000000..06e4588 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs @@ -0,0 +1,331 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Condensation; +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Observers; + +namespace QuickGraph.Algorithms +{ + public static class AlgoUtility + { + public static IDictionary ConstantCapacities( + IEdgeSet g, double value) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(g, "g"); + + var capacities = new Dictionary(g.EdgeCount); + foreach (var e in g.Edges) + capacities.Add(e, value); + return capacities; + } + + public static IEnumerable Sinks( + IVertexListGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + foreach (var v in visitedGraph.Vertices) + if (visitedGraph.IsOutEdgesEmpty(v)) + yield return v; + } + + public static IEnumerable Roots( + IBidirectionalGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + foreach (var v in visitedGraph.Vertices) + if (visitedGraph.IsInEdgesEmpty(v)) + yield return v; + } + + public static IEnumerable IsolatedVertices( + IBidirectionalGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + foreach (var v in visitedGraph.Vertices) + if (visitedGraph.Degree(v) == 0) + yield return v; + } + + public static IEnumerable Roots( + IUndirectedGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + var dfs = new UndirectedDepthFirstSearchAlgorithm(visitedGraph); + var vis = new VertexPredecessorRecorderObserver(); + vis.Attach(dfs); + + foreach (var predecessor in vis.VertexPredecessors) + { + if (predecessor.Value.Equals(default(TEdge))) + yield return predecessor.Key; + } + } + + public static IEnumerable Roots( + IVertexListGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + var dfs = new DepthFirstSearchAlgorithm(visitedGraph); + var vis = new VertexPredecessorRecorderObserver(); + vis.Attach(dfs); + + foreach (var predecessor in vis.VertexPredecessors) + { + if (predecessor.Value.Equals(default(TEdge))) + yield return predecessor.Key; + } + } + + public static ICollection TopologicalSort( + IUndirectedGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + var vertices = new List(visitedGraph.VertexCount); + TopologicalSort(visitedGraph, vertices); + return vertices; + } + + public static void TopologicalSort( + IUndirectedGraph visitedGraph, + IList vertices + ) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + GraphContracts.AssumeNotNull(vertices, "vertices"); + + var topo = new UndirectedTopologicalSortAlgorithm(visitedGraph); + topo.Compute(vertices); + } + + public static ICollection TopologicalSort( + IVertexListGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + var vertices = new List(visitedGraph.VertexCount); + TopologicalSort(visitedGraph, vertices); + return vertices; + } + + public static void TopologicalSort( + IVertexListGraph visitedGraph, + IList vertices) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + GraphContracts.AssumeNotNull(vertices, "vertices"); + + var topo = new TopologicalSortAlgorithm(visitedGraph); + topo.Compute(vertices); + } + + public static ICollection SourceFirstTopologicalSort( + IVertexAndEdgeListGraph visitedGraph) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + var vertices = new List(visitedGraph.VertexCount); + SourceFirstTopologicalSort(visitedGraph, vertices); + return vertices; + } + + public static void SourceFirstTopologicalSort( + IVertexAndEdgeListGraph visitedGraph, + IList vertices) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + GraphContracts.AssumeNotNull(vertices, "vertices"); + + var topo = new SourceFirstTopologicalSortAlgorithm(visitedGraph); + topo.Compute(vertices); + } + + public static int ConnectedComponents( + IUndirectedGraph g, + TVertex startVertex, + IDictionary components) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(g, "g"); + GraphContracts.Assume(g.ContainsVertex(startVertex), "g.ContainsVertex(startVertex)"); + GraphContracts.AssumeNotNull(components, "components"); + + var conn = new ConnectedComponentsAlgorithm(g, components); + conn.Compute(startVertex); + return conn.ComponentCount; + } + + public static int WeaklyConnectedComponents( + IVertexListGraph g, + IDictionary components) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(g, "g"); + GraphContracts.AssumeNotNull(components, "components"); + + var conn = new WeaklyConnectedComponentsAlgorithm(g, components); + conn.Compute(); + return conn.ComponentCount; + } + + public static int StronglyConnectedComponents( + IVertexListGraph g, + IDictionary components) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(g, "g"); + GraphContracts.AssumeNotNull(components, "components"); + + var conn = new StronglyConnectedComponentsAlgorithm(g, components); + conn.Compute(); + return conn.ComponentCount; + } + + public static void Clone( + IVertexAndEdgeListGraph g, + IMutableVertexAndEdgeListGraph clone) + where TVertex : ICloneable + where TEdge : ICloneableEdge + { + GraphContracts.AssumeNotNull(g, "g"); + GraphContracts.AssumeNotNull(clone, "clone"); + + var vertexClones = new Dictionary(); + + foreach (var v in g.Vertices) + { + var vc = (TVertex)v.Clone(); + clone.AddVertex(vc); + vertexClones.Add(v, vc); + } + + foreach (var edge in g.Edges) + { + var ec = (TEdge)edge.Clone( + vertexClones[edge.Source], + vertexClones[edge.Target]); + clone.AddEdge(ec); + } + } + + public static IMutableBidirectionalGraph> Condensate( + IVertexAndEdgeListGraph g) + where TEdge : IEdge + where TGraph : IMutableVertexAndEdgeListGraph, new() + { + if (g == null) + throw new ArgumentNullException("g"); + + var condensator = new CondensationGraphAlgorithm(g); + condensator.Compute(); + return condensator.CondensatedGraph; + } + + /// + /// Create a collection of odd vertices + /// + /// graph to visit + /// colleciton of odd vertices + /// g is a null reference + public static List OddVertices(IVertexAndEdgeListGraph g) + where TEdge : IEdge + { + if (g == null) + throw new ArgumentNullException("g"); + + var counts = new Dictionary(g.VertexCount); + foreach (var v in g.Vertices) + counts.Add(v,0); + + foreach (var e in g.Edges) + { + ++counts[e.Source]; + --counts[e.Target]; + } + + var odds = new List(); + foreach (var de in counts) + { + if (de.Value % 2 != 0) + odds.Add(de.Key); + } + + return odds; + } + + public static bool IsDirectedAcyclicGraph(IVertexListGraph g) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(g, "g"); + + return new DagTester().IsDag(g); + } + + private sealed class DagTester + { + private bool isDag = true; + + public bool IsDag(IVertexListGraph g) + where TEdge : IEdge + { + var dfs = new DepthFirstSearchAlgorithm(g); + try + { + dfs.BackEdge += new EdgeEventHandler(dfs_BackEdge); + isDag = true; + dfs.Compute(); + return isDag; + } + finally + { + dfs.BackEdge -= new EdgeEventHandler(dfs_BackEdge); + } + } + + void dfs_BackEdge(object sender, EdgeEventArgs e) + where Edge : IEdge + { + isDag = false; + } + } + + public static double ComputePredecessorCost( + IDictionary predecessors, + IDictionary edgeCosts, + TVertex target + ) + where TEdge : IEdge + { + GraphContracts.AssumeNotNull(predecessors, "predecessors"); + GraphContracts.AssumeNotNull(edgeCosts, "edgeCosts"); + + double cost = 0; + TVertex current = target; + TEdge edge; + + while (predecessors.TryGetValue(current, out edge)) { + cost += edgeCosts[edge]; + current = edge.Source; + } + + return cost; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs.meta new file mode 100644 index 0000000..795dce5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgoUtility.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 89fbc26e814864e8c9f087e5b704f188 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs new file mode 100755 index 0000000..7fbd4fd --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs @@ -0,0 +1,202 @@ +using System; +using QuickGraph.Algorithms.Services; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms +{ + public abstract class AlgorithmBase : + IAlgorithm, + IAlgorithmComponent + { + private readonly TGraph visitedGraph; + private readonly AlgorithmServices services; + private volatile object syncRoot = new object(); + private volatile ComputationState state = ComputationState.NotRunning; + + /// + /// Creates a new algorithm with an (optional) host. + /// + /// if null, host is set to the this reference + /// + protected AlgorithmBase(IAlgorithmComponent host, TGraph visitedGraph) + { + if (host == null) + host = this; + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + this.visitedGraph = visitedGraph; + this.services = new AlgorithmServices(host); + } + + protected AlgorithmBase(TGraph visitedGraph) + { + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + this.visitedGraph = visitedGraph; + this.services = new AlgorithmServices(this); + } + + public TGraph VisitedGraph + { + get { return this.visitedGraph; } + } + + public IAlgorithmServices Services + { + get { return this.services; } + } + + public Object SyncRoot + { + get { return this.syncRoot; } + } + + public ComputationState State + { + get + { + lock (this.syncRoot) + { + return this.state; + } + } + } + + public void Compute() + { + this.BeginComputation(); + this.InternalCompute(); + this.EndComputation(); + } + + protected abstract void InternalCompute(); + + public void Abort() + { + bool raise = false; + lock (this.syncRoot) + { + if (this.state == ComputationState.Running) + { + this.state = ComputationState.PendingAbortion; + this.Services.CancelManager.Cancel(); + raise = true; + } + } + if (raise) + this.OnStateChanged(EventArgs.Empty); + } + + public event EventHandler StateChanged; + protected virtual void OnStateChanged(EventArgs e) + { + EventHandler eh = this.StateChanged; + if (eh!=null) + eh(this, e); + } + + public event EventHandler Started; + protected virtual void OnStarted(EventArgs e) + { + EventHandler eh = this.Started; + if (eh != null) + eh(this, e); + } + + public event EventHandler Finished; + protected virtual void OnFinished(EventArgs e) + { + EventHandler eh = this.Finished; + if (eh != null) + eh(this, e); + } + + public event EventHandler Aborted; + protected virtual void OnAborted(EventArgs e) + { + EventHandler eh = this.Aborted; + if (eh != null) + eh(this, e); + } + + protected void BeginComputation() + { + lock (this.syncRoot) + { + if (this.state != ComputationState.NotRunning) + throw new InvalidOperationException(); + + this.state = ComputationState.Running; + this.Services.CancelManager.ResetCancel(); + this.OnStarted(EventArgs.Empty); + this.OnStateChanged(EventArgs.Empty); + } + } + + protected void EndComputation() + { + lock (this.syncRoot) + { + switch (this.state) + { + case ComputationState.Running: + this.state = ComputationState.Finished; + this.OnFinished(EventArgs.Empty); + break; + case ComputationState.PendingAbortion: + this.state = ComputationState.Aborted; + this.OnAborted(EventArgs.Empty); + break; + default: + throw new InvalidOperationException(); + } + this.Services.CancelManager.ResetCancel(); + this.OnStateChanged(EventArgs.Empty); + } + } + + public T GetService() + where T : IService + { + T service; + if (!this.TryGetService(out service)) + throw new InvalidOperationException("service not found"); + return service; + } + + public bool TryGetService(out T service) + where T : IService + { + object serviceObject; + if (this.TryGetService(typeof(T), out serviceObject)) + { + service = (T)serviceObject; + return true; + } + + service = default(T); + return false; + } + + Dictionary _services; + protected virtual bool TryGetService(Type serviceType, out object service) + { + GraphContracts.AssumeNotNull(serviceType, "serviceType"); + lock (this.SyncRoot) + { + if (this._services == null) + this._services = new Dictionary(); + if (!this._services.TryGetValue(serviceType, out service)) + { + if (serviceType == typeof(ICancelManager)) + this._services[serviceType] = service = new CancelManager(); + else + this._services[serviceType] = service = null; + } + + return service != null; + + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs.meta new file mode 100644 index 0000000..3107698 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cee0824fd2f8543189ed0fcc274de2f4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs new file mode 100755 index 0000000..d7f5f49 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms +{ + public delegate void AlgorithmEventHandler( + IAlgorithm sender, + EventArgs e); +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs.meta new file mode 100644 index 0000000..dd58f75 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/AlgorithmEventHandler.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 67be721f58b044638a65be46c4e9e9a4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs new file mode 100755 index 0000000..d14ea2d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.ShortestPath; +using QuickGraph.Algorithms.Observers; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class CentralityApproximationAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private Random rand = new Random(); + private DijkstraShortestPathAlgorithm dijkstra; + private VertexPredecessorRecorderObserver predecessorRecorder; + private int maxIterationCount = 50; + private IDictionary centralities = new Dictionary(); + + public CentralityApproximationAlgorithm( + IVertexListGraph visitedGraph, + IDictionary distances + ) + :base(visitedGraph) + { + if (distances==null) + throw new ArgumentNullException("distances"); + this.dijkstra = new DijkstraShortestPathAlgorithm( + this.VisitedGraph, + distances, + new ShortestDistanceRelaxer() + ); + this.predecessorRecorder = new VertexPredecessorRecorderObserver(); + this.predecessorRecorder.Attach(this.dijkstra); + } + + public IDictionary Distances + { + get { return this.dijkstra.Weights; } + } + + public Random Rand + { + get { return this.rand; } + set { this.rand = value; } + } + + public int MaxIterationCount + { + get { return this.maxIterationCount; } + set { this.maxIterationCount = value; } + } + + private void Initialize() + { + this.centralities.Clear(); + foreach (var v in this.VisitedGraph.Vertices) + this.centralities.Add(v, 0); + } + + protected override void InternalCompute() + { + if (this.VisitedGraph.VertexCount == 0) + return; + + // compute temporary values + int n = this.VisitedGraph.VertexCount; + for(int i = 0;i(this.VisitedGraph, this.Rand); + this.dijkstra.Compute(v); + + foreach (var u in this.VisitedGraph.Vertices) + this.centralities[u] += n * this.dijkstra.Distances[u] / (this.MaxIterationCount * (n - 1)); + } + + // update + foreach (var v in this.VisitedGraph.Vertices) + this.centralities[v] = 1.0/this.centralities[v]; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs.meta new file mode 100644 index 0000000..fb66180 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/CentralityApproximationAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 19512a09eb387494f938ab982fbf2e77 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs new file mode 100755 index 0000000..99ccb63 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs @@ -0,0 +1,14 @@ +using System; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public enum ComputationState + { + NotRunning, + Running, + PendingAbortion, + Finished, + Aborted + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs.meta new file mode 100644 index 0000000..619566a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ComputationState.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5d8efbe7dc2294f068a7030f3fb06a26 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation.meta new file mode 100644 index 0000000..a3bfa83 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 55ef485efbff643cc8984c6e972e9381 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs new file mode 100755 index 0000000..a837be6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Collections; + +namespace QuickGraph.Algorithms.Condensation +{ + [Serializable] + public sealed class CondensatedEdge : Edge + where TEdge : IEdge + where TGraph : IMutableVertexAndEdgeListGraph, new() + { + private List edges = new List(); + public CondensatedEdge(TGraph source, TGraph target) + :base(source,target) + { } + + public IList Edges + { + get { return this.edges; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs.meta new file mode 100644 index 0000000..d7b43b2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensatedEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 93f7a6ea0b1b748ae95cfd44628c122b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs new file mode 100755 index 0000000..9b0d873 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Collections; + +namespace QuickGraph.Algorithms.Condensation +{ + public sealed class CondensationGraphAlgorithm : + AlgorithmBase> + where TEdge : IEdge + where TGraph : IMutableVertexAndEdgeListGraph, new() + { + private bool stronglyConnected = true; + + private IMutableBidirectionalGraph< + TGraph, + CondensatedEdge + > condensatedGraph; + + public CondensationGraphAlgorithm(IVertexAndEdgeListGraph visitedGraph) + :base(visitedGraph) + {} + + public IMutableBidirectionalGraph< + TGraph, + CondensatedEdge + > CondensatedGraph + { + get { return this.condensatedGraph; } + } + + public bool StronglyConnected + { + get { return this.stronglyConnected; } + set { this.stronglyConnected = value; } + } + + protected override void InternalCompute() + { + // create condensated graph + this.condensatedGraph = new BidirectionalGraph< + TGraph, + CondensatedEdge + >(false); + if (this.VisitedGraph.VertexCount == 0) + return; + + // compute strongly connected components + var components = new Dictionary(this.VisitedGraph.VertexCount); + int componentCount = ComputeComponentCount(components); + + var cancelManager = this.Services.CancelManager; + if (cancelManager.IsCancelling) return; + + // create list vertices + var condensatedVertices = new Dictionary(componentCount); + for (int i = 0; i < componentCount; ++i) + { + if (cancelManager.IsCancelling) return; + + TGraph v = new TGraph(); + condensatedVertices.Add(i, v); + this.condensatedGraph.AddVertex(v); + } + + // addingvertices + foreach (var v in this.VisitedGraph.Vertices) + { + condensatedVertices[components[v]].AddVertex(v); + } + if (cancelManager.IsCancelling) return; + + // condensated edges + var condensatedEdges = new Dictionary>(componentCount); + + // iterate over edges and condensate graph + foreach (var edge in this.VisitedGraph.Edges) + { + if (cancelManager.IsCancelling) return; + + // get component ids + int sourceID = components[edge.Source]; + int targetID = components[edge.Target]; + + // get vertices + TGraph sources = condensatedVertices[sourceID]; + if (sourceID == targetID) + { + sources.AddEdge(edge); + continue; + } + + // + TGraph targets = condensatedVertices[targetID]; + + // at last add edge + var edgeKey = new EdgeKey(sourceID, targetID); + CondensatedEdge condensatedEdge; + if (!condensatedEdges.TryGetValue(edgeKey, out condensatedEdge)) + { + condensatedEdge = new CondensatedEdge(sources, targets); + condensatedEdges.Add(edgeKey, condensatedEdge); + this.condensatedGraph.AddEdge(condensatedEdge); + } + condensatedEdge.Edges.Add(edge); + } + } + + private int ComputeComponentCount(Dictionary components) + { + IConnectedComponentAlgorithm> componentAlgorithm; + if (this.StronglyConnected) + componentAlgorithm = new StronglyConnectedComponentsAlgorithm( + this, + this.VisitedGraph, + components); + else + componentAlgorithm = new WeaklyConnectedComponentsAlgorithm( + this, + this.VisitedGraph, + components); + componentAlgorithm.Compute(); + return componentAlgorithm.ComponentCount; + } + + private struct EdgeKey : IEquatable + { + int SourceID; + int TargetID; + + public EdgeKey(int sourceID, int targetID) + { + SourceID = sourceID; + TargetID = targetID; + } + + public bool Equals(EdgeKey other) + { + return + SourceID == other.SourceID + && TargetID == other.TargetID; + } + + public override int GetHashCode() + { + return HashCodeHelper.Combine(this.SourceID, this.TargetID); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs.meta new file mode 100644 index 0000000..ca79d84 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/CondensationGraphAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 837e6a695ed574f06a9fbc378d47b4e3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs new file mode 100755 index 0000000..bf69757 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Condensation +{ + public sealed class EdgeMergeCondensationGraphAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private IMutableBidirectionalGraph< + TVertex, + MergedEdge + > condensatedGraph; + private VertexPredicate vertexPredicate; + + public EdgeMergeCondensationGraphAlgorithm( + IBidirectionalGraph visitedGraph, + IMutableBidirectionalGraph> condensatedGraph, + VertexPredicate vertexPredicate + ) + :base(visitedGraph) + { + if (condensatedGraph == null) + throw new ArgumentNullException("condensatedGraph"); + if (vertexPredicate == null) + throw new ArgumentNullException("vertexPredicate"); + + this.condensatedGraph = condensatedGraph; + this.vertexPredicate = vertexPredicate; + } + + public IMutableBidirectionalGraph + > CondensatedGraph + { + get { return this.condensatedGraph; } + } + + public VertexPredicate VertexPredicate + { + get { return this.vertexPredicate; } + } + + protected override void InternalCompute() + { + // adding vertices to the new graph + // and pusing filtered vertices in queue + Queue filteredVertices = new Queue(); + foreach (var v in this.VisitedGraph.Vertices) + { + this.CondensatedGraph.AddVertex(v); + if (!this.VertexPredicate(v)) + filteredVertices.Enqueue(v); + } + + // adding all edges + foreach (var edge in this.VisitedGraph.Edges) + { + MergedEdge mergedEdge = new MergedEdge(edge.Source, edge.Target); + mergedEdge.Edges.Add(edge); + + this.CondensatedGraph.AddEdge(mergedEdge); + } + + // remove vertices + while (filteredVertices.Count > 0) + { + TVertex filteredVertex = filteredVertices.Dequeue(); + + // do the cross product between inedges and outedges + MergeVertex(filteredVertex); + } + } + + private void MergeVertex(TVertex v) + { + // get in edges and outedge + List> inEdges = + new List>(this.CondensatedGraph.InEdges(v)); + List> outEdges = + new List>(this.CondensatedGraph.OutEdges(v)); + + // remove vertex + this.CondensatedGraph.RemoveVertex(v); + + // add condensated edges + for (int i = 0; i < inEdges.Count; ++i) + { + MergedEdge inEdge = inEdges[i]; + if (inEdge.Source.Equals(v)) + continue; + + for (int j = 0; j < outEdges.Count; ++j) + { + MergedEdge outEdge = outEdges[j]; + if (outEdge.Target.Equals(v)) + continue; + + MergedEdge newEdge = + MergedEdge.Merge(inEdge, outEdge); + this.CondensatedGraph.AddEdge(newEdge); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs.meta new file mode 100644 index 0000000..e3c1970 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/EdgeMergeCondensationGraphAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 95ba75344ded843e289c04b133cc8629 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs new file mode 100755 index 0000000..2a00cb4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Collections; + +namespace QuickGraph.Algorithms.Condensation +{ + [Serializable] + public sealed class MergedEdge : Edge + where TEdge : IEdge + { + private List edges = new List(); + + public MergedEdge(TVertex source, TVertex target) + :base(source,target) + { } + + public IList Edges + { + get { return this.edges; } + } + + public static MergedEdge Merge( + MergedEdge inEdge, + MergedEdge outEdge + ) + { + MergedEdge newEdge = new MergedEdge( + inEdge.Source, outEdge.Target); + newEdge.edges = new List(inEdge.Edges.Count + outEdge.Edges.Count); + newEdge.edges.AddRange(inEdge.Edges); + newEdge.edges.AddRange(outEdge.edges); + + return newEdge; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs.meta new file mode 100644 index 0000000..fd653e4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Condensation/MergedEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 17b0e3b604249468f9afd303dbfe7b6a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs new file mode 100755 index 0000000..420e5b8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class ConnectedComponentsAlgorithm : + RootedAlgorithmBase>, + IConnectedComponentAlgorithm> + where TEdge : IEdge + { + private IDictionary components; + private int componentCount=0; + + public ConnectedComponentsAlgorithm(IUndirectedGraph g) + :this(g, new Dictionary()) + { } + + public ConnectedComponentsAlgorithm( + IUndirectedGraph visitedGraph, + IDictionary components) + : this(null, visitedGraph, components) + { } + + public ConnectedComponentsAlgorithm( + IAlgorithmComponent host, + IUndirectedGraph visitedGraph, + IDictionary components) + :base(host, visitedGraph) + { + if (components == null) + throw new ArgumentNullException("components"); + + this.components = components; + } + + public IDictionary Components + { + get + { + return this.components; + } + } + + public int ComponentCount + { + get { return this.componentCount; } + } + + private void StartVertex(Object sender, VertexEventArgs args) + { + ++this.componentCount; + } + + private void DiscoverVertex(Object sender, VertexEventArgs args) + { + Components[args.Vertex] = this.componentCount; + } + + protected override void InternalCompute() + { + this.componentCount = -1; + this.components.Clear(); + + UndirectedDepthFirstSearchAlgorithm dfs = null; + try + { + dfs = new UndirectedDepthFirstSearchAlgorithm( + this, + this.VisitedGraph, + new Dictionary(this.VisitedGraph.VertexCount) + ); + + dfs.StartVertex += new VertexEventHandler(this.StartVertex); + dfs.DiscoverVertex += new VertexEventHandler(this.DiscoverVertex); + + if (this.VisitedGraph.VertexCount != 0) + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + rootVertex = TraversalHelper.GetFirstVertex(this.VisitedGraph); + dfs.Compute(rootVertex); + } + + ++this.componentCount; + } + finally + { + if (dfs != null) + { + dfs.StartVertex -= new VertexEventHandler(this.StartVertex); + dfs.DiscoverVertex -= new VertexEventHandler(this.DiscoverVertex); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs.meta new file mode 100644 index 0000000..9aa7a64 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ConnectedComponentsAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3f74b052c713f4263a0c0d6bfb8171cf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs new file mode 100755 index 0000000..02b1069 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs @@ -0,0 +1,465 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class EulerianTrailAlgorithm : + RootedAlgorithmBase>, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private List circuit; + private List temporaryCircuit; + private TVertex currentVertex; + private List temporaryEdges; + + public EulerianTrailAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph) + : this(null, visitedGraph) + { } + + /// + /// Construct an eulerian trail builder + /// + /// + public EulerianTrailAlgorithm( + IAlgorithmComponent host, + IMutableVertexAndEdgeListGraph visitedGraph) + :base(host, visitedGraph) + { + this.circuit = new List(); + this.temporaryCircuit = new List(); + this.currentVertex = default(TVertex); + this.temporaryEdges = new List(); + } + + public List Circuit + { + get + { + return circuit; + } + } + + private bool NotInCircuit(TEdge edge) + { + return !this.circuit.Contains(edge) + && !this.temporaryCircuit.Contains(edge); + } + + private IEnumerable SelectOutEdgesNotInCircuit(TVertex v) + { + foreach (var edge in VisitedGraph.OutEdges(v)) + if (this.NotInCircuit(edge)) + yield return edge; + } + + private TEdge SelectSingleOutEdgeNotInCircuit(TVertex v) + { + IEnumerable en = this.SelectOutEdgesNotInCircuit(v); + IEnumerator eor = en.GetEnumerator(); + if (!eor.MoveNext()) + return default(TEdge); + else + return eor.Current; + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler CircuitEdge; + private void OnCircuitEdge(TEdge e) + { + if (CircuitEdge != null) + CircuitEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler VisitEdge; + private void OnVisitEdge(TEdge e) + { + if (VisitEdge != null) + VisitEdge(this, new EdgeEventArgs(e)); + } + + private bool Search(TVertex u) + { + foreach (var e in SelectOutEdgesNotInCircuit(u)) + { + OnTreeEdge(e); + TVertex v = e.Target; + // add edge to temporary path + this.temporaryCircuit.Add(e); + // e.Target should be equal to CurrentVertex. + if (e.Target.Equals(this.currentVertex)) + return true; + + // continue search + if (Search(v)) + return true; + else + // remove edge + this.temporaryCircuit.Remove(e); + } + + // it's a dead end. + return false; + } + + + /// + /// Looks for a new path to add to the current vertex. + /// + /// true if found a new path, false otherwize + private bool Visit() + { + // find a vertex that needs to be visited + foreach (var e in Circuit) + { + TEdge fe = SelectSingleOutEdgeNotInCircuit(e.Source); + if (fe != null) + { + OnVisitEdge(fe); + this.currentVertex = e.Source; + if (Search(currentVertex)) + return true; + } + } + + // Could not augment circuit + return false; + } + + /// + /// Computes the number of eulerian trail in the graph. + /// + /// + /// number of eulerian trails + public static int ComputeEulerianPathCount(IVertexAndEdgeListGraph g) + { + if (g == null) + throw new ArgumentNullException("g"); + + if (g.EdgeCount < g.VertexCount) + return 0; + + int odd = AlgoUtility.OddVertices(g).Count; + if (odd == 0) + return 1; + else if (odd % 2 != 0) + return 0; + else + return odd / 2; + } + + /// + /// Merges the temporary circuit with the current circuit + /// + /// true if all the graph edges are in the circuit + private bool CircuitAugmentation() + { + List newC = new List(this.circuit.Count + this.temporaryCircuit.Count); + int i, j; + + // follow C until w is found + for (i = 0; i < Circuit.Count; ++i) + { + TEdge e = Circuit[i]; + if (e.Source.Equals(currentVertex)) + break; + newC.Add(e); + } + + // follow D until w is found again + for (j = 0; j < this.temporaryCircuit.Count; ++j) + { + TEdge e = this.temporaryCircuit[j]; + newC.Add(e); + OnCircuitEdge(e); + if (e.Target.Equals(this.currentVertex)) + break; + } + this.temporaryCircuit.Clear(); + + // continue C + for (; i < Circuit.Count; ++i) + { + TEdge e = this.Circuit[i]; + newC.Add(e); + } + + // set as new circuit + circuit = newC; + + // check if contains all edges + if (this.circuit.Count == this.VisitedGraph.EdgeCount) + return true; + + return false; + } + + protected override void InternalCompute() + { + if (this.VisitedGraph.VertexCount == 0) + return; + + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + rootVertex = TraversalHelper.GetFirstVertex(this.VisitedGraph); + + this.currentVertex = rootVertex; + // start search + Search(this.currentVertex); + if (CircuitAugmentation()) + return; // circuit is found + + do + { + if (!Visit()) + break; // visit edges and build path + if (CircuitAugmentation()) + break; // circuit is found + } while (true); + } + + /// + /// Adds temporary edges to the graph to make all vertex even. + /// + /// + /// + public List AddTemporaryEdges(IEdgeFactory edgeFactory) + { + // first gather odd edges. + List oddVertices = AlgoUtility.OddVertices(this.VisitedGraph); + + // check that there are an even number of them + if (oddVertices.Count % 2 != 0) + throw new Exception("number of odd vertices in not even!"); + + // add temporary edges to create even edges: + this.temporaryEdges = new List(); + + bool found, foundbe, foundadjacent; + while (oddVertices.Count > 0) + { + TVertex u = oddVertices[0]; + // find adjacent odd vertex. + found = false; + foundadjacent = false; + foreach (var e in this.VisitedGraph.OutEdges(u)) + { + TVertex v = e.Target; + if (!v.Equals(u) && oddVertices.Contains(v)) + { + foundadjacent = true; + // check that v does not have an out-edge towards u + foundbe = false; + foreach (var be in this.VisitedGraph.OutEdges(v)) + { + if (be.Target.Equals(u)) + { + foundbe = true; + break; + } + } + if (foundbe) + continue; + // add temporary edge + TEdge tempEdge = edgeFactory.CreateEdge(v, u); + if (!this.VisitedGraph.AddEdge(tempEdge)) + throw new InvalidOperationException(); + // add to collection + temporaryEdges.Add(tempEdge); + // remove u,v from oddVertices + oddVertices.Remove(u); + oddVertices.Remove(v); + // set u to null + found = true; + break; + } + } + + if (!foundadjacent) + { + // pick another vertex + if (oddVertices.Count < 2) + throw new Exception("Eulerian trail failure"); + TVertex v = oddVertices[1]; + TEdge tempEdge = edgeFactory.CreateEdge(u, v); + if (!this.VisitedGraph.AddEdge(tempEdge)) + throw new InvalidOperationException(); + // add to collection + temporaryEdges.Add(tempEdge); + // remove u,v from oddVertices + oddVertices.Remove(u); + oddVertices.Remove(v); + // set u to null + found = true; + + } + + if (!found) + { + oddVertices.Remove(u); + oddVertices.Add(u); + } + } + return this.temporaryEdges; + } + + /// + /// Removes temporary edges + /// + /// + public void RemoveTemporaryEdges() + { + // remove from graph + foreach (var e in temporaryEdges) + this.VisitedGraph.RemoveEdge(e); + this.temporaryEdges.Clear(); + } + + /// + /// Computes the set of eulerian trails that traverse the edge set. + /// + /// + /// This method returns a set of disjoint eulerian trails. This set + /// of trails spans the entire set of edges. + /// + /// Eulerian trail set + public ICollection> Trails() + { + List> trails = new List>(); + + List trail = new List(); + foreach (var e in this.Circuit) + { + if (this.temporaryEdges.Contains(e)) + { + // store previous trail and start new one. + if (trail.Count != 0) + trails.Add(trail); + // start new trail + trail = new List(); + } + else + trail.Add(e); + } + if (trail.Count != 0) + trails.Add(trail); + + return trails; + } + + /// + /// Computes a set of eulerian trail, starting at + /// that spans the entire graph. + /// + /// + /// + /// This method computes a set of eulerian trail starting at + /// that spans the entire graph.The algorithm outline is as follows: + /// + /// + /// The algorithms iterates throught the Eulerian circuit of the augmented + /// graph (the augmented graph is the graph with additional edges to make + /// the number of odd vertices even). + /// + /// + /// If the current edge is not temporary, it is added to the current trail. + /// + /// + /// If the current edge is temporary, the current trail is finished and + /// added to the trail collection. The shortest path between the + /// start vertex and the target vertex of the + /// temporary edge is then used to start the new trail. This shortest + /// path is computed using the . + /// + /// + /// start vertex + /// eulerian trail set, all starting at s + /// s is a null reference. + /// Eulerian trail not computed yet. + public ICollection> Trails(TVertex s) + { + if (s == null) + throw new ArgumentNullException("s"); + if (this.Circuit.Count == 0) + throw new Exception("Circuit is empty"); + + // find the first edge in the circuit. + int i = 0; + for (i = 0; i < this.Circuit.Count; ++i) + { + TEdge e = this.Circuit[i]; + if (this.temporaryEdges.Contains(e)) + continue; + if (e.Source.Equals(s)) + break; + } + if (i == this.Circuit.Count) + throw new Exception("Did not find vertex in eulerian trail?"); + + // create collections + List> trails = new List>(); + List trail = new List(); + BreadthFirstSearchAlgorithm bfs = + new BreadthFirstSearchAlgorithm(VisitedGraph); + VertexPredecessorRecorderObserver vis = + new VertexPredecessorRecorderObserver(); + vis.Attach(bfs); + bfs.Compute(s); + + // go throught the edges and build the predecessor table. + int start = i; + for (; i < this.Circuit.Count; ++i) + { + TEdge e = this.Circuit[i]; + if (this.temporaryEdges.Contains(e)) + { + // store previous trail and start new one. + if (trail.Count != 0) + trails.Add(trail); + // start new trail + // take the shortest path from the start vertex to + // the target vertex + trail = vis.Path(e.Target); + } + else + trail.Add(e); + } + + // starting again on the circuit + for (i = 0; i < start; ++i) + { + TEdge e = this.Circuit[i]; + if (this.temporaryEdges.Contains(e)) + { + // store previous trail and start new one. + if (trail.Count != 0) + trails.Add(trail); + // start new trail + // take the shortest path from the start vertex to + // the target vertex + trail = vis.Path(e.Target); + } + else + trail.Add(e); + } + + // adding the last element + if (trail.Count != 0) + trails.Add(trail); + + return trails; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs.meta new file mode 100644 index 0000000..9e6463e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/EulerianTrailAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a940e93d8117f4284a84d4f30c98b8bd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration.meta new file mode 100644 index 0000000..f5b6705 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: f3524a21373dc4caa93b0111d51c0890 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs new file mode 100755 index 0000000..46dad20 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Predicates; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Exploration +{ + public sealed class CloneableVertexGraphExplorerAlgorithm : + RootedAlgorithmBase>, + ITreeBuilderAlgorithm + where TVertex : ICloneable, IComparable + where TEdge : IEdge + { + private IList> transitionFactories = new List>(); + + private Queue unexploredVertices = new Queue(); + + private VertexPredicate addVertexPredicate = new AnyVertexPredicate().Test; + private VertexPredicate exploreVertexPredicate = new AnyVertexPredicate().Test; + private EdgePredicate addEdgePredicate = new AnyEdgePredicate().Test; + private IPredicate> finishedPredicate = + new DefaultFinishedPredicate(); + private bool finishedSuccessfully; + + public CloneableVertexGraphExplorerAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph + ) + : this(null, visitedGraph) + { } + + public CloneableVertexGraphExplorerAlgorithm( + IAlgorithmComponent host, + IMutableVertexAndEdgeListGraph visitedGraph + ) + :base(host, visitedGraph) + {} + + public IList> TransitionFactories + { + get { return this.transitionFactories; } + } + + public VertexPredicate AddVertexPredicate + { + get { return this.addVertexPredicate; } + set { this.addVertexPredicate = value; } + } + + public VertexPredicate ExploreVertexPredicate + { + get { return this.exploreVertexPredicate; } + set { this.exploreVertexPredicate = value; } + } + + public EdgePredicate AddEdgePredicate + { + get { return this.addEdgePredicate; } + set { this.addEdgePredicate = value; } + } + + public IPredicate> FinishedPredicate + { + get { return this.finishedPredicate; } + set { this.finishedPredicate = value; } + } + + public IEnumerable UnexploredVertices + { + get { return this.unexploredVertices; } + } + + public bool FinishedSuccessfully + { + get { return this.finishedSuccessfully; } + } + + public event VertexEventHandler DiscoverVertex; + private void OnDiscoverVertex(TVertex v) + { + this.VisitedGraph.AddVertex(v); + this.unexploredVertices.Enqueue(v); + if (this.DiscoverVertex != null) + this.DiscoverVertex(this, new VertexEventArgs(v)); + } + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (this.TreeEdge != null) + this.TreeEdge(this, new EdgeEventArgs(e)); + } + public event EdgeEventHandler BackEdge; + private void OnBackEdge(TEdge e) + { + if (this.BackEdge != null) + this.BackEdge(this, new EdgeEventArgs(e)); + } + public event EdgeEventHandler EdgeSkipped; + private void OnEdgeSkipped(TEdge e) + { + if (this.EdgeSkipped != null) + this.EdgeSkipped(this, new EdgeEventArgs(e)); + } + + protected override void InternalCompute() + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + throw new InvalidOperationException("RootVertex is not specified"); + + this.VisitedGraph.Clear(); + this.unexploredVertices.Clear(); + this.finishedSuccessfully = false; + + if (!this.AddVertexPredicate(rootVertex)) + throw new ArgumentException("StartVertex does not satisfy AddVertexPredicate"); + this.OnDiscoverVertex(rootVertex); + + while (unexploredVertices.Count > 0) + { + // are we done yet ? + if (!this.FinishedPredicate.Test(this)) + { + this.finishedSuccessfully = false; + return; + } + + TVertex current = unexploredVertices.Dequeue(); + TVertex clone = (TVertex)current.Clone(); + + // let's make sure we want to explore this one + if (!this.ExploreVertexPredicate(clone)) + continue; + + foreach (ITransitionFactory transitionFactory in this.TransitionFactories) + { + GenerateFromTransitionFactory(clone, transitionFactory); + } + } + + this.finishedSuccessfully = true; + } + + private void GenerateFromTransitionFactory( + TVertex current, + ITransitionFactory transitionFactory + ) + { + if (!transitionFactory.IsValid(current)) + return; + + foreach (var transition in transitionFactory.Apply(current)) + { + if ( + !this.AddVertexPredicate(transition.Target) + || !this.AddEdgePredicate(transition)) + { + this.OnEdgeSkipped(transition); + continue; + } + + bool backEdge = this.VisitedGraph.ContainsVertex(transition.Target); + if (!backEdge) + this.OnDiscoverVertex(transition.Target); + + this.VisitedGraph.AddEdge(transition); + if (backEdge) + this.OnBackEdge(transition); + else + this.OnTreeEdge(transition); + } + } + + public sealed class DefaultFinishedPredicate : + IPredicate> + { + private int maxVertexCount = 1000; + private int maxEdgeCount = 1000; + + public DefaultFinishedPredicate() + { } + + public DefaultFinishedPredicate( + int maxVertexCount, + int maxEdgeCount) + { + this.maxVertexCount = maxVertexCount; + this.maxEdgeCount = maxEdgeCount; + } + + public int MaxVertexCount + { + get { return this.maxVertexCount; } + set { this.maxVertexCount = value; } + } + + public int MaxEdgeCount + { + get { return this.maxEdgeCount; } + set { this.maxEdgeCount = value; } + } + + public bool Test(CloneableVertexGraphExplorerAlgorithm t) + { + if (t.VisitedGraph.VertexCount > this.MaxVertexCount) + return false; + if (t.VisitedGraph.EdgeCount > this.MaxEdgeCount) + return false; + return true; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs.meta new file mode 100644 index 0000000..a3792e7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/CloneableVertexGraphExplorerAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 02dff452d0e0a44298315814928be32f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs new file mode 100755 index 0000000..5e8f7ae --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Exploration +{ + public interface ITransitionFactory + where TVertex : ICloneable + where TEdge : IEdge + { + bool IsValid(TVertex v); + IEnumerable Apply(TVertex source); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs.meta new file mode 100644 index 0000000..df4fc01 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/ITransitionFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d36da0bf200c46dabc3deb6a4c1df18 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs new file mode 100755 index 0000000..a688abd --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Web; + +using QuickGraph.Predicates; + +namespace QuickGraph.Algorithms.Exploration +{ + public sealed class TransitionFactoryImplicitGraph : + IImplicitGraph + where TVertex : ICloneable + where TEdge : IEdge + { + private IList> transitionFactories + = new List>(); + private VertexPredicate successorVertexPredicate + = new AnyVertexPredicate().Test; + private EdgePredicate successorEdgePredicate + = new AnyEdgePredicate().Test; + + public TransitionFactoryImplicitGraph() + {} + + public IList> TransitionFactories + { + get { return this.transitionFactories; } + } + + public VertexPredicate SuccessorVertexPredicate + { + get { return this.successorVertexPredicate; } + set { this.successorVertexPredicate = value; } + } + + public EdgePredicate SuccessorEdgePredicate + { + get { return this.successorEdgePredicate; } + set { this.successorEdgePredicate = value; } + } + + public bool IsOutEdgesEmpty(TVertex v) + { + return this.OutDegree(v) == 0; + } + + public int OutDegree(TVertex v) + { + int i = 0; + foreach(TEdge edge in this.OutEdges(v)) + i++; + return i; + } + + public IEnumerable OutEdges(TVertex v) + { + foreach (ITransitionFactory transitionFactory + in this.TransitionFactories) + { + if (!transitionFactory.IsValid(v)) + continue; + + foreach (var edge in transitionFactory.Apply(v)) + { + if (this.SuccessorVertexPredicate(edge.Target) && + this.SuccessorEdgePredicate(edge)) + yield return edge; + } + } + } + + public TEdge OutEdge(TVertex v, int index) + { + int i = 0; + foreach (var e in this.OutEdges(v)) + if (i++ == index) + return e; + throw new ArgumentOutOfRangeException("index"); + } + + public bool IsDirected + { + get { return true; } + } + + public bool AllowParallelEdges + { + get { return true; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs.meta new file mode 100644 index 0000000..6feef29 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Exploration/TransitionFactoryImplicitGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d3af236a89624bd4a47ab82205e1101 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs new file mode 100755 index 0000000..1b1d894 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs @@ -0,0 +1,11 @@ +using System; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms +{ + public interface IAlgorithm : + IComputation + { + TGraph VisitedGraph { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs.meta new file mode 100644 index 0000000..8eb78c9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 34fcc00df114c400cbf489b982a8fd19 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs new file mode 100755 index 0000000..3760d38 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms +{ + public interface IComputation + { + object SyncRoot { get; } + ComputationState State { get; } + + void Compute(); + void Abort(); + + event EventHandler StateChanged; + event EventHandler Started; + event EventHandler Finished; + event EventHandler Aborted; + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs.meta new file mode 100644 index 0000000..3ec3d2f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IComputation.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6b96eaa25642248f6b768d338c733e6c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs new file mode 100755 index 0000000..7548022 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms +{ + public interface IConnectedComponentAlgorithm : IAlgorithm + where TGraph : IGraph + where TEdge : IEdge + { + int ComponentCount { get;} + IDictionary Components { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs.meta new file mode 100644 index 0000000..9fd381e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IConnectedComponentAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 877c61d80ee594c83bbf5b27b0451232 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs new file mode 100755 index 0000000..e290517 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Algorithms +{ + public interface IDistanceRecorderAlgorithm + where TEdge : IEdge + { + event VertexEventHandler InitializeVertex; + event VertexEventHandler DiscoverVertex; + event EdgeEventHandler TreeEdge; + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs.meta new file mode 100644 index 0000000..1df0e5f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IDistanceRecorderAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc9d326915c874296834d9364a8865d0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs new file mode 100755 index 0000000..2924527 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms +{ + public interface IEdgeColorizerAlgorithm + where TEdge : IEdge + { + IDictionary EdgeColors { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs.meta new file mode 100644 index 0000000..16bc9b6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgeColorizerAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cf274d3b62019415aaac2c8bab740906 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs new file mode 100755 index 0000000..1309724 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs @@ -0,0 +1,11 @@ +using System; + +namespace QuickGraph.Algorithms +{ + public interface IEdgePredecessorRecorderAlgorithm + where TEdge : IEdge + { + event EdgeEdgeEventHandler DiscoverTreeEdge; + event EdgeEventHandler FinishEdge; + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs.meta new file mode 100644 index 0000000..e6426aa --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEdgePredecessorRecorderAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c2e18ce75aa4f42b183331b04b6914c4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs new file mode 100755 index 0000000..16b4ecb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs @@ -0,0 +1,8 @@ +using System; +namespace QuickGraph.Algorithms +{ + public interface IEndPathEdgeRecorderAlgorithm + where TEdge : IEdge + { + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs.meta new file mode 100644 index 0000000..44cf459 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IEndPathEdgeRecorderAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9f005fb3218f4681a3dec7366b02b63 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs new file mode 100755 index 0000000..3a826d6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs @@ -0,0 +1,10 @@ +using System; + +namespace QuickGraph.Algorithms +{ + public interface ITreeBuilderAlgorithm + where TEdge : IEdge + { + event EdgeEventHandler TreeEdge; + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs.meta new file mode 100644 index 0000000..1ee6099 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ITreeBuilderAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9183401b3c05f4eb994c9a91369b1776 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs new file mode 100755 index 0000000..9d8ec7d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms +{ + public interface IVertexColorizerAlgorithm + where TEdge : IEdge + { + IDictionary VertexColors { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs.meta new file mode 100644 index 0000000..1b5fc20 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexColorizerAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3cd3b6d5e25bf4d44900434bb396a264 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs new file mode 100755 index 0000000..a5d980f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Algorithms +{ + public interface IVertexPredecessorRecorderAlgorithm : + ITreeBuilderAlgorithm + where TEdge : IEdge + { + event VertexEventHandler StartVertex; + event VertexEventHandler FinishVertex; + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs.meta new file mode 100644 index 0000000..1067951 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexPredecessorRecorderAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0d2dabc76db540e184b6f2dfeabbd01 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs new file mode 100755 index 0000000..6ee96d4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs @@ -0,0 +1,11 @@ +using System; + +namespace QuickGraph.Algorithms +{ + public interface IVertexTimeStamperAlgorithm + where TEdge : IEdge + { + event VertexEventHandler DiscoverVertex; + event VertexEventHandler FinishVertex; + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs.meta new file mode 100644 index 0000000..0d7ffd5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/IVertexTimeStamperAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d8a69b4e653a949bb8083f59c73da0d7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix.meta new file mode 100644 index 0000000..4db64b5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: b099c7cc50f984060aea32bf39e54dcb +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs new file mode 100755 index 0000000..d1780d7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms.Matrix +{ + public sealed class DenseFloatMatrix + { + private readonly int rowCount; + private readonly int columnCount; + private float[] data; + + public DenseFloatMatrix(int rowCount, int columnCount) + { + this.rowCount = rowCount; + this.columnCount = columnCount; + this.data = new float[this.rowCount * this.columnCount]; + } + + public int RowCount + { + get { return this.rowCount; } + } + + public int ColumnCount + { + get { return this.columnCount; } + } + + public float this[int i, int j] + { + get { return this.data[i * this.columnCount + j]; } + set { this.data[i * this.columnCount + j] = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs.meta new file mode 100644 index 0000000..a2d1dc0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DenseFloatMatrix.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a803d4b514d34bc091bac19c3517357 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs new file mode 100755 index 0000000..a76ba24 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs @@ -0,0 +1,382 @@ +using System; +using System.IO; +namespace QuickGraph.Algorithms.Matrix +{ + [Serializable] + public sealed class DoubleDenseMatrix : ICloneable + { + private readonly double[] data; + private readonly int rowCount; + private readonly int columnCount; + + public static DoubleDenseMatrix Create(DoubleDenseMatrix matrix) + { + return new DoubleDenseMatrix(matrix.RowCount, matrix.ColumnCount, matrix.GetData()); + } + + public static DoubleDenseMatrix Create(int rowCount, int columnCount, Double value) + { + // + if (columnCount * rowCount < 0) + throw new ArgumentException("columnCount * rowCount < 0"); + // + double[] data = new double[rowCount * columnCount]; + for (int i = 0; i < data.Length; ++i) + data[i] = value; + + return new DoubleDenseMatrix(rowCount, columnCount, data); + } + + public DoubleDenseMatrix (int rowCount, int columnCount) + { + // + if (rowCount < 0) + throw new ArgumentOutOfRangeException("rowCount"); + if (columnCount < 0) + throw new ArgumentOutOfRangeException("rowCount"); + if (columnCount * rowCount < 0) + throw new ArgumentException("columnCount * rowCount < 0"); + // + + this.rowCount = rowCount; + this.columnCount = columnCount; + this.data = new double[rowCount * columnCount]; + } + + private DoubleDenseMatrix(int rowCount, int columnCount, double[] data) + { + if (rowCount < 0) + throw new ArgumentOutOfRangeException("rowCount"); + if (columnCount < 0) + throw new ArgumentOutOfRangeException("rowCount"); + if (rowCount * columnCount != data.Length) + throw new ArgumentOutOfRangeException("data"); + + this.rowCount = rowCount; + this.columnCount = columnCount; + this.data = data; + } + + private void VerifySize(DoubleDenseMatrix matrix) + { + if (this.RowCount != matrix.RowCount) + throw new MatrixSizeMistmatchException(); + if (this.ColumnCount != matrix.ColumnCount) + throw new MatrixSizeMistmatchException(); + } + + #region Basic matrix + public int RowCount + { + get { return this.rowCount; } + } + + public int ColumnCount + { + get { return this.columnCount; } + } + + public int Count + { + get { return this.rowCount * this.columnCount; } + } + + public double[] GetData() + { + return this.data; + } + + public double this[int row, int column] + { + get { return this.data[row + column * this.RowCount]; } + set { this.data[row + column * this.RowCount] = value; } + } + #endregion + + #region Cloning + public DoubleDenseMatrix Clone() + { + return new DoubleDenseMatrix( + this.RowCount, + this.ColumnCount, + (double[])this.data.Clone() + ); + } + + object ICloneable.Clone() + { + return this.Clone(); + } + #endregion + + #region Basic operations + public DoubleDenseMatrix Add(DoubleDenseMatrix matrix) + { + VerifySize(matrix); + + for (int i = 0; i < data.Length; ++i) + this.data[i] += matrix.data[i]; + + return this; + } + + public static DoubleDenseMatrix Add(DoubleDenseMatrix left, DoubleDenseMatrix right) + { + // + if (left == (DoubleDenseMatrix)null) + throw new ArgumentNullException("left"); + // + DoubleDenseMatrix m = Create(left); + return m.Add(right); + } + + public static DoubleDenseMatrix operator +(DoubleDenseMatrix left, DoubleDenseMatrix right) + { + return Add(left, right); + } + + public DoubleDenseMatrix Sub(DoubleDenseMatrix matrix) + { + VerifySize(matrix); + + for (int i = 0; i < data.Length; ++i) + this.data[i] -= matrix.data[i]; + + return this; + } + + public static DoubleDenseMatrix Sub(DoubleDenseMatrix left, DoubleDenseMatrix right) + { + DoubleDenseMatrix m = Create(left); + return m.Sub(right); + } + + public static DoubleDenseMatrix operator - (DoubleDenseMatrix left, DoubleDenseMatrix right) + { + return Sub(left, right); + } + + public DoubleDenseMatrix Mul(double factor) + { + for (int i = 0; i < data.Length; ++i) + this.data[i] *= factor; + return this; + } + + public static DoubleDenseMatrix Mul(DoubleDenseMatrix left, double factor) + { + DoubleDenseMatrix m = Create(left); + return m.Mul(factor); + } + + public static DoubleDenseMatrix operator * (DoubleDenseMatrix left, double factor) + { + return Mul(left, factor); + } + + public static DoubleDenseMatrix Mul(double factor, DoubleDenseMatrix right) + { + DoubleDenseMatrix m = Create(right); + return m.Mul(factor); + } + + public static DoubleDenseMatrix operator *(double factor, DoubleDenseMatrix right) + { + return Mul(factor, right); + } + + public static DoubleDenseMatrix Mul(DoubleDenseMatrix left, DoubleDenseMatrix right) + { + // + if (left == (DoubleDenseMatrix)null) + throw new ArgumentNullException("left"); + if (right == (DoubleDenseMatrix)null) + throw new ArgumentNullException("right"); + // + if (left.ColumnCount != right.RowCount) + throw new MatrixSizeMistmatchException(); + + DoubleDenseMatrix m = new DoubleDenseMatrix(left.RowCount, right.ColumnCount); + for (int i = 0; i < left.RowCount; ++i) + { + for (int j = 0; j < left.ColumnCount; ++j) + { + for (int k = 0; k < right.ColumnCount; ++k) + { + m[i,k] += left[i,j] * right[j,k]; + } + } + } + + return m; + } + + public static DoubleDenseMatrix operator *(DoubleDenseMatrix left, DoubleDenseMatrix right) + { + return Mul(left, right); + } + + public DoubleDenseMatrix Div(double factor) + { + for (int i = 0; i < data.Length; ++i) + this.data[i] = checked(this.data[i]/factor); + + return this; + } + #endregion + + #region norms + public double GetNorm1() + { + double norm = 0; + for (int i = 0; i < this.RowCount; ++i) + { + double sum = 0; + for (int j = 0; j < this.ColumnCount; ++j) + { + sum += this[i, j]; + } + + norm = Math.Max(sum, norm); + } + + return norm; + } + + public double GetNormInfinity() + { + double norm = 0; + for (int j = 0; j < this.ColumnCount; ++j) + { + double sum = 0; + for (int i = 0; i < this.RowCount; ++i) + { + sum += this[i, j]; + } + norm = Math.Max(sum, norm); + } + + return norm; + } + + public double GetNorm2() + { + double norm = 0; + for (int i = 0; i < this.Count; ++i) + { + norm += this.data[i] * this.data[i]; + } + return Math.Sqrt(norm); + } + #endregion + + #region special methods + public DoubleDenseMatrix Trace() + { + if (this.RowCount != this.ColumnCount) + throw new MatrixSizeMistmatchException(); + DoubleDenseMatrix m = new DoubleDenseMatrix(this.RowCount,1); + for (int i = 0; i < this.RowCount; ++i) + m.data[i] = this[i, i]; + + return m; + } + + public DoubleDenseMatrix Transpose() + { + DoubleDenseMatrix m = new DoubleDenseMatrix(this.ColumnCount, this.RowCount); + for (int i = 0; i < this.RowCount; ++i) + for (int j = 0; j < this.ColumnCount; ++j) + m[j, i] = this[i, j]; + return m; + } + #endregion + + #region Factories + public static DoubleDenseMatrix Identity(int count) + { + DoubleDenseMatrix m = new DoubleDenseMatrix(count, count); + for (int i = 0; i < count; ++i) + m[i, i] = 1; + return m; + } + #endregion + + #region similarity + public static DoubleDenseMatrix Similarity( + DoubleDenseMatrix A, + DoubleDenseMatrix B, + double tolerance + ) + { + // + if (A == (DoubleDenseMatrix)null) + throw new ArgumentNullException("A"); + if (B == (DoubleDenseMatrix)null) + throw new ArgumentNullException("B"); + // + DoubleDenseMatrix AT = A.Transpose(); + DoubleDenseMatrix BT = B.Transpose(); + DoubleDenseMatrix Zk = DoubleDenseMatrix.Create(B.RowCount, A.RowCount, 1.0/(A.RowCount*B.RowCount)); + DoubleDenseMatrix Zk1 = null; + DoubleDenseMatrix ZkOld = null; + + int iteration = 0; + do + { + Zk1 = B * Zk * AT + BT * Zk * A; + Zk1.Div(Zk1.GetNorm2()); + + ZkOld = Zk; + Zk = B * Zk1 * AT + BT * Zk1 * A; + Zk.Div(Zk.GetNorm2()); + + Console.WriteLine(iteration); + Zk.WriteMatrix(Console.Out); + Console.WriteLine((Zk - ZkOld).GetNorm2()); + + if (iteration++ > 100) + throw new InvalidOperationException(); + + } while ((Zk - ZkOld).GetNorm2() > tolerance); + + return Zk; + } + #endregion + + #region ToString + public override string ToString() + { + return String.Format("({0}x{1})", this.RowCount, this.ColumnCount); + } + + public void WriteMatrix(TextWriter writer) + { + for (int i = 0; i < this.RowCount; ++i) + { + for (int j = 0; j < this.ColumnCount; ++j) + { + if (j != 0) + writer.Write(" "); + writer.Write(this[i, j]); + } + writer.WriteLine(); + } + } + + public void WriteMatrix(TextWriter writer, string formatString) + { + for (int i = 0; i < this.RowCount; ++i) + { + for (int j = 0; j < this.ColumnCount; ++j) + { + if (j != 0) + writer.Write(" "); + writer.Write(formatString, this[i, j]); + } + writer.WriteLine(); + } + } + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs.meta new file mode 100644 index 0000000..3ef011a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Matrix/DoubleDenseMatrix.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9ec4b4364176040c884944d8f0dd7430 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs new file mode 100755 index 0000000..a62b55d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.MaximumFlow; + +namespace QuickGraph.Algorithms +{ + public sealed class MaximumBipartiteMatchingAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private IVertexFactory vertexFactory; + private IEdgeFactory edgeFactory; + private IList matchedEdges = new List(); + + public MaximumBipartiteMatchingAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph + ) + : this(visitedGraph, + FactoryCompiler.GetVertexFactory(), + FactoryCompiler.GetEdgeFactory() + ) + { } + + public MaximumBipartiteMatchingAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory + ) + :base(visitedGraph) + { + if (vertexFactory == null) + throw new ArgumentNullException("vertexFactory"); + if (edgeFactory == null) + throw new ArgumentNullException("edgeFactory"); + + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + } + + public IVertexFactory VertexFactory + { + get { return this.vertexFactory; } + } + + public IEdgeFactory EdgeFactory + { + get { return this.edgeFactory; } + } + + public ICollection MatchedEdges + { + get { return this.matchedEdges; } + } + + protected override void InternalCompute() + { + var cancelManager = this.Services.CancelManager; + this.matchedEdges.Clear(); + AllVerticesGraphAugmentorAlgorithm augmentor=null; + ReversedEdgeAugmentorAlgorithm reverser=null; + try + { + if (cancelManager.IsCancelling) + return; + + //augmenting graph + augmentor = new AllVerticesGraphAugmentorAlgorithm( + this, + this.VisitedGraph, + this.VertexFactory, + this.EdgeFactory); + augmentor.Compute(); + if (cancelManager.IsCancelling) + return; + + + // adding reverse edges + reverser = new ReversedEdgeAugmentorAlgorithm( + this, + this.VisitedGraph, + this.EdgeFactory + ); + reverser.AddReversedEdges(); + if (cancelManager.IsCancelling) + return; + + + // compute maxflow + var flow = new EdmondsKarpMaximumFlowAlgorithm( + this, + this.VisitedGraph, + AlgoUtility.ConstantCapacities(this.VisitedGraph, 1), + reverser.ReversedEdges + ); + flow.Compute(augmentor.SuperSource, augmentor.SuperSink); + if (cancelManager.IsCancelling) + return; + + + foreach (var edge in this.VisitedGraph.Edges) + { + if (cancelManager.IsCancelling) return; + + if (flow.ResidualCapacities[edge] == 0) + this.matchedEdges.Add(edge); + } + } + finally + { + if (reverser!=null && reverser.Augmented) + { + reverser.RemoveReversedEdges(); + reverser=null; + } + if (augmentor != null && augmentor.Augmented) + { + augmentor.Rollback(); + augmentor = null; + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs.meta new file mode 100644 index 0000000..e52c19a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumBipartiteMatchingAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 86c82d8c5c4fe46808fd0794244e7aa4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow.meta new file mode 100644 index 0000000..9844848 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 49413ed86f227492f89c249fde7a64b1 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs new file mode 100755 index 0000000..a2653c7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs @@ -0,0 +1,48 @@ +using System; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + public sealed class AllVerticesGraphAugmentorAlgorithm : + GraphAugmentorAlgorithmBase> + where TEdge : IEdge + { + public AllVerticesGraphAugmentorAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph + ) + : this(visitedGraph, + FactoryCompiler.GetVertexFactory(), + FactoryCompiler.GetEdgeFactory() + ) + { } + + public AllVerticesGraphAugmentorAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory + ) + : this(null, visitedGraph, vertexFactory, edgeFactory) + { } + + public AllVerticesGraphAugmentorAlgorithm( + IAlgorithmComponent host, + IMutableVertexAndEdgeListGraph visitedGraph, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory + ) + :base(host, visitedGraph,vertexFactory,edgeFactory) + {} + + protected override void AugmentGraph() + { + var cancelManager = this.Services.CancelManager; + foreach (var v in this.VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) break; + + this.AddAugmentedEdge(this.SuperSource, v); + this.AddAugmentedEdge(v, this.SuperSink); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs.meta new file mode 100644 index 0000000..c7df061 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/AllVerticesGraphAugmentorAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 724e85497d33448aeac7dd85b183c9e6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs new file mode 100755 index 0000000..87bf0f8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Collections; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Predicates; +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + /// + /// Edmond and Karp maximum flow algorithm + /// for directed graph with positive capacities and + /// flows. + /// + /// + /// + [Serializable] + public sealed class EdmondsKarpMaximumFlowAlgorithm + : MaximumFlowAlgorithm + where TEdge : IEdge + { + public EdmondsKarpMaximumFlowAlgorithm( + IVertexListGraph g, + IDictionary capacities, + IDictionary reversedEdges + ) + : this(null, g, capacities, reversedEdges) + { } + + public EdmondsKarpMaximumFlowAlgorithm( + IAlgorithmComponent host, + IVertexListGraph g, + IDictionary capacities, + IDictionary reversedEdges + ) + : base(host, g,capacities,reversedEdges) + {} + + private IVertexListGraph ResidualGraph + { + get + { + return new FilteredVertexListGraph< + TVertex, + TEdge, + IVertexListGraph + >( + VisitedGraph, + new AnyVertexPredicate().Test, + new ResidualEdgePredicate(ResidualCapacities).Test + ); + } + } + + private void Augment( + TVertex src, + TVertex sink + ) + { + TEdge e; + TVertex u; + + // find minimum residual capacity along the augmenting path + double delta = double.MaxValue; + u = sink; + do + { + e = Predecessors[u]; + delta = Math.Min(delta, ResidualCapacities[e]); + u = e.Source; + } while (!u.Equals(src)); + + // push delta units of flow along the augmenting path + u = sink; + do + { + e = Predecessors[u]; + ResidualCapacities[e] -= delta; + ResidualCapacities[ ReversedEdges[e] ] += delta; + u = e.Source; + } while (!u.Equals(src)); + } + + /// + /// Computes the maximum flow between and + /// + /// + /// + /// + /// + protected override void InternalCompute() + { + if (this.Source==null) + throw new InvalidOperationException("Source is not specified"); + if (this.Sink==null) + throw new InvalidOperationException("Sink is not specified"); + + foreach(TVertex u in VisitedGraph.Vertices) + { + foreach(TEdge e in VisitedGraph.OutEdges(u)) + { + ResidualCapacities[e] = Capacities[e]; + } + } + + VertexColors[Sink] = GraphColor.Gray; + while (VertexColors[Sink] != GraphColor.White) + { + VertexPredecessorRecorderObserver vis = new VertexPredecessorRecorderObserver( + Predecessors + ); + var Q = new QuickGraph.Collections.Queue(); + var bfs = new BreadthFirstSearchAlgorithm( + ResidualGraph, + Q, + VertexColors + ); + vis.Attach(bfs); + bfs.Compute(this.Source); + vis.Detach(bfs); + + if (VertexColors[this.Sink] != GraphColor.White) + Augment(this.Source, this.Sink); + } // while + + this.MaxFlow = 0; + foreach(TEdge e in VisitedGraph.OutEdges(Source)) + this.MaxFlow += (Capacities[e] - ResidualCapacities[e]); + } + } + +} \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs.meta new file mode 100644 index 0000000..dfc962d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/EdmondsKarpMaximumFlowAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2acd97bb4bf4345928a250d45b09b28f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs new file mode 100755 index 0000000..74fa704 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs @@ -0,0 +1,18 @@ +#region Using directives + +using System; +using System.Collections.Generic; +using System.Text; + +#endregion + +namespace QuickGraph.Algorithms.MaximumFlow +{ + public class FeasibleFlowAlgorithm + { + public FeasibleFlowAlgorithm() + { + + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs.meta new file mode 100644 index 0000000..c419278 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/FeasibleFlowAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2aeaf96b20a074adaa6b284d94fbbcd2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs new file mode 100755 index 0000000..efdd740 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + public abstract class GraphAugmentorAlgorithmBase : + AlgorithmBase + where TEdge : IEdge + where TGraph : IMutableVertexAndEdgeListGraph + { + private bool augmented = false; + private List augmentedEdges = new List(); + private IVertexFactory vertexFactory; + private IEdgeFactory edgeFactory; + + private TVertex superSource = default(TVertex); + private TVertex superSink = default(TVertex); + + protected GraphAugmentorAlgorithmBase( + IAlgorithmComponent host, + TGraph visitedGraph, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory + ) + :base(host, visitedGraph) + { + if (vertexFactory == null) + throw new ArgumentNullException("vertexFactory"); + if (edgeFactory == null) + throw new ArgumentNullException("edgeFactory"); + + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + } + + public IVertexFactory VertexFactory + { + get { return this.vertexFactory; } + } + + public IEdgeFactory EdgeFactory + { + get { return this.edgeFactory; } + } + + public TVertex SuperSource + { + get { return this.superSource; } + } + + public TVertex SuperSink + { + get { return this.superSink; } + } + + public bool Augmented + { + get { return this.augmented; } + } + + public ICollection AugmentedEdges + { + get { return this.augmentedEdges; } + } + + public event VertexEventHandler SuperSourceAdded; + private void OnSuperSourceAdded(TVertex v) + { + if (this.SuperSourceAdded != null) + this.SuperSourceAdded(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler SuperSinkAdded; + private void OnSuperSinkAdded(TVertex v) + { + if (this.SuperSinkAdded != null) + this.SuperSinkAdded(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler EdgeAdded; + private void OnEdgeAdded(TEdge e) + { + if (this.EdgeAdded != null) + this.EdgeAdded(this, new EdgeEventArgs(e)); + } + + + protected override void InternalCompute() + { + if (this.Augmented) + throw new InvalidOperationException("Graph already augmented"); + + this.superSource = this.VertexFactory.CreateVertex(); + this.VisitedGraph.AddVertex(this.superSource); + this.OnSuperSourceAdded(this.SuperSource); + + this.superSink = this.VertexFactory.CreateVertex(); + this.VisitedGraph.AddVertex(this.superSink); + this.OnSuperSinkAdded(this.SuperSink); + + this.AugmentGraph(); + this.augmented = true; + } + + public virtual void Rollback() + { + if (!this.Augmented) + return; + + this.VisitedGraph.RemoveVertex(this.SuperSource); + this.VisitedGraph.RemoveVertex(this.SuperSink); + this.superSource = default(TVertex); + this.superSink = default(TVertex); + this.augmentedEdges.Clear(); + this.augmented = false; + } + + protected abstract void AugmentGraph(); + + protected void AddAugmentedEdge(TVertex source, TVertex target) + { + TEdge edge = this.EdgeFactory.CreateEdge(source, target); + this.augmentedEdges.Add(edge); + this.VisitedGraph.AddEdge(edge); + this.OnEdgeAdded(edge); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs.meta new file mode 100644 index 0000000..3d71dbf --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphAugmentorAlgorithmBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: df0c499a327934f0c8238188fde1579c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs new file mode 100755 index 0000000..ab93845 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs @@ -0,0 +1,380 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + [Serializable] + public class GraphBalancerAlgorithm + where TEdge : IEdge + { + private IMutableBidirectionalGraph visitedGraph; + private IVertexFactory vertexFactory; + private IEdgeFactory edgeFactory; + + private TVertex source; + private TVertex sink; + + private TVertex balancingSource; + private TEdge balancingSourceEdge; + + private TVertex balancingSink; + private TEdge balancingSinkEdge; + + private IDictionary capacities = new Dictionary(); + private Dictionary preFlow = new Dictionary(); + private List surplusVertices = new List(); + private List surplusEdges = new List(); + private List deficientVertices = new List(); + private List deficientEdges = new List(); + private bool balanced = false; + + public GraphBalancerAlgorithm( + IMutableBidirectionalGraph visitedGraph, + TVertex source, + TVertex sink + ) + : this(visitedGraph, + source, + sink, + FactoryCompiler.GetVertexFactory(), + FactoryCompiler.GetEdgeFactory() + ) + { } + + public GraphBalancerAlgorithm( + IMutableBidirectionalGraph visitedGraph, + TVertex source, + TVertex sink, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory + ) + { + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + if (vertexFactory==null) + throw new ArgumentNullException("vertexFactory"); + if (edgeFactory==null) + throw new ArgumentNullException("edgeFactory"); + if (source == null) + throw new ArgumentNullException("source"); + if (!visitedGraph.ContainsVertex(source)) + throw new ArgumentException("source is not part of the graph"); + if (sink == null) + throw new ArgumentNullException("sink"); + if (!visitedGraph.ContainsVertex(sink)) + throw new ArgumentException("sink is not part of the graph"); + + this.visitedGraph = visitedGraph; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + this.source = source; + this.sink = sink; + + // setting capacities = u(e) = +infty + foreach (var edge in this.VisitedGraph.Edges) + this.capacities.Add(edge, double.MaxValue); + + // setting preflow = l(e) = 1 + foreach (var edge in this.VisitedGraph.Edges) + this.preFlow.Add(edge, 1); + } + + public GraphBalancerAlgorithm( + IMutableBidirectionalGraph visitedGraph, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory, + TVertex source, + TVertex sink, + IDictionary capacities) + { + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + if (vertexFactory==null) + throw new ArgumentNullException("vertexFactory"); + if (edgeFactory==null) + throw new ArgumentNullException("edgeFactory"); + if (source == null) + throw new ArgumentNullException("source"); + if (!visitedGraph.ContainsVertex(source)) + throw new ArgumentException("source is not part of the graph"); + if (sink == null) + throw new ArgumentNullException("sink"); + if (!visitedGraph.ContainsVertex(sink)) + throw new ArgumentException("sink is not part of the graph"); + if (capacities == null) + throw new ArgumentNullException("capacities"); + + this.visitedGraph = visitedGraph; + this.source = source; + this.sink = sink; + this.capacities = capacities; + + // setting preflow = l(e) = 1 + foreach (var edge in this.VisitedGraph.Edges) + this.preFlow.Add(edge, 1); + } + + public IMutableBidirectionalGraph VisitedGraph + { + get + { + return this.visitedGraph; + } + } + + public IVertexFactory VertexFactory + { + get { return this.vertexFactory;} + } + + public IEdgeFactory EdgeFactory + { + get { return this.edgeFactory;} + } + + public bool Balanced + { + get + { + return this.balanced; + } + } + + public TVertex Source + { + get + { + return this.source; + } + } + public TVertex Sink + { + get + { + return this.sink; + } + } + public TVertex BalancingSource + { + get + { + return this.balancingSource; + } + } + public TEdge BalancingSourceEdge + { + get + { + return this.balancingSourceEdge; + } + } + public TVertex BalancingSink + { + get + { + return this.balancingSink; + } + } + public TEdge BalancingSinkEdge + { + get + { + return this.balancingSinkEdge; + } + } + public ICollection SurplusVertices + { + get + { + return this.surplusVertices; + } + } + public ICollection SurplusEdges + { + get + { + return this.surplusEdges; + } + } + public ICollection DeficientVertices + { + get + { + return this.deficientVertices; + } + } + public ICollection DeficientEdges + { + get + { + return this.deficientEdges; + } + } + public IDictionary Capacities + { + get + { + return this.capacities; + } + } + + public event VertexEventHandler BalancingSourceAdded; + private void OnBalancingSourceAdded() + { + if (this.BalancingSourceAdded != null) + this.BalancingSourceAdded(this, new VertexEventArgs(source)); + } + public event VertexEventHandler BalancingSinkAdded; + private void OnBalancingSinkAdded() + { + if (this.BalancingSinkAdded != null) + this.BalancingSinkAdded(this, new VertexEventArgs(this.sink)); + } + public event EdgeEventHandler EdgeAdded; + private void OnEdgeAdded(TEdge edge) + { + if (this.EdgeAdded != null) + this.EdgeAdded(this, new EdgeEventArgs(edge)); + } + public event VertexEventHandler SurplusVertexAdded; + private void OnSurplusVertexAdded(TVertex vertex) + { + if (this.SurplusVertexAdded != null) + this.SurplusVertexAdded(this, new VertexEventArgs(vertex)); + } + public event VertexEventHandler DeficientVertexAdded; + private void OnDeficientVertexAdded(TVertex vertex) + { + if (this.DeficientVertexAdded != null) + this.DeficientVertexAdded(this, new VertexEventArgs(vertex)); + } + + public int GetBalancingIndex(TVertex v) + { + int bi = 0; + foreach (var edge in this.VisitedGraph.OutEdges(v)) + { + int pf = this.preFlow[edge]; + bi += pf; + } + foreach (var edge in this.VisitedGraph.InEdges(v)) + { + int pf = this.preFlow[edge]; + bi -= pf; + } + return bi; + } + + public void Balance() + { + if (this.Balanced) + throw new InvalidOperationException("Graph already balanced"); + + // step 0 + // create new source, new sink + this.balancingSource = this.VertexFactory.CreateVertex(); + this.visitedGraph.AddVertex(this.balancingSource); + this.OnBalancingSourceAdded(); + + this.balancingSink = this.VertexFactory.CreateVertex(); + this.visitedGraph.AddVertex(this.balancingSink); + this.OnBalancingSinkAdded(); + + // step 1 + this.balancingSourceEdge = this.EdgeFactory.CreateEdge(this.BalancingSource, this.Source); + this.VisitedGraph.AddEdge(this.BalancingSourceEdge); + this.capacities.Add(this.balancingSourceEdge, double.MaxValue); + this.preFlow.Add(this.balancingSourceEdge, 0); + OnEdgeAdded(balancingSourceEdge); + + this.balancingSinkEdge = this.EdgeFactory.CreateEdge(this.Sink, this.BalancingSink); + this.VisitedGraph.AddEdge(this.balancingSinkEdge); + this.capacities.Add(this.balancingSinkEdge, double.MaxValue); + this.preFlow.Add(this.balancingSinkEdge, 0); + OnEdgeAdded(balancingSinkEdge); + + // step 2 + // for each surplus vertex v, add (source -> v) + foreach (var v in this.VisitedGraph.Vertices) + { + if (v.Equals(this.balancingSource)) + continue; + if (v.Equals(this.balancingSink)) + continue; + if (v.Equals(this.source)) + continue; + if (v.Equals(this.sink)) + continue; + + int balacingIndex = this.GetBalancingIndex(v); + if (balacingIndex == 0) + continue; + + if (balacingIndex < 0) + { + // surplus vertex + TEdge edge = this.EdgeFactory.CreateEdge(this.BalancingSource, v); + this.VisitedGraph.AddEdge(edge); + this.surplusEdges.Add(edge); + this.surplusVertices.Add(v); + this.preFlow.Add(edge, 0); + this.capacities.Add(edge, -balacingIndex); + OnSurplusVertexAdded(v); + OnEdgeAdded(edge); + } + else + { + // deficient vertex + TEdge edge = this.EdgeFactory.CreateEdge(v, this.BalancingSink); + this.deficientEdges.Add(edge); + this.deficientVertices.Add(v); + this.preFlow.Add(edge, 0); + this.capacities.Add(edge, balacingIndex); + OnDeficientVertexAdded(v); + OnEdgeAdded(edge); + } + } + + this.balanced = true; + } + + public void UnBalance() + { + if (!this.Balanced) + throw new InvalidOperationException("Graph is not balanced"); + foreach (var edge in this.surplusEdges) + { + this.VisitedGraph.RemoveEdge(edge); + this.capacities.Remove(edge); + this.preFlow.Remove(edge); + } + foreach (var edge in this.deficientEdges) + { + this.VisitedGraph.RemoveEdge(edge); + this.capacities.Remove(edge); + this.preFlow.Remove(edge); + } + + this.capacities.Remove(this.BalancingSinkEdge); + this.capacities.Remove(this.BalancingSourceEdge); + this.preFlow.Remove(this.BalancingSinkEdge); + this.preFlow.Remove(this.BalancingSourceEdge); + this.VisitedGraph.RemoveEdge(this.BalancingSourceEdge); + this.VisitedGraph.RemoveEdge(this.BalancingSinkEdge); + this.VisitedGraph.RemoveVertex(this.BalancingSource); + this.VisitedGraph.RemoveVertex(this.BalancingSink); + + this.balancingSource = default(TVertex); + this.balancingSink = default(TVertex); + this.balancingSourceEdge = default(TEdge); + this.balancingSinkEdge = default(TEdge); + + this.surplusEdges.Clear(); + this.deficientEdges.Clear(); + this.surplusVertices.Clear(); + this.deficientVertices.Clear(); + + this.balanced = false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs.meta new file mode 100644 index 0000000..d29e6d5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/GraphBalancingAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29f1adf57a2884d72b71bea3737887a8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs new file mode 100755 index 0000000..ae3123c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + /// + /// Abstract base class for maximum flow algorithms. + /// + [Serializable] + public abstract class MaximumFlowAlgorithm : + AlgorithmBase>, + IVertexColorizerAlgorithm + where TEdge : IEdge + { + private IDictionary predecessors; + private IDictionary capacities; + private IDictionary residualCapacities; + private IDictionary reversedEdges; + private IDictionary vertexColors; + private TVertex source; + private TVertex sink; + private double maxFlow = 0; + + protected MaximumFlowAlgorithm( + IAlgorithmComponent host, + IVertexListGraph visitedGraph, + IDictionary capacities, + IDictionary reversedEdges + ) + :base(host, visitedGraph) + { + if (capacities == null) + throw new ArgumentNullException("capacities"); + if (reversedEdges == null) + throw new ArgumentNullException("reversedEdges"); + + this.capacities = capacities; + this.reversedEdges = reversedEdges; + + this.predecessors = new Dictionary(); + this.residualCapacities = new Dictionary(); + this.vertexColors = new Dictionary(); + } + + public IDictionary Predecessors + { + get + { + return predecessors; + } + } + + public IDictionary Capacities + { + get + { + return capacities; + } + } + + public IDictionary ResidualCapacities + { + get + { + return residualCapacities; + } + } + + public IDictionary ReversedEdges + { + get + { + return reversedEdges; + } + } + + public IDictionary VertexColors + { + get + { + return vertexColors; + } + } + + public TVertex Source + { + get { return this.source; } + set + { + if (value == null) + throw new ArgumentNullException("source"); + this.source = value; + } + } + + public TVertex Sink + { + get { return this.sink; } + set + { + if (value == null) + throw new ArgumentNullException("sink"); + this.sink = value; + } + } + + public double MaxFlow + { + get { return this.maxFlow; } + set { this.maxFlow = value; } + } + + public double Compute(TVertex source, TVertex sink) + { + this.Source = source; + this.Sink = sink; + this.Compute(); + return this.MaxFlow; + } + } + +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs.meta new file mode 100644 index 0000000..df64c67 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MaximumFlowAlgorithmBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 398973ac6692c4b6a9dec27a389dab1f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs new file mode 100755 index 0000000..0e87594 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + public class MinimumCostMaximumFlowAlgorithm + { + public MinimumCostMaximumFlowAlgorithm() + { + + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs.meta new file mode 100644 index 0000000..cbcad03 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MinimumCostMaximumFlowAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 704f48c15c0c444c3951c2bf0e2ccbae +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs new file mode 100755 index 0000000..77f47bc --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs @@ -0,0 +1,49 @@ +using System; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + public sealed class MultiSourceSinkGraphAugmentorAlgorithm : + GraphAugmentorAlgorithmBase> + where TEdge : IEdge + { + public MultiSourceSinkGraphAugmentorAlgorithm(IMutableBidirectionalGraph visitedGraph) + : this(visitedGraph, + FactoryCompiler.GetVertexFactory(), + FactoryCompiler.GetEdgeFactory() + ) + { } + + public MultiSourceSinkGraphAugmentorAlgorithm( + IMutableBidirectionalGraph visitedGraph, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory) + :this(null, visitedGraph, vertexFactory, edgeFactory) + {} + + public MultiSourceSinkGraphAugmentorAlgorithm( + IAlgorithmComponent host, + IMutableBidirectionalGraph visitedGraph, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory) + :base(host, visitedGraph,vertexFactory,edgeFactory) + {} + + protected override void AugmentGraph() + { + var cancelManager = this.Services.CancelManager; + foreach (var v in this.VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) break; + + // is source + if (this.VisitedGraph.IsInEdgesEmpty(v)) + this.AddAugmentedEdge(this.SuperSource, v); + + // is sink + if (this.VisitedGraph.IsOutEdgesEmpty(v)) + this.AddAugmentedEdge(v,this.SuperSink); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs.meta new file mode 100644 index 0000000..05e33ad --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/MultiSourceSinkGraphAugmentorAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 148cdf4af1285496699a990ae9e7fb9e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs new file mode 100755 index 0000000..fbe91cd --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.MaximumFlow +{ + [Serializable] + public sealed class ReversedEdgeAugmentorAlgorithm + where TEdge : IEdge + { + private IMutableVertexAndEdgeListGraph visitedGraph; + private IEdgeFactory edgeFactory; + private IList augmentedEgdes = new List(); + private IDictionary reversedEdges = new Dictionary(); + private bool augmented = false; + + public ReversedEdgeAugmentorAlgorithm( + IMutableVertexAndEdgeListGraph visitedGraph, + IEdgeFactory edgeFactory) + : this(null, visitedGraph, edgeFactory) + { } + + public ReversedEdgeAugmentorAlgorithm( + IAlgorithmComponent host, + IMutableVertexAndEdgeListGraph visitedGraph, + IEdgeFactory edgeFactory) + { + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + if (edgeFactory == null) + throw new ArgumentNullException("edgeFactory"); + this.visitedGraph = visitedGraph; + this.edgeFactory = edgeFactory; + } + + public IMutableVertexAndEdgeListGraph VisitedGraph + { + get + { + return this.visitedGraph; + } + } + + public IEdgeFactory EdgeFactory + { + get { return this.edgeFactory; } + } + + public ICollection AugmentedEdges + { + get + { + return this.augmentedEgdes; + } + } + + public IDictionary ReversedEdges + { + get + { + return this.reversedEdges; + } + } + + public bool Augmented + { + get + { + return this.augmented; + } + } + + public event EdgeEventHandler ReversedEdgeAdded; + private void OnReservedEdgeAdded(EdgeEventArgs e) + { + if (this.ReversedEdgeAdded != null) + this.ReversedEdgeAdded(this, e); + } + + public void AddReversedEdges() + { + if (this.Augmented) + throw new InvalidOperationException("Graph already augmented"); + // step 1, find edges that need reversing + IList notReversedEdges = new List(); + foreach (var edge in this.VisitedGraph.Edges) + { + // if reversed already found, continue + if (this.reversedEdges.ContainsKey(edge)) + continue; + + TEdge reversedEdge = this.FindReversedEdge(edge); + if (reversedEdge != null) + { + // setup edge + this.reversedEdges[edge] = reversedEdge; + // setup reversed if needed + if (!this.reversedEdges.ContainsKey(reversedEdge)) + this.reversedEdges[reversedEdge] = edge; + continue; + } + + // this edge has no reverse + notReversedEdges.Add(edge); + } + + // step 2, go over each not reversed edge, add reverse + foreach (var edge in notReversedEdges) + { + if (this.reversedEdges.ContainsKey(edge)) + continue; + + // already been added + TEdge reversedEdge = this.FindReversedEdge(edge); + if (reversedEdge != null) + { + this.reversedEdges[edge] = reversedEdge; + continue; + } + + // need to create one + reversedEdge = this.edgeFactory.CreateEdge(edge.Target, edge.Source); + if (!this.VisitedGraph.AddEdge(reversedEdge)) + throw new InvalidOperationException("We should not be here"); + this.augmentedEgdes.Add(reversedEdge); + this.reversedEdges[edge] = reversedEdge; + this.reversedEdges[reversedEdge] = edge; + this.OnReservedEdgeAdded(new EdgeEventArgs(reversedEdge)); + } + + this.augmented = true; + } + + public void RemoveReversedEdges() + { + if (!this.Augmented) + throw new InvalidOperationException("Graph is not yet augmented"); + + foreach (var edge in this.augmentedEgdes) + this.VisitedGraph.RemoveEdge(edge); + + this.augmentedEgdes.Clear(); + this.reversedEdges.Clear(); + + this.augmented = false; + } + + private TEdge FindReversedEdge(TEdge edge) + { + foreach (var redge in this.VisitedGraph.OutEdges(edge.Target)) + if (redge.Target.Equals(edge.Source)) + return redge; + return default(TEdge); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs.meta new file mode 100644 index 0000000..4074e06 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MaximumFlow/ReverseEdgeAugmentorAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 338ce79453954445ba3d20705a17150e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree.meta new file mode 100644 index 0000000..7b57995 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: d6cb40f85bb6944e3bee404516a0d890 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs new file mode 100755 index 0000000..94dff1e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Collections; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.MinimumSpanningTree +{ + /// + /// Prim's classic minimum spanning tree algorithm for undirected graphs + /// + /// + /// + /// + [Serializable] + public sealed class PrimMinimumSpanningTreeAlgorithm : + RootedAlgorithmBase>, + ITreeBuilderAlgorithm, + IVertexPredecessorRecorderAlgorithm + where TEdge : IEdge + { + private IDictionary edgeWeights; + private Dictionary minimumWeights; + private PriorityQueue queue; + + public PrimMinimumSpanningTreeAlgorithm( + IUndirectedGraph visitedGraph, + IDictionary edgeWeights + ) + : this(null, visitedGraph, edgeWeights) + {} + + public PrimMinimumSpanningTreeAlgorithm( + IAlgorithmComponent host, + IUndirectedGraph visitedGraph, + IDictionary edgeWeights + ) + :base(host, visitedGraph) + { + if (edgeWeights == null) + throw new ArgumentNullException("edgeWeights"); + this.edgeWeights = edgeWeights; + } + + public IDictionary EdgeWeights + { + get { return this.edgeWeights; } + } + + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + VertexEventHandler eh = this.StartVertex; + if (eh != null) + eh(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + EdgeEventHandler eh = this.TreeEdge; + if (eh != null) + eh(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler FinishVertex; + + private void OnFinishVertex(TVertex v) + { + VertexEventHandler eh = this.FinishVertex; + if (eh != null) + eh(this, new VertexEventArgs(v)); + } + + protected override void InternalCompute() + { + if (this.VisitedGraph.VertexCount == 0) + return; + var cancelManager = this.Services.CancelManager; + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + rootVertex = TraversalHelper.GetFirstVertex(this.VisitedGraph); + + this.Initialize(); + + try + { + this.minimumWeights[rootVertex] = 0; + this.queue.Update(rootVertex); + this.OnStartVertex(rootVertex); + + while (queue.Count != 0) + { + if (cancelManager.IsCancelling) + return; + TVertex u = queue.Dequeue(); + foreach (var edge in this.VisitedGraph.AdjacentEdges(u)) + { + if (cancelManager.IsCancelling) + return; + double edgeWeight = this.EdgeWeights[edge]; + if ( + queue.Contains(edge.Target) && + edgeWeight < this.minimumWeights[edge.Target] + ) + { + this.minimumWeights[edge.Target] = edgeWeight; + this.queue.Update(edge.Target); + this.OnTreeEdge(edge); + } + } + this.OnFinishVertex(u); + } + } + finally + { + this.CleanUp(); + } + } + + private void Initialize() + { + this.minimumWeights = new Dictionary(this.VisitedGraph.VertexCount); + this.queue = new PriorityQueue(this.minimumWeights); + foreach (var u in this.VisitedGraph.Vertices) + { + this.minimumWeights.Add(u, double.MaxValue); + this.queue.Enqueue(u); + } + } + + private void CleanUp() + { + this.minimumWeights = null; + this.queue = null; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs.meta new file mode 100644 index 0000000..007d803 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/MinimumSpanningTree/PrimMinimumSpanningTreeAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 80bf3b94a6bc649db8af099ef16ede8b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers.meta new file mode 100644 index 0000000..0285b28 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 75963fb3afec149998ddb844fcb688ec +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs new file mode 100755 index 0000000..461d840 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Observers +{ + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class EdgePredecessorRecorderObserver : + IObserver> + where TEdge : IEdge + { + private IDictionary edgePredecessors; + private IList endPathEdges; + + public EdgePredecessorRecorderObserver() + :this(new Dictionary(), new List()) + {} + + public EdgePredecessorRecorderObserver( + IDictionary edgePredecessors, + IList endPathEdges + ) + { + if (edgePredecessors == null) + throw new ArgumentNullException("edgePredecessors"); + if (endPathEdges == null) + throw new ArgumentNullException("endPathEdges"); + + this.edgePredecessors = edgePredecessors; + this.endPathEdges = endPathEdges; + } + + public IDictionary EdgePredecessors + { + get + { + return edgePredecessors; + } + } + + public IList EndPathEdges + { + get + { + return endPathEdges; + } + } + + public void Attach(IEdgePredecessorRecorderAlgorithm algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + algorithm.DiscoverTreeEdge +=new EdgeEdgeEventHandler(this.DiscoverTreeEdge); + algorithm.FinishEdge +=new EdgeEventHandler(this.FinishEdge); + } + + public void Detach(IEdgePredecessorRecorderAlgorithm algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + algorithm.DiscoverTreeEdge -= new EdgeEdgeEventHandler(this.DiscoverTreeEdge); + algorithm.FinishEdge -= new EdgeEventHandler(this.FinishEdge); + } + + public ICollection Path(TEdge se) + { + List path = new List(); + + TEdge ec = se; + path.Insert(0, ec); + while (EdgePredecessors.ContainsKey(ec)) + { + TEdge e = EdgePredecessors[ec]; + path.Insert(0, e); + ec = e; + } + return path; + } + + public ICollection> AllPaths() + { + IList> es = new List>(); + + foreach (var e in EndPathEdges) + es.Add(Path(e)); + + return es; + } + + public ICollection MergedPath(TEdge se, IDictionary colors) + { + List path = new List(); + + TEdge ec = se; + GraphColor c = colors[ec]; + if (c != GraphColor.White) + return path; + else + colors[ec] = GraphColor.Black; + + path.Insert(0, ec); + while (EdgePredecessors.ContainsKey(ec)) + { + TEdge e = EdgePredecessors[ec]; + c = colors[e]; + if (c != GraphColor.White) + return path; + else + colors[e] = GraphColor.Black; + + path.Insert(0, e); + ec = e; + } + return path; + } + + public ICollection> AllMergedPaths() + { + List> es = new List>(EndPathEdges.Count); + IDictionary colors = new Dictionary(); + + foreach (KeyValuePair de in EdgePredecessors) + { + colors[de.Key] = GraphColor.White; + colors[de.Value] = GraphColor.White; + } + + for (int i = 0; i < EndPathEdges.Count; ++i) + es.Add(MergedPath(EndPathEdges[i], colors)); + + return es; + } + + private void DiscoverTreeEdge(Object sender, EdgeEdgeEventArgs args) + { + if (!args.Edge.Equals(args.TargetEdge)) + EdgePredecessors[args.TargetEdge] = args.Edge; + } + + private void FinishEdge(Object sender, EdgeEventArgs args) + { + foreach (var edge in this.EdgePredecessors.Values) + if (edge.Equals(args.Edge)) + return; + + this.EndPathEdges.Add(args.Edge); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs.meta new file mode 100644 index 0000000..96b1e88 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgePredecessorRecorderObserver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a881b56ac3b0d4ed08314d3fa6a7f4a9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs new file mode 100755 index 0000000..889b326 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Observers +{ + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class EdgeRecorderObserver : + IObserver> + where TEdge : IEdge + { + private IList edges; + public EdgeRecorderObserver() + :this(new List()) + {} + + public EdgeRecorderObserver(IList edges) + { + if (edges == null) + throw new ArgumentNullException("edges"); + this.edges = edges; + } + + public IList Edges + { + get + { + return this.edges; + } + } + + public void Attach(ITreeBuilderAlgorithm algorithm) + { + algorithm.TreeEdge +=new EdgeEventHandler(RecordEdge); + } + + public void Detach(ITreeBuilderAlgorithm algorithm) + { + algorithm.TreeEdge -=new EdgeEventHandler(RecordEdge); + } + + public void RecordEdge(Object sender, EdgeEventArgs args) + { + this.Edges.Add(args.Edge); + } + public void RecordSource(Object sender, EdgeEdgeEventArgs args) + { + this.Edges.Add(args.Edge); + } + public void RecordTarget(Object sender, EdgeEdgeEventArgs args) + { + this.Edges.Add(args.TargetEdge); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs.meta new file mode 100644 index 0000000..f545304 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/EdgeRecorderObserver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fbf16462c074f4a2a94b9280cad02291 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs new file mode 100755 index 0000000..25fadfb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs @@ -0,0 +1,16 @@ +using System; +namespace QuickGraph.Algorithms.Observers +{ + /// + /// An algorithm observer + /// + /// + /// + public interface IObserver + { + void Attach(TAlgorithm algorithm); + void Detach(TAlgorithm algorithm); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs.meta new file mode 100644 index 0000000..ff6384b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/IObserver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec97caa52e5884d758723e29ee27a034 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs new file mode 100755 index 0000000..6bcb447 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs @@ -0,0 +1,44 @@ +using System; + +namespace QuickGraph.Algorithms.Observers +{ + [Serializable] + public static class ObserverScope + { + public static IDisposable + Create(TAlgorithm algorithm, IObserver observer) + { + return new ObserverGuardian(algorithm, observer); + } + + [Serializable] + internal sealed class ObserverGuardian : + IDisposable + { + private TAlgorithm algorithm; + private IObserver observer; + + public ObserverGuardian(TAlgorithm algorithm, IObserver observer) { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + if (observer == null) + throw new ArgumentNullException("observer"); + + this.algorithm = algorithm; + this.observer = observer; + + this.observer.Attach(this.algorithm); + } + + public void Dispose() { + if (this.observer != null && this.algorithm != null) + { + this.observer.Detach(this.algorithm); + this.algorithm = default(TAlgorithm); + this.observer = null; + } + } + } + + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs.meta new file mode 100644 index 0000000..63b6d4b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/ObserverUtility.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c28144388749346ed8227f69045a3788 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs new file mode 100755 index 0000000..1df9373 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Observers +{ + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class VertexDistanceRecorderObserver : + IObserver> + where TEdge : IEdge + { + private IDictionary distances; + + public VertexDistanceRecorderObserver() + :this(new Dictionary()) + {} + + public VertexDistanceRecorderObserver(IDictionary distances) + { + if (distances == null) + throw new ArgumentNullException("distances"); + this.distances = distances; + } + + public IDictionary Distances + { + get { return this.distances; } + } + + public void Attach(IDistanceRecorderAlgorithm algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("algorithm"); + + algorithm.TreeEdge += new EdgeEventHandler(this.TreeEdge); + } + + public void Detach(IDistanceRecorderAlgorithm algorithm) + { + if (algorithm == null) + throw new ArgumentNullException("arg"); + + algorithm.TreeEdge -= new EdgeEventHandler(this.TreeEdge); + } + + private void TreeEdge(Object sender, EdgeEventArgs args) + { + int sourceDistance; + if(!this.distances.TryGetValue(args.Edge.Source, out sourceDistance)) + this.distances[args.Edge.Source] = sourceDistance = 0; + this.distances[args.Edge.Target] = sourceDistance + 1; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs.meta new file mode 100644 index 0000000..0669401 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexDistanceRecorderObserver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5f5218d0d88684efd823e9e71aaaad86 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs new file mode 100755 index 0000000..439561d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Observers +{ + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class VertexPredecessorRecorderObserver : + IObserver> + where TEdge : IEdge + { + private readonly IDictionary vertexPredecessors; + private readonly List endPathVertices = new List(); + private bool recordEndPath = true; + + public VertexPredecessorRecorderObserver() + :this(new Dictionary()) + {} + + public VertexPredecessorRecorderObserver( + IDictionary vertexPredecessors) + { + if (vertexPredecessors == null) + throw new ArgumentNullException("vertexPredecessors"); + this.vertexPredecessors = vertexPredecessors; + } + + public IDictionary VertexPredecessors + { + get { return this.vertexPredecessors; } + } + + public ICollection EndPathVertices + { + get { return this.endPathVertices; } + } + + public bool RecordEndPath + { + get { return this.recordEndPath; } + set { this.recordEndPath = value; } + } + + public void Attach(IVertexPredecessorRecorderAlgorithm algorithm) + { + algorithm.StartVertex += new VertexEventHandler(StartVertex); + algorithm.TreeEdge+=new EdgeEventHandler(TreeEdge); + algorithm.FinishVertex+=new VertexEventHandler(FinishVertex); + } + + public void Detach(IVertexPredecessorRecorderAlgorithm algorithm) + { + algorithm.StartVertex -= new VertexEventHandler(StartVertex); + algorithm.TreeEdge -= new EdgeEventHandler(TreeEdge); + algorithm.FinishVertex -= new VertexEventHandler(FinishVertex); + } + + void StartVertex(object sender, VertexEventArgs e) + { +// VertexPredecessors[e.Vertex] = default(Edge); + } + + void TreeEdge(Object sender, EdgeEventArgs e) + { + VertexPredecessors[e.Edge.Target] = e.Edge; + } + + void FinishVertex(Object sender, VertexEventArgs e) + { + if (this.RecordEndPath) + { + foreach (var edge in this.VertexPredecessors.Values) + { + if (edge.Source.Equals(e.Vertex)) + return; + } + this.endPathVertices.Add(e.Vertex); + } + } + + public List Path(TVertex v) + { + List path = new List(); + + TVertex vc = v; + TEdge e; + while (this.VertexPredecessors.TryGetValue(vc, out e)) + { + path.Insert(0, e); + vc = e.Source; + } + + return path; + } + + public IList> AllPaths() + { + List> es = new List>(); + foreach (var v in this.EndPathVertices) + es.Add(Path(v)); + + return es; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs.meta new file mode 100644 index 0000000..ceb8f27 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexPredecessorRecorderObserver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7513d33d3ec9b4916858272c3c60caa7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs new file mode 100755 index 0000000..df02389 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Observers +{ + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class VertexRecorderObserver : + IObserver> + where TEdge : IEdge + { + private IList vertices; + public VertexRecorderObserver() + : this(new List()) + { } + + public VertexRecorderObserver(IList vertices) + { + if (vertices == null) + throw new ArgumentNullException("edges"); + this.vertices = vertices; + } + + public IList Vertices + { + get + { + return this.vertices; + } + } + + public void Attach(IVertexTimeStamperAlgorithm algorithm) + { + algorithm.DiscoverVertex += new VertexEventHandler(algorithm_DiscoverVertex); + } + + public void Detach(IVertexTimeStamperAlgorithm algorithm) + { + algorithm.DiscoverVertex -= new VertexEventHandler(algorithm_DiscoverVertex); + } + + void algorithm_DiscoverVertex(object sender, VertexEventArgs e) + { + this.Vertices.Add(e.Vertex); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs.meta new file mode 100644 index 0000000..10f7096 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexRecorderObserver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 81154368cbff9413c83eb23c15e49f06 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs new file mode 100755 index 0000000..46efb87 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.Observers +{ + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class VertexTimeStamperObserver : + IObserver> + where TEdge : IEdge + { + private IDictionary discoverTimes; + private IDictionary finishTimes; + private int currentTime = 0; + + public VertexTimeStamperObserver() + :this(new Dictionary(), new Dictionary()) + {} + + public VertexTimeStamperObserver( + IDictionary discoverTimes, + IDictionary finishTimes) + { + if (discoverTimes == null) + throw new ArgumentNullException("discoverTimes"); + if (finishTimes == null) + throw new ArgumentNullException("finishTimes"); + this.discoverTimes = discoverTimes; + this.finishTimes = finishTimes; + } + + public IDictionary DiscoverTimes + { + get { return this.discoverTimes; } + } + + public IDictionary FinishTimes + { + get { return this.finishTimes; } + } + + public void Attach(IVertexTimeStamperAlgorithm algorithm) + { + algorithm.DiscoverVertex+=new VertexEventHandler(DiscoverVertex); + algorithm.FinishVertex+=new VertexEventHandler(FinishVertex); + } + + public void Detach(IVertexTimeStamperAlgorithm algorithm) + { + algorithm.DiscoverVertex -= new VertexEventHandler(DiscoverVertex); + algorithm.FinishVertex -= new VertexEventHandler(FinishVertex); + } + + void DiscoverVertex(Object sender, VertexEventArgs e) + { + this.discoverTimes[e.Vertex] = this.currentTime++; + } + + void FinishVertex(Object sender, VertexEventArgs e) + { + this.finishTimes[e.Vertex] = this.currentTime++; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs.meta new file mode 100644 index 0000000..4ca906f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Observers/VertexTimeStamperObserver.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1852c24fa2c9f4279ac708dc85bcb04d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs new file mode 100755 index 0000000..55a42d9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Predicates; +using QuickGraph.Collections; + +namespace QuickGraph.Algorithms.Ranking +{ + [Serializable] + public sealed class PageRankAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private IDictionary ranks = new Dictionary(); + + private int maxIterations = 60; + private double tolerance = 2 * double.Epsilon; + private double damping = 0.85; + + public PageRankAlgorithm(IBidirectionalGraph visitedGraph) + :base(visitedGraph) + {} + + public IDictionary Ranks + { + get + { + return this.ranks; + } + } + + public double Damping + { + get + { + return this.damping; + } + set + { + this.damping = value; + } + } + + public double Tolerance + { + get + { + return this.tolerance; + } + set + { + this.tolerance = value; + } + } + + public int MaxIteration + { + get + { + return this.maxIterations; + } + set + { + this.maxIterations = value; + } + } + + public void InitializeRanks() + { + this.ranks.Clear(); + foreach (var v in this.VisitedGraph.Vertices) + { + this.ranks.Add(v, 0); + } +// this.RemoveDanglingLinks(); + } +/* + public void RemoveDanglingLinks() + { + VertexCollection danglings = new VertexCollection(); + do + { + danglings.Clear(); + + // create filtered graph + IVertexListGraph fg = new FilteredVertexListGraph( + this.VisitedGraph, + new InDictionaryVertexPredicate(this.ranks) + ); + + // iterate over of the vertices in the rank map + foreach (IVertex v in this.ranks.Keys) + { + // if v does not have out-edge in the filtered graph, remove + if (fg.OutDegree(v) == 0) + danglings.Add(v); + } + + // remove from ranks + foreach (IVertex v in danglings) + this.ranks.Remove(v); + // iterate until no dangling was removed + } while (danglings.Count != 0); + } +*/ + protected override void InternalCompute() + { + var cancelManager = this.Services.CancelManager; + IDictionary tempRanks = new Dictionary(); + + // create filtered graph + FilteredBidirectionalGraph< + TVertex, + TEdge, + IBidirectionalGraph + > fg = new FilteredBidirectionalGraph>( + this.VisitedGraph, + new InDictionaryVertexPredicate(this.ranks).Test, + new AnyEdgePredicate().Test + ); + + int iter = 0; + double error = 0; + do + { + if (cancelManager.IsCancelling) + return; + + // compute page ranks + error = 0; + foreach (KeyValuePair de in this.Ranks) + { + if (cancelManager.IsCancelling) + return; + + TVertex v = de.Key; + double rank = de.Value; + // compute ARi + double r = 0; + foreach (var e in fg.InEdges(v)) + { + r += this.ranks[e.Source] / fg.OutDegree(e.Source); + } + + // add sourceRank and store + double newRank = (1 - this.damping) + this.damping * r; + tempRanks[v] = newRank; + // compute deviation + error += Math.Abs(rank - newRank); + } + + // swap ranks + var temp = ranks; + ranks = tempRanks; + tempRanks = temp; + + iter++; + } while (error > this.tolerance && iter < this.maxIterations); + Console.WriteLine("{0}, {1}", iter, error); + } + + public double GetRanksSum() + { + double sum = 0; + foreach (double rank in this.ranks.Values) + { + sum += rank; + } + return sum; + } + + public double GetRanksMean() + { + return GetRanksSum() / this.ranks.Count; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs.meta new file mode 100644 index 0000000..0c1e139 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/PageRankAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 551c6fd618320496a9295852d0637557 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs new file mode 100755 index 0000000..9d6d28c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public static class RandomGraphFactory + { + public static TVertex GetVertex(IVertexListGraph g, Random rnd) + where TEdge : IEdge + { + if (g == null) + throw new ArgumentNullException("g"); + if (rnd == null) + throw new ArgumentNullException("random generator"); + if (g.VertexCount == 0) + throw new ArgumentException("g is empty"); + return GetVertex(g.Vertices, g.VertexCount, rnd); + } + + public static TVertex GetVertex(IEnumerable vertices, int count, Random rnd) + where TEdge : IEdge + { + if (vertices == null) + throw new ArgumentNullException("vertices"); + if (rnd == null) + throw new ArgumentNullException("random generator"); + if (count == 0) + throw new ArgumentException("vertices is empty"); + + int i = rnd.Next(count); + foreach (var v in vertices) + { + if (i == 0) + return v; + else + --i; + } + + // failed + throw new InvalidOperationException("Could not find vertex"); + } + + public static TEdge GetEdge(IEdgeSet g, Random rnd) + where TEdge : IEdge + { + if (g == null) + throw new ArgumentNullException("g"); + if (rnd == null) + throw new ArgumentNullException("random generator"); + if (g.EdgeCount == 0) + throw new ArgumentException("g is empty"); + + int i = rnd.Next(g.EdgeCount); + foreach (var e in g.Edges) + { + if (i == 0) + return e; + else + --i; + } + + // failed + throw new InvalidOperationException("Could not find edge"); + } + + public static TEdge GetEdge(IEnumerable edges, int count, Random rnd) + where TEdge : IEdge + { + if (edges == null) + throw new ArgumentNullException("edges"); + if (rnd == null) + throw new ArgumentNullException("random generator"); + if (count == 0) + throw new ArgumentException("edges is empty"); + + int i = rnd.Next(count); + foreach (var e in edges) + { + if (i == 0) + return e; + else + --i; + } + + // failed + throw new InvalidOperationException("Could not find edge"); + } + + public static void Create( + IMutableVertexAndEdgeListGraph g, + Random rnd, + int vertexCount, + int edgeCount, + bool selfEdges + ) where TEdge : IEdge + { + Create( + g, + FactoryCompiler.GetVertexFactory(), + FactoryCompiler.GetEdgeFactory(), + rnd, + vertexCount, + edgeCount, + selfEdges + ); + } + + public static void Create( + IMutableVertexAndEdgeListGraph g, + IVertexFactory vertexFactory, + IEdgeFactory edgeFactory, + Random rnd, + int vertexCount, + int edgeCount, + bool selfEdges + ) where TEdge : IEdge + { + if (g == null) + throw new ArgumentNullException("g"); + if (vertexFactory == null) + throw new ArgumentNullException("vertexFactory"); + if (edgeFactory == null) + throw new ArgumentNullException("edgeFactory"); + if (rnd == null) + throw new ArgumentNullException("random generator"); + + + for (int i = 0; i < vertexCount; ++i) + g.AddVertex( vertexFactory.CreateVertex() ); + + + TVertex a; + TVertex b; + int j = 0; + while (j < edgeCount) + { + a = GetVertex(g, rnd); + do + { + b = GetVertex(g, rnd); + } + while (selfEdges == false && a.Equals(b)); + + if (g.AddEdge( edgeFactory.CreateEdge(a,b))) + ++j; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs.meta new file mode 100644 index 0000000..2c3f1d9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomGraphFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9203e7502d93f47f69ee9f9c5a1de628 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks.meta new file mode 100644 index 0000000..32e38f1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: af2938d1854234403960a2bb626798b6 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs new file mode 100755 index 0000000..21db4e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.RandomWalks +{ + /// + /// Wilson-Propp Cycle-Popping Algorithm for Random Tree Generation. + /// + [Serializable] + public sealed class CyclePoppingRandomTreeAlgorithm : + RootedAlgorithmBase> + where TEdge : IEdge + { + private IDictionary vertexColors = new Dictionary(); + private IMarkovEdgeChain edgeChain = new NormalizedMarkovEdgeChain(); + private IDictionary successors = new Dictionary(); + private Random rnd = new Random((int)DateTime.Now.Ticks); + + public CyclePoppingRandomTreeAlgorithm( + IVertexListGraph visitedGraph) + : this(visitedGraph, new NormalizedMarkovEdgeChain()) + { } + + public CyclePoppingRandomTreeAlgorithm( + IVertexListGraph visitedGraph, + IMarkovEdgeChain edgeChain) + : this(null, visitedGraph, edgeChain) + { } + + public CyclePoppingRandomTreeAlgorithm( + IAlgorithmComponent host, + IVertexListGraph visitedGraph, + IMarkovEdgeChain edgeChain + ) + :base(host, visitedGraph) + { + if (edgeChain == null) + throw new ArgumentNullException("edgeChain"); + this.edgeChain = edgeChain; + } + + public IDictionary VertexColors + { + get + { + return this.vertexColors; + } + } + + public IMarkovEdgeChain EdgeChain + { + get + { + return this.edgeChain; + } + } + + /// + /// Gets or sets the random number generator used in RandomTree. + /// + /// + /// number generator + /// + public Random Rnd + { + get + { + return this.rnd; + } + set + { + this.rnd = value; + } + } + + public IDictionary Successors + { + get + { + return this.successors; + } + } + + public event VertexEventHandler InitializeVertex; + private void OnInitializeVertex(TVertex v) + { + if (this.InitializeVertex != null) + this.InitializeVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler FinishVertex; + private void OnFinishVertex(TVertex v) + { + if (this.FinishVertex != null) + this.FinishVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (this.TreeEdge != null) + this.TreeEdge(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler ClearTreeVertex; + private void OnClearTreeVertex(TVertex v) + { + if (this.ClearTreeVertex != null) + this.ClearTreeVertex(this, new VertexEventArgs(v)); + } + + private void Initialize() + { + this.successors.Clear(); + this.vertexColors.Clear(); + foreach (var v in this.VisitedGraph.Vertices) + { + this.vertexColors.Add(v,GraphColor.White); + OnInitializeVertex(v); + } + } + + private bool NotInTree(TVertex u) + { + GraphColor color = this.vertexColors[u]; + return color == GraphColor.White; + } + + private void SetInTree(TVertex u) + { + this.vertexColors[u] = GraphColor.Black; + OnFinishVertex(u); + } + + private TEdge RandomSuccessor(TVertex u) + { + return this.EdgeChain.Successor(this.VisitedGraph, u); + } + + private void Tree(TVertex u, TEdge next) + { + this.successors[u] = next; + if (next == null) + return; + OnTreeEdge(next); + } + + private TVertex NextInTree(TVertex u) + { + TEdge next = this.successors[u]; + if (next == null) + return default(TVertex); + else + return next.Target; + } + + private bool Chance(double eps) + { + return this.rnd.NextDouble() <= eps; + } + + private void ClearTree(TVertex u) + { + this.successors[u] = default(TEdge); + OnClearTreeVertex(u); + } + + public void RandomTreeWithRoot(TVertex root) + { + if (root == null) + throw new ArgumentNullException("root"); + this.SetRootVertex(root); + this.Compute(); + } + + protected override void InternalCompute() + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + throw new InvalidOperationException("RootVertex not specified"); + // initialize vertices to white + Initialize(); + + // process root + ClearTree(rootVertex); + SetInTree(rootVertex); + + TVertex u; + foreach (var i in this.VisitedGraph.Vertices) + { + u = i; + + // first pass exploring + while (u != null && NotInTree(u)) + { + Tree(u, RandomSuccessor(u)); + u = NextInTree(u); + } + + // second pass, coloring + u = i; + while (u != null && NotInTree(u)) + { + SetInTree(u); + u = NextInTree(u); + } + } + } + + public void RandomTree() + { + double eps = 1; + bool success; + do + { + eps /= 2; + success = Attempt(eps); + } while (!success); + } + + private bool Attempt(double eps) + { + Initialize(); + int numRoots = 0; + + TVertex u; + foreach (var i in this.VisitedGraph.Vertices) + { + u = i; + + // first pass exploring + while (u != null && NotInTree(u)) + { + if (Chance(eps)) + { + ClearTree(u); + SetInTree(u); + ++numRoots; + if (numRoots > 1) + return false; + } + else + { + Tree(u, RandomSuccessor(u)); + u = NextInTree(u); + } + } + + // second pass, coloring + u = i; + while (u != null && NotInTree(u)) + { + SetInTree(u); + u = NextInTree(u); + } + } + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs.meta new file mode 100644 index 0000000..b1c5cab --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/CyclePoppingRandomTreeAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 73c6810cbc095455abf303548f1df969 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs new file mode 100755 index 0000000..bea4b75 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs @@ -0,0 +1,8 @@ +namespace QuickGraph.Algorithms.RandomWalks +{ + public interface IEdgeChain + where TEdge : IEdge + { + TEdge Successor(IImplicitGraph g, TVertex u); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs.meta new file mode 100644 index 0000000..1129e13 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IEdgeChain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d9748959bf76e469e95f5ea5710c5c70 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs new file mode 100755 index 0000000..61c0c0e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs @@ -0,0 +1,9 @@ +using System; +namespace QuickGraph.Algorithms.RandomWalks +{ + public interface IMarkovEdgeChain : IEdgeChain + where TEdge : IEdge + { + Random Rand { get;set;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs.meta new file mode 100644 index 0000000..6720a08 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/IMarkovEdgeChain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3803279c53e8a43099ee167b44d19bb5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs new file mode 100755 index 0000000..29509b7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs @@ -0,0 +1,26 @@ +using System; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [Serializable] + public abstract class MarkovEdgeChainBase : + IMarkovEdgeChain + where TEdge : IEdge + { + private Random rand = new Random(); + + public Random Rand + { + get + { + return this.rand; + } + set + { + this.rand = value; + } + } + + public abstract TEdge Successor(IImplicitGraph g, TVertex u); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs.meta new file mode 100644 index 0000000..3828622 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/MarkovEdgeChainBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7a59d22ac9b8e40acbe7852ee4b80b4e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs new file mode 100755 index 0000000..8fb4850 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [Serializable] + public sealed class NormalizedMarkovEdgeChain : + MarkovEdgeChainBase + where TEdge : IEdge + { + public override TEdge Successor(IImplicitGraph g, TVertex u) + { + int outDegree = g.OutDegree(u); + if (outDegree == 0) + return default(TEdge); + + int index = this.Rand.Next(0, outDegree); + return g.OutEdge(u, index); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs.meta new file mode 100644 index 0000000..979d5db --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/NormalizedMarkovEdgeChain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 70c4579455495474b814507a32309dd5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs new file mode 100755 index 0000000..8c3471e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.Observers; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [Serializable] + public sealed class RandomWalkAlgorithm : + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private IImplicitGraph visitedGraph; + private EdgePredicate endPredicate; + private IEdgeChain edgeChain; + + public RandomWalkAlgorithm(IImplicitGraph visitedGraph) + :this(visitedGraph,new NormalizedMarkovEdgeChain()) + {} + + public RandomWalkAlgorithm( + IImplicitGraph visitedGraph, + IEdgeChain edgeChain + ) + { + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + if (edgeChain == null) + throw new ArgumentNullException("edgeChain"); + this.visitedGraph = visitedGraph; + this.edgeChain = edgeChain; + } + + public IImplicitGraph VisitedGraph + { + get + { + return this.visitedGraph; + } + } + + public IEdgeChain EdgeChain + { + get + { + return this.edgeChain; + } + set + { + if (value == null) + throw new ArgumentNullException("edgeChain"); + this.edgeChain = value; + } + } + + public EdgePredicate EndPredicate + { + get + { + return this.endPredicate; + } + set + { + this.endPredicate = value; + } + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + if (StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler EndVertex; + private void OnEndVertex(TVertex v) + { + if (EndVertex != null) + EndVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (this.TreeEdge != null) + this.TreeEdge(this, new EdgeEventArgs(e)); + } + + private TEdge Successor(TVertex u) + { + return this.EdgeChain.Successor(this.VisitedGraph, u); + } + + public void Generate(TVertex root) + { + if (root == null) + throw new ArgumentNullException("root"); + Generate(root, 100); + } + + public void Generate(TVertex root, int walkCount) + { + if (root == null) + throw new ArgumentNullException("root"); + + int count = 0; + TEdge e = default(TEdge); + TVertex v = root; + + OnStartVertex(root); + while (count < walkCount) + { + e = Successor(v); + // if dead end stop + if (e==null) + break; + // if end predicate, test + if (this.endPredicate != null && this.endPredicate(e)) + break; + OnTreeEdge(e); + v = e.Target; + // upgrade count + ++count; + } + OnEndVertex(v); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs.meta new file mode 100644 index 0000000..c8cc8de --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RandomWalkAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4505fbdb09fd945e38a70616f3b265c4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs new file mode 100755 index 0000000..86dc811 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [Serializable] + public sealed class RoundRobinEdgeChain : + IEdgeChain + where TEdge : IEdge + { + private Dictionary outEdgeIndices = new Dictionary(); + + public TEdge Successor(IImplicitGraph g, TVertex u) + { + int outDegree = g.OutDegree(u); + if (outDegree == 0) + return default(TEdge); + + int index; + if (!outEdgeIndices.TryGetValue(u, out index)) + { + index = 0; + outEdgeIndices.Add(u, index); + } + TEdge e = g.OutEdge(u, index); + this.outEdgeIndices[u] = (++index) % outDegree; + + return e; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs.meta new file mode 100644 index 0000000..a8d4a77 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/RoundRobinEdgeChain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 46c01a87cffd84bf998e2563dc310077 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs new file mode 100755 index 0000000..26e165b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +namespace QuickGraph.Algorithms.RandomWalks +{ + [Serializable] + public sealed class VanishingWeightedMarkovEdgeChain : + WeightedMarkovEdgeChainBase + where TEdge : IEdge + { + private double factor; + + public VanishingWeightedMarkovEdgeChain(IDictionary weights) + :this(weights,0.2) + {} + + public VanishingWeightedMarkovEdgeChain(IDictionary weights, double factor) + :base(weights) + { + this.factor = factor; + } + + public double Factor + { + get + { + return this.factor; + } + set + { + this.factor = value; + } + } + + public override TEdge Successor(IImplicitGraph g, TVertex u) + { + if (g.IsOutEdgesEmpty(u)) + return default(TEdge); + // get outweight + double outWeight = GetOutWeight(g, u); + // get succesor + TEdge s = Successor(g,u,this.Rand.NextDouble() * outWeight); + + // update probabilities + this.Weights[s]*=this.Factor; + + // normalize + foreach(TEdge e in g.OutEdges(u)) + { + checked + { + this.Weights[e]/=outWeight; + } + } + + return s; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs.meta new file mode 100644 index 0000000..5ac9ba5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/VanishingWeightedMarkovEdgeChain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f24dadeaa3cf44378aa09c036d8d7b8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs new file mode 100755 index 0000000..ce04e6b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [Serializable] + public sealed class WeightedMarkovEdgeChain : + WeightedMarkovEdgeChainBase + where TEdge : IEdge + { + public WeightedMarkovEdgeChain(IDictionary weights) + :base(weights) + {} + + public override TEdge Successor(IImplicitGraph g, TVertex u) + { + if (g == null) + throw new ArgumentNullException("g"); + if (u == null) + throw new ArgumentNullException("u"); + + // get number of out-edges + int n = g.OutDegree(u); + if (n == 0) + return default(TEdge); + // compute out-edge su + double outWeight = GetOutWeight(g, u); + // scale and get next edge + double r = this.Rand.NextDouble() * outWeight; + return Successor(g, u, r); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs.meta new file mode 100644 index 0000000..ebc9449 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkedEdgeChain.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc43d8b0c329646dda76f083f52ff9de +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs new file mode 100755 index 0000000..be74983 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Algorithms.RandomWalks +{ + [Serializable] + public abstract class WeightedMarkovEdgeChainBase : + MarkovEdgeChainBase + where TEdge : IEdge + { + private IDictionary weights; + public WeightedMarkovEdgeChainBase(IDictionary weights) + { + if (weights == null) + throw new ArgumentNullException("weights"); + this.weights = weights; + } + + public IDictionary Weights + { + get { return this.weights; } + set { this.weights = value; } + } + + protected double GetOutWeight(IImplicitGraph g, TVertex u) + { + double outWeight = 0; + foreach (var e in g.OutEdges(u)) + { + outWeight += this.weights[e]; + } + return outWeight; + } + + protected TEdge Successor(IImplicitGraph g, TVertex u, double position) + { + double pos = 0; + double nextPos = 0; + foreach (var e in g.OutEdges(u)) + { + nextPos = pos + this.weights[e]; + if (position >= pos && position <= nextPos) + return e; + pos = nextPos; + } + return default(TEdge); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs.meta new file mode 100644 index 0000000..60d69c5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RandomWalks/WeightedMarkovEdgeChainBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 88e7932a833bb443d91fe9ba5f7cebe3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs new file mode 100755 index 0000000..f997f8d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs @@ -0,0 +1,67 @@ +using System; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public abstract class RootedAlgorithmBase : + AlgorithmBase + { + private TVertex rootVertex; + private bool hasRootVertex; + + protected RootedAlgorithmBase( + IAlgorithmComponent host, + TGraph visitedGraph) + :base(host, visitedGraph) + {} + + public bool TryGetRootVertex(out TVertex rootVertex) + { + if (this.hasRootVertex) + { + rootVertex = this.rootVertex; + return true; + } + else + { + rootVertex = default(TVertex); + return false; + } + } + + public void SetRootVertex(TVertex rootVertex) + { + GraphContracts.AssumeNotNull(rootVertex, "rootVertex"); + // GraphContracts.AssumeInVertexSet(this.VisitedGraph, rootVertex, "rootVertex"); + + bool changed = !Comparison.Equals(this.rootVertex, rootVertex); + this.rootVertex = rootVertex; + if (changed) + this.OnRooVertexChanged(EventArgs.Empty); + this.hasRootVertex = true; + } + + public void ClearRootVertex() + { + this.rootVertex = default(TVertex); + this.hasRootVertex = false; + } + + public event EventHandler RootVertexChanged; + protected virtual void OnRooVertexChanged(EventArgs e) + { + if (this.RootVertexChanged != null) + this.RootVertexChanged(this, e); + } + + public void Compute(TVertex rootVertex) + { + GraphContracts.AssumeNotNull(rootVertex, "rootVertex"); + // GraphContracts.AssumeInVertexSet(this.VisitedGraph, rootVertex, "rootVertex"); + + this.SetRootVertex(rootVertex); + this.Compute(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs.meta new file mode 100644 index 0000000..7c4f796 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/RootedAlgorithmBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e72897705f83441a0bf279d93e9dee45 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search.meta new file mode 100644 index 0000000..0dec8f0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: cae3bd092ded64da48beb9ec449fdcc0 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..4e77fa6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A depth and height first search algorithm for directed graphs + /// + /// + /// This is a modified version of the classic DFS algorithm + /// where the search is performed both in depth and height. + /// + /// + [Serializable] + public sealed class BidirectionalDepthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IVertexColorizerAlgorithm, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private IDictionary colors; + private int maxDepth = int.MaxValue; + + public BidirectionalDepthFirstSearchAlgorithm(IBidirectionalGraph g) + : this(g, new Dictionary()) + { } + + public BidirectionalDepthFirstSearchAlgorithm( + IBidirectionalGraph visitedGraph, + IDictionary colors + ) + : this(null, visitedGraph, colors) + { } + + public BidirectionalDepthFirstSearchAlgorithm( + IAlgorithmComponent host, + IBidirectionalGraph visitedGraph, + IDictionary colors + ) + : base(host, visitedGraph) + { + if (colors == null) + throw new ArgumentNullException("VertexColors"); + + this.colors = colors; + } + + public IDictionary VertexColors + { + get + { + return this.colors; + } + } + + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + public event VertexEventHandler InitializeVertex; + private void OnInitializeVertex(TVertex v) + { + if (InitializeVertex != null) + InitializeVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + if (StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler DiscoverVertex; + private void OnDiscoverVertex(TVertex v) + { + if (DiscoverVertex != null) + DiscoverVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler BackEdge; + private void OnBackEdge(TEdge e) + { + if (BackEdge != null) + BackEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler ForwardOrCrossEdge; + private void OnForwardOrCrossEdge(TEdge e) + { + if (ForwardOrCrossEdge != null) + ForwardOrCrossEdge(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler FinishVertex; + private void OnFinishVertex(TVertex v) + { + if (FinishVertex != null) + FinishVertex(this, new VertexEventArgs(v)); + } + + protected override void InternalCompute() + { + // put all vertex to white + Initialize(); + + // if there is a starting vertex, start whith him: + TVertex rootVertex; + if (this.TryGetRootVertex(out rootVertex)) + { + OnStartVertex(rootVertex); + Visit(rootVertex, 0); + } + + // process each vertex + var cancelManager = this.Services.CancelManager; + foreach (var u in VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) return; + if (VertexColors[u] == GraphColor.White) + { + OnStartVertex(u); + Visit(u, 0); + } + } + } + + public void Initialize() + { + foreach (var u in VisitedGraph.Vertices) + { + VertexColors[u] = GraphColor.White; + OnInitializeVertex(u); + } + } + + public void Visit(TVertex u, int depth) + { + GraphContracts.AssumeNotNull(u, "u"); + if (depth > this.maxDepth) + return; + + VertexColors[u] = GraphColor.Gray; + OnDiscoverVertex(u); + + var cancelManager = this.Services.CancelManager; + TVertex v = default(TVertex); + foreach (var e in VisitedGraph.OutEdges(u)) + { + if (cancelManager.IsCancelling) return; + + OnExamineEdge(e); + v = e.Target; + ProcessEdge(depth, v, e); + } + + foreach (var e in VisitedGraph.InEdges(u)) + { + if (cancelManager.IsCancelling) return; + + OnExamineEdge(e); + v = e.Source; + ProcessEdge(depth, v, e); + } + + VertexColors[u] = GraphColor.Black; + OnFinishVertex(u); + } + + private void ProcessEdge(int depth, TVertex v, TEdge e) + { + GraphColor c = VertexColors[v]; + if (c == GraphColor.White) + { + OnTreeEdge(e); + Visit(v, depth + 1); + } + else if (c == GraphColor.Gray) + { + OnBackEdge(e); + } + else + { + OnForwardOrCrossEdge(e); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..0f357d8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BidirectionalDepthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: afc03efbba1744f2c84530578253e55e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..3d61ca4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs @@ -0,0 +1,229 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Collections; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A breath first search algorithm for directed graphs + /// + /// + [Serializable] + public sealed class BreadthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IVertexPredecessorRecorderAlgorithm, + IDistanceRecorderAlgorithm, + IVertexColorizerAlgorithm, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private IDictionary vertexColors; + private IQueue vertexQueue; + + public BreadthFirstSearchAlgorithm(IVertexListGraph g) + : this(g, new QuickGraph.Collections.Queue(), new Dictionary()) + {} + + public BreadthFirstSearchAlgorithm( + IVertexListGraph visitedGraph, + IQueue vertexQueue, + IDictionary vertexColors + ) + : this(null, visitedGraph, vertexQueue, vertexColors) + { } + + public BreadthFirstSearchAlgorithm( + IAlgorithmComponent host, + IVertexListGraph visitedGraph, + IQueue vertexQueue, + IDictionary vertexColors + ) + :base(host, visitedGraph) + { + if (vertexQueue == null) + throw new ArgumentNullException("vertexQueue"); + if (vertexColors == null) + throw new ArgumentNullException("vertexColors"); + + this.vertexColors = vertexColors; + this.vertexQueue = vertexQueue; + } + + public IDictionary VertexColors + { + get + { + return vertexColors; + } + } + + public event VertexEventHandler InitializeVertex; + private void OnInitializeVertex(TVertex v) + { + if (InitializeVertex != null) + InitializeVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + VertexEventHandler eh = this.StartVertex; + if (eh!=null) + eh(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler ExamineVertex; + private void OnExamineVertex(TVertex v) + { + if (ExamineVertex != null) + ExamineVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler DiscoverVertex; + private void OnDiscoverVertex(TVertex v) + { + if (DiscoverVertex != null) + DiscoverVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler NonTreeEdge; + private void OnNonTreeEdge(TEdge e) + { + if (NonTreeEdge != null) + NonTreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler GrayTarget; + private void OnGrayTarget(TEdge e) + { + if (GrayTarget != null) + GrayTarget(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler BlackTarget; + private void OnBlackTarget(TEdge e) + { + if (BlackTarget != null) + BlackTarget(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler FinishVertex; + private void OnFinishVertex(TVertex v) + { + if (FinishVertex != null) + FinishVertex(this, new VertexEventArgs(v)); + } + + public void Initialize() + { + var cancelManager = this.Services.CancelManager; + // initialize vertex u + foreach (var v in VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) + return; + VertexColors[v] = GraphColor.White; + OnInitializeVertex(v); + } + } + + protected override void InternalCompute() + { + if (this.VisitedGraph.VertexCount == 0) + return; + + this.Initialize(); + + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + { + // enqueue roots + foreach (var root in AlgoUtility.Roots(this.VisitedGraph)) + this.EnqueueRoot(root); + } + else // enqueue select root only + { + this.Visit(rootVertex); + } + this.FlushVisitQueue(); + } + + public void Visit(TVertex s) + { + this.EnqueueRoot(s); + this.FlushVisitQueue(); + } + + private void EnqueueRoot(TVertex s) + { + this.OnStartVertex(s); + + this.VertexColors[s] = GraphColor.Gray; + + OnDiscoverVertex(s); + this.vertexQueue.Enqueue(s); + } + + private void FlushVisitQueue() + { + var cancelManager = this.Services.CancelManager; + + while (this.vertexQueue.Count != 0) + { + if (cancelManager.IsCancelling) return; + + var u = this.vertexQueue.Dequeue(); + OnExamineVertex(u); + foreach (var e in VisitedGraph.OutEdges(u)) + { + TVertex v = e.Target; + OnExamineEdge(e); + + GraphColor vColor = VertexColors[v]; + if (vColor == GraphColor.White) + { + OnTreeEdge(e); + VertexColors[v] = GraphColor.Gray; + OnDiscoverVertex(v); + this.vertexQueue.Enqueue(v); + } + else + { + OnNonTreeEdge(e); + if (vColor == GraphColor.Gray) + { + OnGrayTarget(e); + } + else + { + OnBlackTarget(e); + } + } + } + VertexColors[u] = GraphColor.Black; + + OnFinishVertex(u); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..5044509 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/BreadthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 35ae30e72c2da4baeacd1606f4fbe77c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..db69052 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A depth first search algorithm for directed graph + /// + /// + /// + /// + [Serializable] + public sealed class DepthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IDistanceRecorderAlgorithm, + IVertexColorizerAlgorithm, + IVertexPredecessorRecorderAlgorithm, + IVertexTimeStamperAlgorithm, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private readonly IDictionary colors; + private int maxDepth = int.MaxValue; + + public DepthFirstSearchAlgorithm(IVertexListGraph g) + :this(g, new Dictionary()) + {} + + public DepthFirstSearchAlgorithm( + IVertexListGraph visitedGraph, + IDictionary colors + ) + : this(null, visitedGraph, colors) + { } + + public DepthFirstSearchAlgorithm( + IAlgorithmComponent host, + IVertexListGraph visitedGraph, + IDictionary colors + ) + :base(host, visitedGraph) + { + if (colors == null) + throw new ArgumentNullException("VertexColors"); + this.colors = colors; + } + + public IDictionary VertexColors + { + get + { + return this.colors; + } + } + + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + public event VertexEventHandler InitializeVertex; + private void OnInitializeVertex(TVertex v) + { + VertexEventHandler eh = this.InitializeVertex; + if (eh!=null) + eh(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + VertexEventHandler eh = this.StartVertex; + if (eh!=null) + eh(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler DiscoverVertex; + private void OnDiscoverVertex(TVertex v) + { + VertexEventHandler eh = this.DiscoverVertex; + if (eh!=null) + eh(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(TEdge e) + { + EdgeEventHandler eh = this.ExamineEdge; + if (eh!=null) + eh(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + EdgeEventHandler eh = this.TreeEdge; + if (eh!=null) + eh(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler BackEdge; + private void OnBackEdge(TEdge e) + { + EdgeEventHandler eh = this.BackEdge; + if (eh!=null) + eh(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler ForwardOrCrossEdge; + private void OnForwardOrCrossEdge(TEdge e) + { + EdgeEventHandler eh = this.ForwardOrCrossEdge; + if (eh!=null) + eh(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler FinishVertex; + private void OnFinishVertex(TVertex v) + { + VertexEventHandler eh = this.FinishVertex; + if (eh!=null) + eh(this, new VertexEventArgs(v)); + } + + protected override void InternalCompute() + { + // put all vertex to white + Initialize(); + + // if there is a starting vertex, start whith him: + TVertex rootVertex; + if (this.TryGetRootVertex(out rootVertex)) + { + OnStartVertex(rootVertex); + Visit(rootVertex, 0); + } + + var cancelManager = this.Services.CancelManager; + // process each vertex + foreach(TVertex u in VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) + return; + if (VertexColors[u] == GraphColor.White) + { + OnStartVertex(u); + Visit(u,0); + } + } + } + + public void Initialize() + { + foreach(TVertex u in VisitedGraph.Vertices) + { + VertexColors[u] = GraphColor.White; + OnInitializeVertex(u); + } + } + + private struct SearchFrame + { + public readonly TVertex Vertex; + public readonly IEnumerator Edges; + public SearchFrame(TVertex vertex, IEnumerator edges) + { + this.Vertex = vertex; + this.Edges = edges; + } + } + + public void Visit(TVertex root, int depth) + { + if ((object)root==null) + throw new ArgumentNullException("root"); + + Stack todo = new Stack(); + this.VertexColors[root] = GraphColor.Gray; + OnDiscoverVertex(root); + + var cancelManager = this.Services.CancelManager; + todo.Push(new SearchFrame(root, this.VisitedGraph.OutEdges(root).GetEnumerator())); + while (todo.Count > 0) + { + if (cancelManager.IsCancelling) return; + + var frame = todo.Pop(); + var u = frame.Vertex; + + var edges = frame.Edges; + while(edges.MoveNext()) + { + TEdge e = edges.Current; + if (cancelManager.IsCancelling) return; + + this.OnExamineEdge(e); + TVertex v = e.Target; + GraphColor c = this.VertexColors[v]; + switch (c) + { + case GraphColor.White: + OnTreeEdge(e); + todo.Push(new SearchFrame(u, edges)); + u = v; + edges = this.VisitedGraph.OutEdges(u).GetEnumerator(); + this.VertexColors[u] = GraphColor.Gray; + this.OnDiscoverVertex(u); + break; + case GraphColor.Gray: + OnBackEdge(e); break; + case GraphColor.Black: + OnForwardOrCrossEdge(e); break; + } + } + + this.VertexColors[u] = GraphColor.Black; + this.OnFinishVertex(u); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..5c5c2af --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/DepthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a1b2c5b681dd0428197d8dc57ea4c1da +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..5e7fc7e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A edge depth first search algorithm for directed graphs + /// + /// + /// This is a variant of the classic DFS algorithm where the + /// edges are color marked instead of the vertices. + /// + /// + [Serializable] + public sealed class EdgeDepthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IEdgeColorizerAlgorithm, + IEdgePredecessorRecorderAlgorithm, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private IDictionary colors; + private int maxDepth = int.MaxValue; + + public EdgeDepthFirstSearchAlgorithm(IEdgeListAndIncidenceGraph g) + :this(g, new Dictionary()) + { + } + + public EdgeDepthFirstSearchAlgorithm( + IEdgeListAndIncidenceGraph visitedGraph, + IDictionary colors + ) + :this(null, visitedGraph, colors) + {} + + public EdgeDepthFirstSearchAlgorithm( + IAlgorithmComponent host, + IEdgeListAndIncidenceGraph visitedGraph, + IDictionary colors + ) + :base(host, visitedGraph) + { + if (colors == null) + throw new ArgumentNullException("VertexColors"); + + this.colors = colors; + } + + public IDictionary EdgeColors + { + get + { + return this.colors; + } + } + + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + public event EdgeEventHandler InitializeEdge; + private void OnInitializeEdge(TEdge e) + { + if (InitializeEdge != null) + InitializeEdge(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + if (StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler StartEdge; + private void OnStartEdge(TEdge e) + { + if (StartEdge != null) + StartEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEdgeEventHandler DiscoverTreeEdge; + private void OnDiscoverTreeEdge(TEdge e, TEdge targetEge) + { + if (DiscoverTreeEdge != null) + DiscoverTreeEdge(this, new EdgeEdgeEventArgs(e, targetEge)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler BackEdge; + private void OnBackEdge(TEdge e) + { + if (BackEdge != null) + BackEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler ForwardOrCrossEdge; + private void OnForwardOrCrossEdge(TEdge e) + { + if (ForwardOrCrossEdge != null) + ForwardOrCrossEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler FinishEdge; + private void OnFinishEdge(TEdge e) + { + if (FinishEdge != null) + FinishEdge(this, new EdgeEventArgs(e)); + } + + protected override void InternalCompute() + { + Initialize(); + var cancelManager = this.Services.CancelManager; + if (cancelManager.IsCancelling) + return; + + // start whith him: + TVertex rootVertex; + if (this.TryGetRootVertex(out rootVertex)) + { + OnStartVertex(rootVertex); + + // process each out edge of v + foreach (var e in VisitedGraph.OutEdges(rootVertex)) + { + if (cancelManager.IsCancelling) + return; + if (EdgeColors[e] == GraphColor.White) + { + OnStartEdge(e); + Visit(e, 0); + } + } + } + + // process the rest of the graph edges + foreach (var e in VisitedGraph.Edges) + { + if (cancelManager.IsCancelling) + return; + if (EdgeColors[e] == GraphColor.White) + { + OnStartEdge(e); + Visit(e, 0); + } + } + } + + public void Initialize() + { + // put all vertex to white + var cancelManager = this.Services.CancelManager; + foreach (var e in VisitedGraph.Edges) + { + if (cancelManager.IsCancelling) + return; + EdgeColors[e] = GraphColor.White; + OnInitializeEdge(e); + } + } + + public void Visit(TEdge se, int depth) + { + if (depth > this.maxDepth) + return; + var cancelManager = this.Services.CancelManager; + + // mark edge as gray + EdgeColors[se] = GraphColor.Gray; + // add edge to the search tree + OnTreeEdge(se); + + // iterate over out-edges + foreach (var e in VisitedGraph.OutEdges(se.Target)) + { + if (cancelManager.IsCancelling) return; + + // check edge is not explored yet, + // if not, explore it. + if (EdgeColors[e] == GraphColor.White) + { + OnDiscoverTreeEdge(se, e); + Visit(e, depth + 1); + } + else if (EdgeColors[e] == GraphColor.Gray) + { + // edge is being explored + OnBackEdge(e); + } + else + // edge is black + OnForwardOrCrossEdge(e); + } + + // all out-edges have been explored + EdgeColors[se] = GraphColor.Black; + OnFinishEdge(se); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..0ba7c46 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/EdgeDepthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22145ecb7e0b84b2e86bc97804ac1964 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs new file mode 100755 index 0000000..1775277 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs @@ -0,0 +1,403 @@ +using System; +using System.Collections.Generic; + +using QuickGraph; +using QuickGraph.Algorithms; + +namespace ModelDriven.Graph.Algorithms.Search +{ + + /// + /// + public sealed class HeightFirstSearchAlgorithm : + /* + IAlgorithm>, + IEdgeColorizerAlgorithm, + IEdgePredecessorRecorderAlgorithm, + ITreeBuilderAlgorithm + where Edge : IEdge + { + private IBidirectionalVertexListGraph visitedGraph; + private VertexColorDictionary colors; + private int maxDepth = int.MaxValue; + + /// + /// A height first search algorithm on a directed graph + /// + /// The graph to traverse + /// g is null + public HeightFirstSearchAlgorithm(IBidirectionalVertexListGraph g) + { + if (g == null) + throw new ArgumentNullException("g"); + this.visitedGraph = g; + this.colors = new VertexColorDictionary(); + } + + /// + /// A height first search algorithm on a directed graph + /// + /// The graph to traverse + /// vertex color map + /// g or colors are null + public HeightFirstSearchAlgorithm( + IBidirectionalVertexListGraph g, + VertexColorDictionary colors + ) + { + if (g == null) + throw new ArgumentNullException("g"); + if (colors == null) + throw new ArgumentNullException("Colors"); + + this.visitedGraph = g; + this.colors = colors; + } + + /// + /// Visited graph + /// + public IBidirectionalVertexListGraph VisitedGraph + { + get + { + return this.visitedGraph; + } + } + + Object IAlgorithm.VisitedGraph + { + get + { + return this.VisitedGraph; + } + } + + /// + /// Gets the vertex color map + /// + /// + /// Vertex color () dictionary + /// + public VertexColorDictionary Colors + { + get + { + return this.colors; + } + } + + /// + /// IVertexColorizerAlgorithm implementation + /// + IDictionary IVertexColorizerAlgorithm.Colors + { + get + { + return this.Colors; + } + } + + /// + /// Gets or sets the maximum exploration depth, from + /// the start vertex. + /// + /// + /// Defaulted at int.MaxValue. + /// + /// + /// Maximum exploration depth. + /// + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + #region Events + /// + /// Invoked on every vertex of the graph before the start of the graph + /// search. + /// + public event VertexEventHandler InitializeVertex; + + /// + /// Raises the event. + /// + /// vertex that raised the event + protected void OnInitializeVertex(IVertex v) + { + if (InitializeVertex != null) + InitializeVertex(this, new VertexEventArgs(v)); + } + + /// + /// Invoked on the source vertex once before the start of the search. + /// + public event VertexEventHandler StartVertex; + + /// + /// Raises the event. + /// + /// vertex that raised the event + protected void OnStartVertex(IVertex v) + { + if (StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + /// + /// Invoked when a vertex is encountered for the first time. + /// + public event VertexEventHandler DiscoverVertex; + + + /// + /// Raises the event. + /// + /// vertex that raised the event + protected void OnDiscoverVertex(IVertex v) + { + if (DiscoverVertex != null) + DiscoverVertex(this, new VertexEventArgs(v)); + } + + /// + /// Invoked on every out-edge of each vertex after it is discovered. + /// + public event EdgeEventHandler ExamineEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + protected void OnExamineEdge(IEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on each edge as it becomes a member of the edges that form + /// the search tree. If you wish to record predecessors, do so at this + /// event point. + /// + public event EdgeEventHandler TreeEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + protected void OnTreeEdge(IEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on the back edges in the graph. + /// + public event EdgeEventHandler BackEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + protected void OnBackEdge(IEdge e) + { + if (BackEdge != null) + BackEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on forward or cross edges in the graph. + /// (In an undirected graph this method is never called.) + /// + public event EdgeEventHandler ForwardOrCrossEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + protected void OnForwardOrCrossEdge(IEdge e) + { + if (ForwardOrCrossEdge != null) + ForwardOrCrossEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on a vertex after all of its out edges have been added to + /// the search tree and all of the adjacent vertices have been + /// discovered (but before their out-edges have been examined). + /// + public event VertexEventHandler FinishVertex; + + /// + /// Raises the event. + /// + /// vertex that raised the event + protected void OnFinishVertex(IVertex v) + { + if (FinishVertex != null) + FinishVertex(this, new VertexEventArgs(v)); + } + #endregion + + /// + /// Execute the DFS search. + /// + public void Compute() + { + Compute(null); + } + + /// + /// Execute the DFS starting with the vertex s + /// + /// Starting vertex + public void Compute(IVertex s) + { + // put all vertex to white + Initialize(); + + // if there is a starting vertex, start whith him: + if (s != null) + { + OnStartVertex(s); + Visit(s, 0); + } + + // process each vertex + foreach (IVertex u in VisitedGraph.Vertices) + { + if (Colors[u] == GraphColor.White) + { + OnStartVertex(u); + Visit(u, 0); + } + } + } + + /// + /// Initializes the vertex color map + /// + /// + /// + public void Initialize() + { + foreach (IVertex u in VisitedGraph.Vertices) + { + Colors[u] = GraphColor.White; + OnInitializeVertex(u); + } + } + + /// + /// Does a depth first search on the vertex u + /// + /// vertex to explore + /// current recursion depth + /// u cannot be null + public void Visit(IVertex u, int depth) + { + if (depth > this.maxDepth) + return; + if (u == null) + throw new ArgumentNullException("u"); + + Colors[u] = GraphColor.Gray; + OnDiscoverVertex(u); + + IVertex v = null; + foreach (IEdge e in VisitedGraph.InEdges(u)) + { + OnExamineEdge(e); + v = e.Source; + GraphColor c = Colors[v]; + if (c == GraphColor.White) + { + OnTreeEdge(e); + Visit(v, depth + 1); + } + else if (c == GraphColor.Gray) + { + OnBackEdge(e); + } + else + { + OnForwardOrCrossEdge(e); + } + } + + Colors[u] = GraphColor.Black; + OnFinishVertex(u); + } + + /// + /// Registers the predecessors handler + /// + /// + public void RegisterPredecessorRecorderHandlers(IPredecessorRecorderVisitor vis) + { + if (vis == null) + throw new ArgumentNullException("visitor"); + TreeEdge += new EdgeEventHandler(vis.TreeEdge); + FinishVertex += new VertexEventHandler(vis.FinishVertex); + } + + /// + /// + /// + /// + public void RegisterTimeStamperHandlers(ITimeStamperVisitor vis) + { + if (vis == null) + throw new ArgumentNullException("visitor"); + + DiscoverVertex += new VertexEventHandler(vis.DiscoverVertex); + FinishVertex += new VertexEventHandler(vis.FinishVertex); + } + + /// + /// + /// + /// + public void RegisterVertexColorizerHandlers(IVertexColorizerVisitor vis) + { + if (vis == null) + throw new ArgumentNullException("visitor"); + + InitializeVertex += new VertexEventHandler(vis.InitializeVertex); + DiscoverVertex += new VertexEventHandler(vis.DiscoverVertex); + FinishVertex += new VertexEventHandler(vis.FinishVertex); + } + + /// + /// + /// + /// + public void RegisterTreeEdgeBuilderHandlers(ITreeEdgeBuilderVisitor vis) + { + if (vis == null) + throw new ArgumentNullException("visitor"); + + TreeEdge += new EdgeEventHandler(vis.TreeEdge); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..bb56e86 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/HeightFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f95833b6da636407585f31dba3543c6c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..b7d3924 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs @@ -0,0 +1,241 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A depth first search algorithm for implicit directed graphs + /// + /// + [Serializable] + public sealed class ImplicitDepthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IVertexPredecessorRecorderAlgorithm, + IVertexTimeStamperAlgorithm, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private int maxDepth = int.MaxValue; + private IDictionary vertexColors = new Dictionary(); + + public ImplicitDepthFirstSearchAlgorithm( + IIncidenceGraph visitedGraph) + : this(null, visitedGraph) + { } + + public ImplicitDepthFirstSearchAlgorithm( + IAlgorithmComponent host, + IIncidenceGraph visitedGraph) + :base(host, visitedGraph) + {} + + /// + /// Gets the vertex color map + /// + /// + /// Vertex color () dictionary + /// + public IDictionary VertexColors + { + get + { + return this.vertexColors; + } + } + + /// + /// Gets or sets the maximum exploration depth, from + /// the start vertex. + /// + /// + /// Defaulted at int.MaxValue. + /// + /// + /// Maximum exploration depth. + /// + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + /// + /// Invoked on the source vertex once before the start of the search. + /// + public event VertexEventHandler StartVertex; + + /// + /// Raises the event. + /// + /// vertex that raised the event + private void OnStartVertex(TVertex v) + { + if (StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + /// + /// Invoked when a vertex is encountered for the first time. + /// + public event VertexEventHandler DiscoverVertex; + + + /// + /// Raises the event. + /// + /// vertex that raised the event + private void OnDiscoverVertex(TVertex v) + { + if (DiscoverVertex != null) + DiscoverVertex(this, new VertexEventArgs(v)); + } + + /// + /// Invoked on every out-edge of each vertex after it is discovered. + /// + public event EdgeEventHandler ExamineEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on each edge as it becomes a member of the edges that form + /// the search tree. If you wish to record predecessors, do so at this + /// event point. + /// + public event EdgeEventHandler TreeEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on the back edges in the graph. + /// + public event EdgeEventHandler BackEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnBackEdge(TEdge e) + { + if (BackEdge != null) + BackEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on forward or cross edges in the graph. + /// (In an undirected graph this method is never called.) + /// + public event EdgeEventHandler ForwardOrCrossEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnForwardOrCrossEdge(TEdge e) + { + if (ForwardOrCrossEdge != null) + ForwardOrCrossEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on a vertex after all of its out edges have been added to + /// the search tree and all of the adjacent vertices have been + /// discovered (but before their out-edges have been examined). + /// + public event VertexEventHandler FinishVertex; + + /// + /// Raises the event. + /// + /// vertex that raised the event + private void OnFinishVertex(TVertex v) + { + if (FinishVertex != null) + FinishVertex(this, new VertexEventArgs(v)); + } + + protected override void InternalCompute() + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + throw new RootVertexNotSpecifiedException(); + + this.Initialize(); + this.Visit(rootVertex, 0); + } + + private void Initialize() + { + this.VertexColors.Clear(); + } + + private void Visit(TVertex u, int depth) + { + if (depth > this.MaxDepth) + return; + + VertexColors[u] = GraphColor.Gray; + OnDiscoverVertex(u); + + var cancelManager = this.Services.CancelManager; + foreach (var e in VisitedGraph.OutEdges(u)) + { + if (cancelManager.IsCancelling) return; + + OnExamineEdge(e); + TVertex v = e.Target; + + if (!this.VertexColors.ContainsKey(v)) + { + OnTreeEdge(e); + Visit(v, depth + 1); + } + else + { + GraphColor c = VertexColors[v]; + if (c == GraphColor.Gray) + { + OnBackEdge(e); + } + else + { + OnForwardOrCrossEdge(e); + } + } + } + + VertexColors[u] = GraphColor.Black; + OnFinishVertex(u); + } + } +} \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..9fbc029 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitDepthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1afed3eb9ff3f4e54bd23f96e1243da7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..f48347c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A edge depth first search algorithm for implicit directed graphs + /// + /// + /// This is a variant of the classic DFS where the edges are color + /// marked. + /// + /// + [Serializable] + public sealed class ImplicitEdgeDepthFirstSearchAlgorithm : + RootedAlgorithmBase>, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private int maxDepth = int.MaxValue; + private IDictionary edgeColors = new Dictionary(); + + public ImplicitEdgeDepthFirstSearchAlgorithm(IIncidenceGraph visitedGraph) + : this(null, visitedGraph) + { } + + public ImplicitEdgeDepthFirstSearchAlgorithm( + IAlgorithmComponent host, + IIncidenceGraph visitedGraph + ) + :base(host, visitedGraph) + {} + + /// + /// + /// Gets the vertex color map + /// + /// + /// Vertex color () dictionary + /// + public IDictionary EdgeColors + { + get + { + return this.edgeColors; + } + } + + /// + /// Gets or sets the maximum exploration depth, from + /// the start vertex. + /// + /// + /// Defaulted at int.MaxValue. + /// + /// + /// Maximum exploration depth. + /// + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + + /// + /// Invoked on the source vertex once before the start of the search. + /// + public event VertexEventHandler StartVertex; + + /// + /// Triggers the StartVertex event. + /// + /// + private void OnStartVertex(TVertex v) + { + if (this.StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + /// + /// Invoked on the first edge of a test case + /// + public event EdgeEventHandler StartEdge; + + /// + /// Triggers the StartEdge event. + /// + /// + private void OnStartEdge(TEdge e) + { + if (this.StartEdge != null) + StartEdge(this, new EdgeEventArgs(e)); + } + + /// + /// + /// + public event EdgeEdgeEventHandler DiscoverTreeEdge; + + /// + /// Triggers DiscoverEdge event + /// + /// + /// + private void OnDiscoverTreeEdge(TEdge se, TEdge e) + { + if (DiscoverTreeEdge != null) + DiscoverTreeEdge(this, new EdgeEdgeEventArgs(se, e)); + } + + /// + /// Invoked on each edge as it becomes a member of the edges that form + /// the search tree. If you wish to record predecessors, do so at this + /// event point. + /// + public event EdgeEventHandler TreeEdge; + + /// + /// Triggers the TreeEdge event. + /// + /// + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on the back edges in the graph. + /// + public event EdgeEventHandler BackEdge; + + /// + /// Triggers the BackEdge event. + /// + /// + private void OnBackEdge(TEdge e) + { + if (BackEdge != null) + BackEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on forward or cross edges in the graph. + /// (In an undirected graph this method is never called.) + /// + public event EdgeEventHandler ForwardOrCrossEdge; + + /// + /// Triggers the ForwardOrCrossEdge event. + /// + /// + private void OnForwardOrCrossEdge(TEdge e) + { + if (this.ForwardOrCrossEdge != null) + ForwardOrCrossEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked on a edge after all of its out edges have been added to + /// the search tree and all of the adjacent vertices have been + /// discovered (but before their out-edges have been examined). + /// + public event EdgeEventHandler FinishEdge; + + /// + /// Triggers the ForwardOrCrossEdge event. + /// + /// + private void OnFinishEdge(TEdge e) + { + if (this.FinishEdge != null) + FinishEdge(this, new EdgeEventArgs(e)); + } + + + + protected override void InternalCompute() + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + throw new RootVertexNotSpecifiedException(); + + // initialize algorithm + this.Initialize(); + + // start whith him: + OnStartVertex(rootVertex); + + var cancelManager = this.Services.CancelManager; + // process each out edge of v + foreach (var e in this.VisitedGraph.OutEdges(rootVertex)) + { + if (cancelManager.IsCancelling) return; + + if (!this.EdgeColors.ContainsKey(e)) + { + OnStartEdge(e); + Visit(e, 0); + } + } + } + + /// + /// Does a depth first search on the vertex u + /// + /// edge to explore + /// current exploration depth + /// se cannot be null + private void Visit(TEdge se, int depth) + { + GraphContracts.AssumeNotNull(se, "se"); + if (depth > this.maxDepth) + return; + + // mark edge as gray + this.EdgeColors[se] = GraphColor.Gray; + // add edge to the search tree + OnTreeEdge(se); + + var cancelManager = this.Services.CancelManager; + // iterate over out-edges + foreach (var e in this.VisitedGraph.OutEdges(se.Target)) + { + if (cancelManager.IsCancelling) return; + + // check edge is not explored yet, + // if not, explore it. + if (!this.EdgeColors.ContainsKey(e)) + { + OnDiscoverTreeEdge(se, e); + Visit(e, depth + 1); + } + else + { + GraphColor c = this.EdgeColors[e]; + if (EdgeColors[e] == GraphColor.Gray) + OnBackEdge(e); + else + OnForwardOrCrossEdge(e); + } + } + + // all out-edges have been explored + this.EdgeColors[se] = GraphColor.Black; + OnFinishEdge(se); + } + + /// + /// Initializes the algorithm before computation. + /// + private void Initialize() + { + this.EdgeColors.Clear(); + } + } +} \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..ebb6090 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/ImplicitEdgeDepthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b49f0d85c7194b3fad4b93da756bc5b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs new file mode 100755 index 0000000..3916bc6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Collections; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A breath first search algorithm for undirected graphs + /// + /// + [Serializable] + public sealed class UndirectedBreadthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IVertexPredecessorRecorderAlgorithm, + IDistanceRecorderAlgorithm, + IVertexColorizerAlgorithm, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private IDictionary vertexColors; + private IQueue vertexQueue; + + public UndirectedBreadthFirstSearchAlgorithm(IUndirectedGraph g) + : this(g, new QuickGraph.Collections.Queue(), new Dictionary()) + { } + + public UndirectedBreadthFirstSearchAlgorithm( + IUndirectedGraph visitedGraph, + IQueue vertexQueue, + IDictionary vertexColors + ) + : this(null, visitedGraph, vertexQueue, vertexColors) + { } + + public UndirectedBreadthFirstSearchAlgorithm( + IAlgorithmComponent host, + IUndirectedGraph visitedGraph, + IQueue vertexQueue, + IDictionary vertexColors + ) + : base(host, visitedGraph) + { + if (vertexQueue == null) + throw new ArgumentNullException("vertexQueue"); + if (vertexColors == null) + throw new ArgumentNullException("vertexColors"); + + this.vertexColors = vertexColors; + this.vertexQueue = vertexQueue; + } + + public IDictionary VertexColors + { + get + { + return vertexColors; + } + } + + public event VertexEventHandler InitializeVertex; + private void OnInitializeVertex(TVertex v) + { + if (InitializeVertex != null) + InitializeVertex(this, new VertexEventArgs(v)); + } + + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + VertexEventHandler eh = this.StartVertex; + if (eh != null) + eh(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler ExamineVertex; + private void OnExamineVertex(TVertex v) + { + if (ExamineVertex != null) + ExamineVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler DiscoverVertex; + private void OnDiscoverVertex(TVertex v) + { + if (DiscoverVertex != null) + DiscoverVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler NonTreeEdge; + private void OnNonTreeEdge(TEdge e) + { + if (NonTreeEdge != null) + NonTreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler GrayTarget; + private void OnGrayTarget(TEdge e) + { + if (GrayTarget != null) + GrayTarget(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler BlackTarget; + private void OnBlackTarget(TEdge e) + { + if (BlackTarget != null) + BlackTarget(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler FinishVertex; + private void OnFinishVertex(TVertex v) + { + if (FinishVertex != null) + FinishVertex(this, new VertexEventArgs(v)); + } + + public void Initialize() + { + // initialize vertex u + var cancelManager = this.Services.CancelManager; + foreach (var v in VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) + return; + VertexColors[v] = GraphColor.White; + OnInitializeVertex(v); + } + } + + protected override void InternalCompute() + { + this.Initialize(); + + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + { + // enqueue all roots + foreach (var root in AlgoUtility.Roots(this.VisitedGraph)) + this.EnqueueRoot(root); + } + else + this.EnqueueRoot(rootVertex); + + this.FlushVisitQueue(); + } + + public void Visit(TVertex s) + { + this.EnqueueRoot(s); + this.FlushVisitQueue(); + } + + private void EnqueueRoot(TVertex s) + { + this.OnStartVertex(s); + this.VertexColors[s] = GraphColor.Gray; + OnDiscoverVertex(s); + this.vertexQueue.Enqueue(s); + } + + private void FlushVisitQueue() + { + var cancelManager = this.Services.CancelManager; + + while (this.vertexQueue.Count != 0) + { + if (cancelManager.IsCancelling) return; + + TVertex u = this.vertexQueue.Dequeue(); + + OnExamineVertex(u); + foreach (var e in VisitedGraph.AdjacentEdges(u)) + { + TVertex v = (e.Source.Equals(u)) ? e.Target : e.Source; + OnExamineEdge(e); + + GraphColor vColor = VertexColors[v]; + if (vColor == GraphColor.White) + { + OnTreeEdge(e); + VertexColors[v] = GraphColor.Gray; + OnDiscoverVertex(v); + this.vertexQueue.Enqueue(v); + } + else + { + OnNonTreeEdge(e); + if (vColor == GraphColor.Gray) + { + OnGrayTarget(e); + } + else + { + OnBlackTarget(e); + } + } + } + VertexColors[u] = GraphColor.Black; + + OnFinishVertex(u); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..b2df960 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedBreathFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00d2961c2e1d74aff968fbf374930941 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..cb0e38e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.Search +{ + /// + /// A depth first search algorithm for undirected graphs + /// + /// + [Serializable] + public sealed class UndirectedDepthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IDistanceRecorderAlgorithm, + IVertexColorizerAlgorithm, + IVertexPredecessorRecorderAlgorithm, + IVertexTimeStamperAlgorithm, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private IDictionary colors; + private int maxDepth = int.MaxValue; + + public UndirectedDepthFirstSearchAlgorithm(IUndirectedGraph g) + :this(g, new Dictionary()) + { + } + + public UndirectedDepthFirstSearchAlgorithm( + IUndirectedGraph visitedGraph, + IDictionary colors + ) + :this(null, visitedGraph, colors) + {} + + public UndirectedDepthFirstSearchAlgorithm( + IAlgorithmComponent host, + IUndirectedGraph visitedGraph, + IDictionary colors + ) + :base(host, visitedGraph) + { + if (colors == null) + throw new ArgumentNullException("VertexColors"); + + this.colors = colors; + } + + public IDictionary VertexColors + { + get + { + return this.colors; + } + } + + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + public event VertexEventHandler InitializeVertex; + private void OnInitializeVertex(TVertex v) + { + if (InitializeVertex != null) + InitializeVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + if (StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler DiscoverVertex; + private void OnDiscoverVertex(TVertex v) + { + if (DiscoverVertex != null) + DiscoverVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler BackEdge; + private void OnBackEdge(TEdge e) + { + if (BackEdge != null) + BackEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler ForwardOrCrossEdge; + private void OnForwardOrCrossEdge(TEdge e) + { + if (ForwardOrCrossEdge != null) + ForwardOrCrossEdge(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler FinishVertex; + private void OnFinishVertex(TVertex v) + { + if (FinishVertex != null) + FinishVertex(this, new VertexEventArgs(v)); + } + + protected override void InternalCompute() + { + // put all vertex to white + Initialize(); + + // if there is a starting vertex, start whith him: + TVertex rootVertex; + if (this.TryGetRootVertex(out rootVertex)) + { + OnStartVertex(rootVertex); + Visit(rootVertex, 0); + } + + var cancelManager = this.Services.CancelManager; + // process each vertex + foreach (var u in VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) + return; + if (VertexColors[u] == GraphColor.White) + { + OnStartVertex(u); + Visit(u, 0); + } + } + } + + public void Initialize() + { + var cancelManager = this.Services.CancelManager; + foreach (var u in VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) + return; + VertexColors[u] = GraphColor.White; + OnInitializeVertex(u); + } + } + + public void Visit(TVertex u, int depth) + { + if (depth > this.maxDepth) + return; + if (u == null) + throw new ArgumentNullException("u"); + + var cancelManager = this.Services.CancelManager; + if (cancelManager.IsCancelling) + return; + + VertexColors[u] = GraphColor.Gray; + OnDiscoverVertex(u); + + TVertex v = default(TVertex); + foreach (var e in VisitedGraph.AdjacentEdges(u)) + { + if (cancelManager.IsCancelling) + return; + + OnExamineEdge(e); + if (u.Equals(e.Source)) + v = e.Target; + else + v = e.Source; + + GraphColor c = VertexColors[v]; + if (c == GraphColor.White) + { + OnTreeEdge(e); + Visit(v, depth + 1); + } + else if (c == GraphColor.Gray) + { + OnBackEdge(e); + } + else + { + OnForwardOrCrossEdge(e); + } + } + + VertexColors[u] = GraphColor.Black; + OnFinishVertex(u); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..bea6e41 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedDepthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4bd3e69f4698547ba8e06d3b9ecbe257 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs new file mode 100755 index 0000000..dac88b5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; + +using QuickGraph; +using QuickGraph.Collections; +using QuickGraph.Algorithms; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Algorithms.Services; + +namespace ModelDriven.Graph.Algorithms.Search +{ + [Serializable] + public sealed class UndirectedEdgeDepthFirstSearchAlgorithm : + RootedAlgorithmBase>, + IEdgeColorizerAlgorithm, + IEdgePredecessorRecorderAlgorithm, + ITreeBuilderAlgorithm + where Edge : IEdge + { + private IDictionary colors; + private int maxDepth = int.MaxValue; + + public UndirectedEdgeDepthFirstSearchAlgorithm(IUndirectedGraph g) + :this(g, new Dictionary()) + { + } + + public UndirectedEdgeDepthFirstSearchAlgorithm( + IUndirectedGraph visitedGraph, + IDictionary colors + ) + :base(visitedGraph) + { + if (colors == null) + throw new ArgumentNullException("VertexColors"); + + this.colors = colors; + } + + public IDictionary EdgeColors + { + get + { + return this.colors; + } + } + + public int MaxDepth + { + get + { + return this.maxDepth; + } + set + { + this.maxDepth = value; + } + } + + public event EdgeEventHandler InitializeEdge; + private void OnInitializeEdge(Edge e) + { + if (InitializeEdge != null) + InitializeEdge(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(Vertex v) + { + if (StartVertex != null) + StartVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler StartEdge; + private void OnStartEdge(Edge e) + { + if (StartEdge != null) + StartEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEdgeEventHandler DiscoverTreeEdge; + private void OnDiscoverTreeEdge(Edge e, Edge targetEge) + { + if (DiscoverTreeEdge != null) + DiscoverTreeEdge(this, new EdgeEdgeEventArgs(e, targetEge)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(Edge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(Edge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler BackEdge; + private void OnBackEdge(Edge e) + { + if (BackEdge != null) + BackEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler ForwardOrCrossEdge; + private void OnForwardOrCrossEdge(Edge e) + { + if (ForwardOrCrossEdge != null) + ForwardOrCrossEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler FinishEdge; + private void OnFinishEdge(Edge e) + { + if (FinishEdge != null) + FinishEdge(this, new EdgeEventArgs(e)); + } + + protected override void InternalCompute() + { + Initialize(); + + // start whith him: + if (this.RootVertex != null) + { + OnStartVertex(this.RootVertex); + + // process each out edge of v + foreach (Edge e in VisitedGraph.OutEdges(this.RootVertex)) + { + if (EdgeColors[e] == GraphColor.White) + { + OnStartEdge(e); + Visit(e, 0); + } + } + } + + // process the rest of the graph edges + foreach (Edge e in VisitedGraph.Edges) + { + if (EdgeColors[e] == GraphColor.White) + { + OnStartEdge(e); + Visit(e, 0); + } + } + } + + public void Initialize() + { + // put all vertex to white + foreach (Edge e in VisitedGraph.Edges) + { + EdgeColors[e] = GraphColor.White; + OnInitializeEdge(e); + } + } + + public void Visit(Edge se, int depth) + { + if (depth > this.maxDepth) + return; + + // mark edge as gray + EdgeColors[se] = GraphColor.Gray; + // add edge to the search tree + OnTreeEdge(se); + + VisitEdges(this.VisitedGraph.AdjacentEdges(se.Target), depth); + VisitEdges(this.VisitedGraph.AdjacentEdges(se.Source), depth); + + // all edges have been explored + EdgeColors[se] = GraphColor.Black; + OnFinishEdge(se); + } + + private void VisitEdges(IEnumerable edges, int depth) + { + // iterate over out-edges + foreach (Edge e in edges) + { + // check edge is not explored yet, + // if not, explore it. + if (EdgeColors[e] == GraphColor.White) + { + OnDiscoverTreeEdge(se, e); + Visit(e, depth + 1); + } + else if (EdgeColors[e] == GraphColor.Gray) + { + // edge is being explored + OnBackEdge(e); + } + else + // edge is black + OnForwardOrCrossEdge(e); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs.meta new file mode 100644 index 0000000..6247395 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Search/UndirectedEdgeDepthFirstSearchAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1d7346abd9b3c40b28259b59f6c1a4a2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services.meta new file mode 100644 index 0000000..4a62221 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 1d2b81998c7b7457d81c33068c77273d +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs new file mode 100755 index 0000000..d12b264 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms.Services +{ + public interface IAlgorithmComponent + { + IAlgorithmServices Services { get; } + T GetService() where T : IService; + bool TryGetService(out T service) where T : IService; + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs.meta new file mode 100644 index 0000000..594bf01 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmComponent.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 53f514da00e8242afbc962e8ea5619c4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs new file mode 100755 index 0000000..ac1ba61 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms.Services +{ + /// + /// Common services available to algorithm instances + /// + public interface IAlgorithmServices + { + ICancelManager CancelManager { get; } + } + + class AlgorithmServices : + IAlgorithmServices + { + readonly IAlgorithmComponent host; + + public AlgorithmServices(IAlgorithmComponent host) + { + GraphContracts.AssumeNotNull(host, "host"); + this.host = host; + } + + ICancelManager _cancelManager; + public ICancelManager CancelManager + { + get + { + if (this._cancelManager == null) + this._cancelManager = this.host.GetService(); + return this._cancelManager; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs.meta new file mode 100644 index 0000000..a9f6be0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IAlgorithmServices.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8035ff247184445a2966d51187522fa4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs new file mode 100755 index 0000000..8745af6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace QuickGraph.Algorithms.Services +{ + public interface ICancelManager : + IService + { + /// + /// Raised when the cancel method is called + /// + event EventHandler CancelRequested; + + /// + /// Requests the component to cancel its computation + /// + void Cancel(); + + /// + /// Gets a value indicating if a cancellation request is pending. + /// + /// + bool IsCancelling { get; } + + /// + /// Raised when the cancel state has been reseted + /// + event EventHandler CancelReseted; + + /// + /// Resets the cancel state + /// + void ResetCancel(); + } + + class CancelManager : + ICancelManager + { + private int cancelling; + + public event EventHandler CancelRequested; + + public void Cancel() + { + var value = Interlocked.Increment(ref this.cancelling); + if (value == 0) + { + var eh = this.CancelRequested; + if (eh != null) + eh(this, EventArgs.Empty); + } + } + + public bool IsCancelling + { + get { return this.cancelling > 0; } + } + + /// + /// Raised when the cancel state has been reseted + /// + public event EventHandler CancelReseted; + + /// + /// Resets the cancel state + /// + public void ResetCancel() + { + var value = Interlocked.Exchange(ref this.cancelling, 0); + if (value != 0) + { + var eh = this.CancelReseted; + if (eh != null) + eh(this, EventArgs.Empty); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs.meta new file mode 100644 index 0000000..72975b3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/ICancelManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 93563a09f6cc540399bc2adc9258cf06 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs new file mode 100755 index 0000000..6d1a768 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs @@ -0,0 +1,5 @@ +namespace QuickGraph.Algorithms.Services +{ + public interface IService + {} +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs.meta new file mode 100644 index 0000000..4170674 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/Services/IService.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 304e4d366974b41c2ac95d18632caa1e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath.meta new file mode 100644 index 0000000..d6e7ef3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 8531232cc5c094baa9507f840b925cd0 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs new file mode 100755 index 0000000..93a975c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.ShortestPath +{ + /// + /// Bellman Ford shortest path algorithm. + /// + /// + /// + /// The Bellman-Ford algorithm solves the single-source shortest paths + /// problem for a graph with both positive and negative edge weights. + /// + /// + /// If you only need to solve the shortest paths problem for positive + /// edge weights, Dijkstra's algorithm provides a more efficient + /// alternative. + /// + /// + /// If all the edge weights are all equal to one then breadth-first search + /// provides an even more efficient alternative. + /// + /// + /// + public sealed class BellmanFordShortestPathAlgorithm : + ShortestPathAlgorithmBase>, + ITreeBuilderAlgorithm + where TEdge : IEdge + { + private readonly Dictionary predecessors; + private bool foundNegativeCycle; + + public BellmanFordShortestPathAlgorithm( + IVertexAndEdgeListGraph visitedGraph, + IDictionary weights + ) + : this(visitedGraph, weights, new ShortestDistanceRelaxer()) + { } + + public BellmanFordShortestPathAlgorithm( + IVertexAndEdgeListGraph visitedGraph, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + : this(null, visitedGraph, weights, distanceRelaxer) + { } + + public BellmanFordShortestPathAlgorithm( + IAlgorithmComponent host, + IVertexAndEdgeListGraph visitedGraph, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + :base(host, visitedGraph, weights, distanceRelaxer) + { + this.predecessors = new Dictionary(); + } + + public bool FoundNegativeCycle + { + get { return this.foundNegativeCycle;} + } + + /// + /// Invoked on each vertex in the graph before the start of the + /// algorithm. + /// + public event VertexEventHandler InitializeVertex; + + /// + /// Raises the event. + /// + /// vertex that raised the event + private void OnInitializeVertex(TVertex v) + { + if (InitializeVertex != null) + InitializeVertex(this, new VertexEventArgs(v)); + } + + /// + /// Invoked on every edge in the graph |V| times. + /// + public event EdgeEventHandler ExamineEdge; + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked when the distance label for the target vertex is decreased. + /// The edge that participated in the last relaxation for vertex v is + /// an edge in the shortest paths tree. + /// + public event EdgeEventHandler TreeEdge; + + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked if the distance label for the target vertex is not + /// decreased. + /// + public event EdgeEventHandler EdgeNotRelaxed; + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnEdgeNotRelaxed(TEdge e) + { + if (EdgeNotRelaxed != null) + EdgeNotRelaxed(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked during the second stage of the algorithm, + /// during the test of whether each edge was minimized. + /// + /// If the edge is minimized then this function is invoked. + /// + public event EdgeEventHandler EdgeMinimized; + + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnEdgeMinimized(TEdge e) + { + if (EdgeMinimized != null) + EdgeMinimized(this, new EdgeEventArgs(e)); + } + + /// + /// Invoked during the second stage of the algorithm, + /// during the test of whether each edge was minimized. + /// + /// If the edge was not minimized, this function is invoked. + /// This happens when there is a negative cycle in the graph. + /// + public event EdgeEventHandler EdgeNotMinimized; + + + /// + /// Raises the event. + /// + /// edge that raised the event + private void OnEdgeNotMinimized(TEdge e) + { + if (EdgeNotMinimized != null) + EdgeNotMinimized(this, new EdgeEventArgs(e)); + } + + /// + /// Constructed predecessor map + /// + public IDictionary Predecessors + { + get + { + return predecessors; + } + } + + private void Initialize() + { + this.foundNegativeCycle = false; + // init color, distance + foreach (var u in VisitedGraph.Vertices) + { + VertexColors[u] = GraphColor.White; + Distances[u] = double.PositiveInfinity; + OnInitializeVertex(u); + } + } + + /// + /// Applies the Bellman Ford algorithm + /// + /// + /// Does not initialize the predecessor and distance map. + /// + /// true if successful, false if there was a negative cycle. + protected override void InternalCompute() + { + this.Initialize(); + + // getting the number of + int N = this.VisitedGraph.VertexCount; + for (int k = 0; k < N; ++k) + { + bool atLeastOneTreeEdge = false; + foreach (var e in this.VisitedGraph.Edges) + { + OnExamineEdge(e); + + if (Relax(e)) + { + atLeastOneTreeEdge = true; + OnTreeEdge(e); + } + else + OnEdgeNotRelaxed(e); + } + if (!atLeastOneTreeEdge) + break; + } + + foreach (var e in VisitedGraph.Edges) + { + if ( + Compare( + Combine( + Distances[e.Source], Weights[e]), + Distances[e.Target] + ) + ) + { + OnEdgeMinimized(e); + this.foundNegativeCycle = true; + return; + } + else + OnEdgeNotMinimized(e); + } + this.foundNegativeCycle = false; + } + + private bool Relax(TEdge e) + { + double du = this.Distances[e.Source]; + double dv = this.Distances[e.Target]; + double we = this.Weights[e]; + + if (Compare(Combine(du, we), dv)) + { + this.Distances[e.Target] = Combine(du, we); + return true; + } + else + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs.meta new file mode 100644 index 0000000..5cf78e6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a86f0011a084540a99326f8db8c469eb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs new file mode 100755 index 0000000..03e675d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms.ShortestPath +{ + public sealed class CriticalDistanceRelaxer : + IDistanceRelaxer + { + public double InitialDistance + { + get { return double.MinValue; } + } + + public bool Compare(double a, double b) + { + return a > b; + } + + public double Combine(double distance, double weight) + { + return distance + weight; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs.meta new file mode 100644 index 0000000..8fa4704 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/CriticalDistanceRelaxer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: be454f5cf6b6a448aa7c24fb8c5bd8e6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs new file mode 100755 index 0000000..33bf131 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.ShortestPath +{ + /// + /// A single-source shortest path algorithm for directed acyclic + /// graph. + /// + /// + /// + /// + [Serializable] + public sealed class DagShortestPathAlgorithm : + ShortestPathAlgorithmBase>, + IVertexColorizerAlgorithm, + ITreeBuilderAlgorithm, + IDistanceRecorderAlgorithm, + IVertexPredecessorRecorderAlgorithm + where TEdge : IEdge + { + public DagShortestPathAlgorithm( + IVertexListGraph g, + IDictionary weights + ) + : this(g, weights, new ShortestDistanceRelaxer()) + { } + + public DagShortestPathAlgorithm( + IVertexListGraph g, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + : this(null, g, weights, distanceRelaxer) + { } + + public DagShortestPathAlgorithm( + IAlgorithmComponent host, + IVertexListGraph g, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + :base(host, g,weights, distanceRelaxer) + {} + + public event VertexEventHandler InitializeVertex; + private void OnInitializeVertex(TVertex v) + { + if (InitializeVertex != null) + InitializeVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler StartVertex; + private void OnStartVertex(TVertex v) + { + VertexEventHandler eh = this.StartVertex; + if (eh!=null) + eh(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler DiscoverVertex; + private void OnDiscoverVertex(TVertex v) + { + if (DiscoverVertex != null) + DiscoverVertex(this, new VertexEventArgs(v)); + } + + public event VertexEventHandler ExamineVertex; + private void OnExamineVertex(TVertex v) + { + if (ExamineVertex != null) + ExamineVertex(this, new VertexEventArgs(v)); + } + + public event EdgeEventHandler ExamineEdge; + private void OnExamineEdge(TEdge e) + { + if (ExamineEdge != null) + ExamineEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + + public event EdgeEventHandler EdgeNotRelaxed; + private void OnEdgeNotRelaxed(TEdge e) + { + if (EdgeNotRelaxed != null) + EdgeNotRelaxed(this, new EdgeEventArgs(e)); + } + + public event VertexEventHandler FinishVertex; + private void OnFinishVertex(TVertex v) + { + if (FinishVertex != null) + FinishVertex(this, new VertexEventArgs(v)); + } + + public void Initialize() + { + this.VertexColors.Clear(); + this.Distances.Clear(); + + // init color, distance + var initialDistance = this.DistanceRelaxer.InitialDistance; + foreach (var u in VisitedGraph.Vertices) + { + this.VertexColors.Add(u, GraphColor.White); + this.Distances.Add(u, initialDistance); + this.OnInitializeVertex(u); + } + } + + protected override void InternalCompute() + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + throw new InvalidOperationException("RootVertex not initialized"); + + this.Initialize(); + VertexColors[rootVertex] = GraphColor.Gray; + Distances[rootVertex] = 0; + ComputeNoInit(rootVertex); + } + + public void ComputeNoInit(TVertex s) + { + ICollection orderedVertices = AlgoUtility.TopologicalSort(this.VisitedGraph); + + OnDiscoverVertex(s); + foreach (var v in orderedVertices) + { + OnExamineVertex(v); + foreach (var e in VisitedGraph.OutEdges(v)) + { + OnDiscoverVertex(e.Target); + bool decreased = Relax(e); + if (decreased) + OnTreeEdge(e); + else + OnEdgeNotRelaxed(e); + } + OnFinishVertex(v); + } + } + + private bool Relax(TEdge e) + { + double du = this.Distances[e.Source]; + double dv = this.Distances[e.Target]; + double we = this.Weights[e]; + + if (Compare(Combine(du, we), dv)) + { + Distances[e.Target] = Combine(du, we); + return true; + } + else + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs.meta new file mode 100644 index 0000000..f9a8d82 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DagShortestPathAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6a5aa9be625fd4efaa1849410648105e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs new file mode 100755 index 0000000..424ef32 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Collections; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.ShortestPath +{ + /// + /// A single-source shortest path algorithm for directed graph + /// with positive distance. + /// + /// + /// + /// + [Serializable] + public sealed class DijkstraShortestPathAlgorithm : + ShortestPathAlgorithmBase>, + IVertexColorizerAlgorithm, + IVertexPredecessorRecorderAlgorithm, + IDistanceRecorderAlgorithm + where TEdge : IEdge + { + private PriorityQueue vertexQueue; + + public DijkstraShortestPathAlgorithm( + IVertexListGraph visitedGraph, + IDictionary weights) + : this(visitedGraph, weights, new ShortestDistanceRelaxer()) + { } + + public DijkstraShortestPathAlgorithm( + IVertexListGraph visitedGraph, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + : this(null, visitedGraph, weights, distanceRelaxer) + { } + + public DijkstraShortestPathAlgorithm( + IAlgorithmComponent host, + IVertexListGraph visitedGraph, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + :base(host, visitedGraph,weights, distanceRelaxer) + { } + + public event VertexEventHandler InitializeVertex; + public event VertexEventHandler DiscoverVertex; + public event VertexEventHandler StartVertex; + public event VertexEventHandler ExamineVertex; + public event EdgeEventHandler ExamineEdge; + public event VertexEventHandler FinishVertex; + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + public event EdgeEventHandler EdgeNotRelaxed; + private void OnEdgeNotRelaxed(TEdge e) + { + if (EdgeNotRelaxed != null) + EdgeNotRelaxed(this, new EdgeEventArgs(e)); + } + + private void InternalExamineEdge(Object sender, EdgeEventArgs args) + { + bool decreased = Relax(args.Edge); + if (decreased) + OnTreeEdge(args.Edge); + else + OnEdgeNotRelaxed(args.Edge); + } + + private void InternalGrayTarget(Object sender, EdgeEventArgs args) + { + bool decreased = Relax(args.Edge); + if (decreased) + { + this.vertexQueue.Update(args.Edge.Target); + OnTreeEdge(args.Edge); + } + else + { + OnEdgeNotRelaxed(args.Edge); + } + } + + public void Initialize() + { + this.VertexColors.Clear(); + this.Distances.Clear(); + // init color, distance + var initialDistance = this.DistanceRelaxer.InitialDistance; + foreach (var u in VisitedGraph.Vertices) + { + this.VertexColors.Add(u, GraphColor.White); + this.Distances.Add(u, initialDistance); + } + } + + protected override void InternalCompute() + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + throw new InvalidOperationException("RootVertex not initialized"); + + this.Initialize(); + this.VertexColors[rootVertex] = GraphColor.Gray; + this.Distances[rootVertex] = 0; + ComputeNoInit(rootVertex); + } + + public void ComputeNoInit(TVertex s) + { + this.vertexQueue = new PriorityQueue(this.Distances); + + BreadthFirstSearchAlgorithm bfs = null; + + try + { + bfs = new BreadthFirstSearchAlgorithm( + this, + this.VisitedGraph, + this.vertexQueue, + VertexColors + ); + + bfs.InitializeVertex += this.InitializeVertex; + bfs.DiscoverVertex += this.DiscoverVertex; + bfs.StartVertex += this.StartVertex; + bfs.ExamineEdge += this.ExamineEdge; + bfs.ExamineVertex += this.ExamineVertex; + bfs.FinishVertex += this.FinishVertex; + + bfs.ExamineEdge += new EdgeEventHandler(this.InternalExamineEdge); + bfs.GrayTarget += new EdgeEventHandler(this.InternalGrayTarget); + + bfs.Visit(s); + } + finally + { + if (bfs != null) + { + bfs.InitializeVertex -= this.InitializeVertex; + bfs.DiscoverVertex -= this.DiscoverVertex; + bfs.StartVertex -= this.StartVertex; + bfs.ExamineEdge -= this.ExamineEdge; + bfs.ExamineVertex -= this.ExamineVertex; + bfs.FinishVertex -= this.FinishVertex; + + bfs.ExamineEdge -= new EdgeEventHandler(this.InternalExamineEdge); + bfs.GrayTarget -= new EdgeEventHandler(this.InternalGrayTarget); + } + } + } + + private bool Relax(TEdge e) + { + double du = this.Distances[e.Source]; + double dv = this.Distances[e.Target]; + double we = this.Weights[e]; + + var duwe = Combine(du, we); + if (Compare(duwe, dv)) + { + this.Distances[e.Target] = duwe; + return true; + } + else + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs.meta new file mode 100644 index 0000000..d1a5620 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/DijkstraShortestPathAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6b100c81667fc436f9b853a8a1448dea +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs new file mode 100755 index 0000000..2d85cbf --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms.ShortestPath +{ + public interface IDistanceRelaxer + { + double InitialDistance { get;} + bool Compare(double a, double b); + double Combine(double distance, double weight); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs.meta new file mode 100644 index 0000000..646b6ac --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/IDistanceRelaxer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6086e79a0dab64ba495d4a0de8f63133 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs new file mode 100755 index 0000000..dd3ae6a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Algorithms.ShortestPath +{ + public sealed class ShortestDistanceRelaxer : IDistanceRelaxer + { + public double InitialDistance + { + get { return double.MaxValue; } + } + + public bool Compare(double a, double b) + { + return a < b; + } + + public double Combine(double distance, double weight) + { + return distance + weight; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs.meta new file mode 100644 index 0000000..070bccb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestDistanceRelaxer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 92f9915f920b94c9a8f493553ea600b1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs new file mode 100755 index 0000000..530da7b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Collections; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.ShortestPath +{ + [Serializable] + public abstract class ShortestPathAlgorithmBase : + RootedAlgorithmBase + where TEdge : IEdge + { + private readonly IDictionary vertexColors; + private readonly IDictionary distances; + private readonly IDictionary weights; + private readonly IDistanceRelaxer distanceRelaxer; + + protected ShortestPathAlgorithmBase( + IAlgorithmComponent host, + TGraph visitedGraph, + IDictionary weights + ) + :this(host, visitedGraph, weights, new ShortestDistanceRelaxer()) + {} + + protected ShortestPathAlgorithmBase( + IAlgorithmComponent host, + TGraph visitedGraph, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + :base(host, visitedGraph) + { + if (weights == null) + throw new ArgumentNullException("weights"); + if (distanceRelaxer == null) + throw new ArgumentNullException("distanceRelaxer"); + + this.vertexColors = new Dictionary(); + this.distances = new Dictionary(); + this.weights = weights; + this.distanceRelaxer = distanceRelaxer; + } + + public static Dictionary UnaryWeightsFromEdgeList( + IEdgeSet graph) + { + if (graph == null) + throw new ArgumentNullException("graph"); + Dictionary weights = new Dictionary(); + foreach (var e in graph.Edges) + weights.Add(e, 1); + return weights; + } + + public static Dictionary UnaryWeightsFromVertexList( + IVertexListGraph graph) + { + if (graph == null) + throw new ArgumentNullException("graph"); + var weights = new Dictionary(graph.VertexCount * 2); + foreach (var v in graph.Vertices) + foreach (var e in graph.OutEdges(v)) + weights.Add(e, 1); + return weights; + } + + public IDictionary VertexColors + { + get + { + return this.vertexColors; + } + } + + public IDictionary Distances + { + get + { + return this.distances; + } + } + + public IDictionary Weights + { + get { return this.weights; } + } + + public IDistanceRelaxer DistanceRelaxer + { + get { return this.distanceRelaxer; } + } + + protected bool Compare(double a, double b) + { + return this.distanceRelaxer.Compare(a, b); + } + + protected double Combine(double distance, double weight) + { + return this.distanceRelaxer.Combine(distance, weight); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs.meta new file mode 100644 index 0000000..51718be --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/ShortestPathAlgorithmBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b985078fdf0e54800bf4aa68e986b9ef +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs new file mode 100755 index 0000000..b909344 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Collections; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms.ShortestPath +{ + /// + /// A single-source shortest path algorithm for undirected graph + /// with positive distance. + /// + /// + [Serializable] + public sealed class UndirectedDijkstraShortestPathAlgorithm : + ShortestPathAlgorithmBase>, + IVertexColorizerAlgorithm, + IVertexPredecessorRecorderAlgorithm, + IDistanceRecorderAlgorithm + where TEdge : IEdge + { + private PriorityQueue vertexQueue; + + public UndirectedDijkstraShortestPathAlgorithm( + IUndirectedGraph visitedGraph, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + : this(null, visitedGraph, weights, distanceRelaxer) + { } + + public UndirectedDijkstraShortestPathAlgorithm( + IAlgorithmComponent host, + IUndirectedGraph visitedGraph, + IDictionary weights, + IDistanceRelaxer distanceRelaxer + ) + : base(host, visitedGraph, weights, distanceRelaxer) + { } + + public event VertexEventHandler InitializeVertex; + public event VertexEventHandler StartVertex; + public event VertexEventHandler DiscoverVertex; + public event VertexEventHandler ExamineVertex; + public event EdgeEventHandler ExamineEdge; + public event VertexEventHandler FinishVertex; + + public event EdgeEventHandler TreeEdge; + private void OnTreeEdge(TEdge e) + { + if (TreeEdge != null) + TreeEdge(this, new EdgeEventArgs(e)); + } + public event EdgeEventHandler EdgeNotRelaxed; + private void OnEdgeNotRelaxed(TEdge e) + { + if (EdgeNotRelaxed != null) + EdgeNotRelaxed(this, new EdgeEventArgs(e)); + } + + private void InternalTreeEdge(Object sender, EdgeEventArgs args) + { + bool decreased = Relax(args.Edge); + if (decreased) + OnTreeEdge(args.Edge); + else + OnEdgeNotRelaxed(args.Edge); + } + + private void InternalGrayTarget(Object sender, EdgeEventArgs args) + { + bool decreased = Relax(args.Edge); + if (decreased) + { + this.vertexQueue.Update(args.Edge.Target); + OnTreeEdge(args.Edge); + } + else + { + OnEdgeNotRelaxed(args.Edge); + } + } + + public void Initialize() + { + this.VertexColors.Clear(); + this.Distances.Clear(); + // init color, distance + foreach (var u in VisitedGraph.Vertices) + { + this.VertexColors.Add(u, GraphColor.White); + this.Distances.Add(u, double.MaxValue); + } + } + + protected override void InternalCompute() + { + TVertex rootVertex; + if (!this.TryGetRootVertex(out rootVertex)) + throw new InvalidOperationException("RootVertex not initialized"); + + this.Initialize(); + this.VertexColors[rootVertex] = GraphColor.Gray; + this.Distances[rootVertex] = 0; + ComputeNoInit(rootVertex); + } + + public void ComputeNoInit(TVertex s) + { + this.vertexQueue = new PriorityQueue(this.Distances); + UndirectedBreadthFirstSearchAlgorithm bfs = null; + + try + { + bfs = new UndirectedBreadthFirstSearchAlgorithm( + this, + this.VisitedGraph, + this.vertexQueue, + VertexColors + ); + + bfs.InitializeVertex += this.InitializeVertex; + bfs.DiscoverVertex += this.DiscoverVertex; + bfs.StartVertex += this.StartVertex; + bfs.ExamineEdge += this.ExamineEdge; + bfs.ExamineVertex += this.ExamineVertex; + bfs.FinishVertex += this.FinishVertex; + + bfs.TreeEdge += new EdgeEventHandler(this.InternalTreeEdge); + bfs.GrayTarget += new EdgeEventHandler(this.InternalGrayTarget); + + bfs.Visit(s); + } + finally + { + if (bfs != null) + { + bfs.InitializeVertex -= this.InitializeVertex; + bfs.DiscoverVertex -= this.DiscoverVertex; + bfs.StartVertex -= this.StartVertex; + bfs.ExamineEdge -= this.ExamineEdge; + bfs.ExamineVertex -= this.ExamineVertex; + bfs.FinishVertex -= this.FinishVertex; + + bfs.TreeEdge -= new EdgeEventHandler(this.InternalTreeEdge); + bfs.GrayTarget -= new EdgeEventHandler(this.InternalGrayTarget); + } + } + } + + private bool Relax(TEdge e) + { + double du = this.Distances[e.Source]; + double dv = this.Distances[e.Target]; + double we = this.Weights[e]; + + if (Compare(Combine(du, we), dv)) + { + this.Distances[e.Target] = Combine(du, we); + return true; + } + else + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs.meta new file mode 100644 index 0000000..d324046 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/ShortestPath/UndirectedDijkstraShortestPathAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa738fc0006474037b648717509e29f0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs new file mode 100755 index 0000000..40db589 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Collections; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class SourceFirstTopologicalSortAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private IDictionary inDegrees = new Dictionary(); + private PriorityQueue heap; + private IList sortedVertices = new List(); + + public SourceFirstTopologicalSortAlgorithm( + IVertexAndEdgeListGraph visitedGraph + ) + :base(visitedGraph) + { + this.heap = new PriorityQueue(this.inDegrees); + } + + public ICollection SortedVertices + { + get + { + return this.sortedVertices; + } + } + + public PriorityQueue Heap + { + get + { + return this.heap; + } + } + + public IDictionary InDegrees + { + get + { + return this.inDegrees; + } + } + + public event VertexEventHandler AddVertex; + private void OnAddVertex(TVertex v) + { + if (this.AddVertex != null) + this.AddVertex(this, new VertexEventArgs(v)); + } + + public void Compute(IList vertices) + { + if (vertices == null) + throw new ArgumentNullException("vertices"); + this.sortedVertices = vertices; + Compute(); + } + + + protected override void InternalCompute() + { + var cancelManager = this.Services.CancelManager; + this.InitializeInDegrees(); + + while (this.heap.Count != 0) + { + if (cancelManager.IsCancelling) break; + + TVertex v = this.heap.Dequeue(); + if (this.inDegrees[v] != 0) + throw new NonAcyclicGraphException(); + + this.sortedVertices.Add(v); + this.OnAddVertex(v); + + // update the count of it's adjacent vertices + foreach (var e in this.VisitedGraph.OutEdges(v)) + { + if (e.Source.Equals(e.Target)) + continue; + + this.inDegrees[e.Target]--; + if (this.inDegrees[e.Target] < 0) + throw new InvalidOperationException("InDegree is negative, and cannot be"); + this.heap.Update(e.Target); + } + } + } + + private void InitializeInDegrees() + { + foreach (var v in this.VisitedGraph.Vertices) + { + this.inDegrees.Add(v, 0); + this.heap.Enqueue(v); + } + + foreach (var e in this.VisitedGraph.Edges) + { + if (e.Source.Equals(e.Target)) + continue; + this.inDegrees[e.Target]++; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs.meta new file mode 100644 index 0000000..f095ecc --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/SourceFirstTopologicalSortAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 56eb53e40c8064e55999b2655087cc2a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs new file mode 100755 index 0000000..3cdd264 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class StronglyConnectedComponentsAlgorithm : + AlgorithmBase>, + IConnectedComponentAlgorithm> + where TEdge : IEdge + { + private IDictionary components; + private IDictionary discoverTimes; + private IDictionary roots; + private Stack stack; + int componentCount; + int dfsTime; + + public StronglyConnectedComponentsAlgorithm( + IVertexListGraph g) + :this(g, new Dictionary()) + {} + + public StronglyConnectedComponentsAlgorithm( + IVertexListGraph g, + IDictionary components) + : this(null, g, components) + { } + + public StronglyConnectedComponentsAlgorithm( + IAlgorithmComponent host, + IVertexListGraph g, + IDictionary components) + :base(host, g) + { + if (components==null) + throw new ArgumentNullException("components"); + + this.components = components; + this.roots = new Dictionary(); + this.discoverTimes = new Dictionary(); + this.stack = new Stack(); + this.componentCount = 0; + this.dfsTime = 0; + } + + public IDictionary Components + { + get + { + return this.components; + } + } + + public IDictionary Roots + { + get + { + return this.roots; + } + } + + public IDictionary DiscoverTimes + { + get + { + return this.discoverTimes; + } + } + + public int ComponentCount + { + get + { + return this.componentCount; + } + } + + private void DiscoverVertex(Object sender, VertexEventArgs args) + { + TVertex v = args.Vertex; + this.Roots[v]=v; + this.Components[v]=int.MaxValue; + this.DiscoverTimes[v]=dfsTime++; + this.stack.Push(v); + } + + /// + /// Used internally + /// + /// + /// + private void FinishVertex(Object sender, VertexEventArgs args) + { + TVertex v = args.Vertex; + foreach(TEdge e in VisitedGraph.OutEdges(v)) + { + TVertex w = e.Target; + if (this.Components[w] == int.MaxValue) + this.Roots[v]=MinDiscoverTime(this.Roots[v], this.Roots[w]); + } + + if (Roots[v].Equals(v)) + { + TVertex w=default(TVertex); + do + { + w = this.stack.Pop(); + this.Components[w]=componentCount; + } + while (!w.Equals(v)); + ++componentCount; + } + } + + private TVertex MinDiscoverTime(TVertex u, TVertex v) + { + if (this.DiscoverTimes[u] dfs = null; + try + { + dfs = new DepthFirstSearchAlgorithm( + this, + VisitedGraph, + new Dictionary(this.VisitedGraph.VertexCount) + ); + dfs.DiscoverVertex += new VertexEventHandler(this.DiscoverVertex); + dfs.FinishVertex += new VertexEventHandler(this.FinishVertex); + + dfs.Compute(); + } + finally + { + if (dfs != null) + { + dfs.DiscoverVertex -= new VertexEventHandler(this.DiscoverVertex); + dfs.FinishVertex -= new VertexEventHandler(this.FinishVertex); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs.meta new file mode 100644 index 0000000..645c37f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/StronglyConnectedComponentAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e8a2ab939a215468eb517077a0987fb1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs new file mode 100755 index 0000000..40da7a8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.Search; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class TopologicalSortAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private IList vertices = new List(); + private bool allowCyclicGraph = false; + + public TopologicalSortAlgorithm(IVertexListGraph g) + :this(g, new List()) + {} + + public TopologicalSortAlgorithm( + IVertexListGraph g, + IList vertices) + :base(g) + { + if (vertices == null) + throw new ArgumentNullException("vertices"); + + this.vertices = vertices; + } + + public IList SortedVertices + { + get + { + return vertices; + } + } + + public bool AllowCyclicGraph + { + get { return this.allowCyclicGraph; } + } + + private void BackEdge(Object sender, EdgeEventArgs args) + { + if (!this.AllowCyclicGraph) + throw new NonAcyclicGraphException(); + } + + private void FinishVertex(Object sender, VertexEventArgs args) + { + vertices.Insert(0, args.Vertex); + } + + protected override void InternalCompute() + { + DepthFirstSearchAlgorithm dfs = null; + try + { + dfs = new DepthFirstSearchAlgorithm( + this, + this.VisitedGraph, + new Dictionary(this.VisitedGraph.VertexCount) + ); + dfs.BackEdge += new EdgeEventHandler(this.BackEdge); + dfs.FinishVertex += new VertexEventHandler(this.FinishVertex); + + dfs.Compute(); + } + finally + { + if (dfs != null) + { + dfs.BackEdge -= new EdgeEventHandler(this.BackEdge); + dfs.FinishVertex -= new VertexEventHandler(this.FinishVertex); + } + } + } + + public void Compute(IList vertices) + { + this.vertices = vertices; + this.vertices.Clear(); + this.Compute(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs.meta new file mode 100644 index 0000000..46c93ad --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/TopologicalSortAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 142b010b546f54ba79dd80fb7f79426e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs new file mode 100755 index 0000000..689b79a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Collections; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class UndirectedFirstTopologicalSortAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private IDictionary degrees = new Dictionary(); + private PriorityQueue heap; + private IList sortedVertices = new List(); + private bool allowCyclicGraph = false; + + public UndirectedFirstTopologicalSortAlgorithm( + IUndirectedGraph visitedGraph + ) + : base(visitedGraph) + { + this.heap = new PriorityQueue(this.degrees); + } + + public ICollection SortedVertices + { + get + { + return this.sortedVertices; + } + } + + public PriorityQueue Heap + { + get + { + return this.heap; + } + } + + public IDictionary Degrees + { + get + { + return this.degrees; + } + } + + + public bool AllowCyclicGraph + { + get { return this.allowCyclicGraph; } + set { this.allowCyclicGraph = value; } + } + + public event VertexEventHandler AddVertex; + private void OnAddVertex(TVertex v) + { + if (this.AddVertex != null) + this.AddVertex(this, new VertexEventArgs(v)); + } + + public void Compute(IList vertices) + { + if (vertices == null) + throw new ArgumentNullException("vertices"); + this.sortedVertices = vertices; + Compute(); + } + + + protected override void InternalCompute() + { + this.InitializeInDegrees(); + var cancelManager = this.Services.CancelManager; + + while (this.heap.Count != 0) + { + if (cancelManager.IsCancelling) return; + + TVertex v = this.heap.Dequeue(); + if (this.degrees[v] != 0 && !this.AllowCyclicGraph) + throw new NonAcyclicGraphException(); + + this.sortedVertices.Add(v); + this.OnAddVertex(v); + + // update the count of it's adjacent vertices + foreach (var e in this.VisitedGraph.AdjacentEdges(v)) + { + if (e.Source.Equals(e.Target)) + continue; + + this.degrees[e.Target]--; + if (this.degrees[e.Target] < 0 && !this.AllowCyclicGraph) + throw new InvalidOperationException("Degree is negative, and cannot be"); + if (this.heap.Contains(e.Target)) + this.heap.Update(e.Target); + } + } + } + + private void InitializeInDegrees() + { + foreach (var v in this.VisitedGraph.Vertices) + { + this.degrees.Add(v, this.VisitedGraph.AdjacentDegree(v)); + this.heap.Enqueue(v); + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs.meta new file mode 100644 index 0000000..90c6ed6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedFirstTopologicalSortAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a1988ee62705c48fab563bc866cd3efb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs new file mode 100755 index 0000000..6e72e6b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; + +using QuickGraph.Algorithms.Search; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class UndirectedTopologicalSortAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private IList vertices; + private bool allowCyclicGraph = false; + + public UndirectedTopologicalSortAlgorithm(IUndirectedGraph g) + : this(g, new List()) + { } + + public UndirectedTopologicalSortAlgorithm( + IUndirectedGraph g, + IList vertices) + : base(g) + { + if (vertices == null) + throw new ArgumentNullException("vertices"); + + this.vertices = vertices; + } + + public IList SortedVertices + { + get + { + return vertices; + } + } + + public bool AllowCyclicGraph + { + get { return this.allowCyclicGraph; } + set { this.allowCyclicGraph = value; } + } + + private void BackEdge(Object sender, EdgeEventArgs args) + { + if (!this.AllowCyclicGraph) + throw new NonAcyclicGraphException(); + } + + private void FinishVertex(Object sender, VertexEventArgs args) + { + vertices.Insert(0, args.Vertex); + } + + protected override void InternalCompute() + { + UndirectedDepthFirstSearchAlgorithm dfs = null; + try + { + dfs = new UndirectedDepthFirstSearchAlgorithm( + this, + VisitedGraph, + new Dictionary(this.VisitedGraph.VertexCount) + ); + dfs.BackEdge += new EdgeEventHandler(this.BackEdge); + dfs.FinishVertex += new VertexEventHandler(this.FinishVertex); + + dfs.Compute(); + } + finally + { + if (dfs != null) + { + dfs.BackEdge -= new EdgeEventHandler(this.BackEdge); + dfs.FinishVertex -= new VertexEventHandler(this.FinishVertex); + } + } + } + + public void Compute(IList vertices) + { + this.vertices = vertices; + this.vertices.Clear(); + this.Compute(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs.meta new file mode 100644 index 0000000..edaadd1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/UndirectedTopologicalSortAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 991d3d3c990234bd695e6b7042604f06 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs new file mode 100755 index 0000000..0ecd17c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; +using QuickGraph.Algorithms.Matrix; + +namespace QuickGraph.Algorithms +{ + public sealed class VertexAdjacencyMatrixBuilderAlgorithm : + AlgorithmBase> + where TEdge : IEdge + { + private DoubleDenseMatrix matrix; + private Dictionary vertexIndices; + + public VertexAdjacencyMatrixBuilderAlgorithm(IVertexListGraph visitedGraph) + :base(visitedGraph) + { + } + + public DoubleDenseMatrix Matrix + { + get { return this.matrix; } + } + + public Dictionary VertexIndices + { + get { return this.vertexIndices; } + } + + protected override void InternalCompute() + { + var cancelManager = this.Services.CancelManager; + this.matrix = new DoubleDenseMatrix(this.VisitedGraph.VertexCount, this.VisitedGraph.VertexCount); + this.vertexIndices = new Dictionary(this.VisitedGraph.VertexCount); + + int index = 0; + foreach (var v in this.VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) break; + + this.vertexIndices.Add(v, index++); + } + + foreach (var v in this.VisitedGraph.Vertices) + { + if (cancelManager.IsCancelling) break; + + int source = this.VertexIndices[v]; + foreach (var edge in this.VisitedGraph.OutEdges(v)) + { + int target = this.VertexIndices[edge.Target]; + + matrix[source, target] = 1; + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs.meta new file mode 100644 index 0000000..cda4415 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/VertexAdjacencyMatrixBuilderAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ae8d3406f51cc40d3a6900e69f9e6f0c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs new file mode 100755 index 0000000..0054015 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using QuickGraph.Algorithms.Search; +using QuickGraph.Algorithms.Observers; +using QuickGraph.Algorithms.Services; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public sealed class WeaklyConnectedComponentsAlgorithm : + AlgorithmBase>, + IConnectedComponentAlgorithm> + where TEdge : IEdge + { + private readonly IDictionary components; + private readonly Dictionary componentEquivalences = new Dictionary(); + private readonly DepthFirstSearchAlgorithm dfs; + private int componentCount = 0; + private int currentComponent = 0; + + public WeaklyConnectedComponentsAlgorithm(IVertexListGraph visitedGraph) + : this(visitedGraph, new Dictionary()) + { } + + public WeaklyConnectedComponentsAlgorithm( + IVertexListGraph visitedGraph, + IDictionary components) + : this(null, visitedGraph, components) + { } + + public WeaklyConnectedComponentsAlgorithm( + IAlgorithmComponent host, + IVertexListGraph visitedGraph, + IDictionary components) + : base(host, visitedGraph) + { + if (components == null) + throw new ArgumentNullException("components"); + this.components = components; + + this.dfs = new DepthFirstSearchAlgorithm(this.VisitedGraph); + this.dfs.StartVertex += new VertexEventHandler(dfs_StartVertex); + this.dfs.TreeEdge += new EdgeEventHandler(dfs_TreeEdge); + this.dfs.ForwardOrCrossEdge += new EdgeEventHandler(dfs_ForwardOrCrossEdge); + } + + public IDictionary Components + { + get { return this.components; } + } + + public int ComponentCount + { + get { return this.componentCount; } + } + + protected override void InternalCompute() + { + this.componentCount = 0; + this.currentComponent = 0; + this.componentEquivalences.Clear(); + this.components.Clear(); + this.dfs.Compute(); + + // updating component numbers + foreach (var v in this.VisitedGraph.Vertices) + { + int component = this.Components[v]; + int equivalent = this.componentEquivalences[component]; + if (component!=equivalent) + this.Components[v] =equivalent; + } + } + + void dfs_StartVertex(object sender, VertexEventArgs e) + { + // we are looking on a new tree + this.currentComponent = this.componentEquivalences.Count; + this.componentEquivalences.Add(this.currentComponent, this.currentComponent); + this.componentCount++; + this.components.Add(e.Vertex, this.currentComponent); + } + + void dfs_TreeEdge(object sender, EdgeEventArgs e) + { + // new edge, we store with the current component number + this.components.Add(e.Edge.Target, this.currentComponent); + } + + void dfs_ForwardOrCrossEdge(object sender, EdgeEventArgs e) + { + // we have touched another tree, updating count and current component + int otherComponent = this.componentEquivalences[this.components[e.Edge.Target]]; + if (otherComponent != this.currentComponent) + { + this.componentCount--; + this.componentEquivalences[this.currentComponent] = otherComponent; + this.currentComponent = otherComponent; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs.meta new file mode 100644 index 0000000..b3fdc6c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/WeaklyConnectedComponentsAlgorithm.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 59244c5d4d758437e98bfdca5dcc60b2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs new file mode 100755 index 0000000..e8855d4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs @@ -0,0 +1,24 @@ +using System; +using QuickGraph.Algorithms.Matrix; + +namespace QuickGraph.Algorithms +{ + [Serializable] + public class MatrixSizeMistmatchException : ApplicationException + { + public MatrixSizeMistmatchException( + DoubleDenseMatrix left, + DoubleDenseMatrix right) + :this(String.Format("Matrix size ({0}x{1}) does not match ({2}x{3})", + left.RowCount,left.ColumnCount,right.RowCount, right.ColumnCount)) + { + } + public MatrixSizeMistmatchException() { } + public MatrixSizeMistmatchException(string message) : base(message) { } + public MatrixSizeMistmatchException(string message, Exception inner) : base(message, inner) { } + protected MatrixSizeMistmatchException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs.meta new file mode 100644 index 0000000..5feff54 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Algorithms/matrixsizemistmatchexception.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 33a6ddd40300e47ad8dc70b99ecc407e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs new file mode 100755 index 0000000..33856a0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs @@ -0,0 +1,628 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace QuickGraph +{ + [Serializable] + public class BidirectionalGraph : + IVertexAndEdgeListGraph, + IEdgeListAndIncidenceGraph, + IMutableEdgeListGraph, + IMutableIncidenceGraph, + IMutableVertexListGraph, + IBidirectionalGraph, + IMutableBidirectionalGraph, + IMutableVertexAndEdgeListGraph, + ICloneable + where TEdge : IEdge + { + private readonly bool isDirected = true; + private readonly bool allowParallelEdges; + private readonly VertexEdgeDictionary vertexOutEdges + = new VertexEdgeDictionary(); + private readonly VertexEdgeDictionary vertexInEdges + = new VertexEdgeDictionary(); + private int edgeCount = 0; + private int edgeCapacity = -1; + + public BidirectionalGraph() + :this(true) + {} + + public BidirectionalGraph(bool allowParallelEdges) + :this(allowParallelEdges,-1) + {} + + public BidirectionalGraph(bool allowParallelEdges, int vertexCapacity) + { + this.allowParallelEdges = allowParallelEdges; + if (vertexCapacity > -1) + { + this.vertexInEdges = new VertexEdgeDictionary(vertexCapacity); + this.vertexOutEdges = new VertexEdgeDictionary(vertexCapacity); + } + else + { + this.vertexInEdges = new VertexEdgeDictionary(); + this.vertexOutEdges = new VertexEdgeDictionary(); + } + } + + public static Type VertexType + { + get { return typeof(TVertex); } + } + + public static Type EdgeType + { + get { return typeof(TEdge); } + } + + public int EdgeCapacity + { + get { return this.edgeCapacity; } + set { this.edgeCapacity = value; } + } + + public bool IsDirected + { + get { return this.isDirected; } + } + + public bool AllowParallelEdges + { + get { return this.allowParallelEdges; } + } + + public bool IsVerticesEmpty + { + get { return this.vertexOutEdges.Count == 0; } + } + + public int VertexCount + { + get { return this.vertexOutEdges.Count; } + } + + public IEnumerable Vertices + { + get { return this.vertexOutEdges.Keys; } + } + + public bool ContainsVertex(TVertex v) + { + GraphContracts.AssumeNotNull(v, "v"); + return this.vertexOutEdges.ContainsKey(v); + } + + public bool IsOutEdgesEmpty(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexOutEdges[v].Count == 0; + } + + public int OutDegree(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexOutEdges[v].Count; + } + + public IEnumerable OutEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexOutEdges[v]; + } + + public TEdge OutEdge(TVertex v, int index) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexOutEdges[v][index]; + } + + public bool IsInEdgesEmpty(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexInEdges[v].Count == 0; + } + + public int InDegree(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexInEdges[v].Count; + } + + public IEnumerable InEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexInEdges[v]; + } + + public TEdge InEdge(TVertex v, int index) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.vertexInEdges[v][index]; + } + + public int Degree(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.OutDegree(v) + this.InDegree(v); + } + + public bool IsEdgesEmpty + { + get { return this.edgeCount == 0; } + } + + public int EdgeCount + { + get + { + GraphContracts.Assert(this.edgeCount >= 0); + return this.edgeCount; + } + } + + public IEnumerable Edges + { + get + { + foreach (EdgeList edges in this.vertexOutEdges.Values) + foreach (var edge in edges) + yield return edge; + } + } + + public bool ContainsEdge(TVertex source, TVertex target) + { + GraphContracts.AssumeInVertexSet(this, source, "source"); + GraphContracts.AssumeInVertexSet(this, target, "target"); + foreach (var outEdge in this.OutEdges(source)) + if (outEdge.Target.Equals(target)) + return true; + return false; + } + + public bool TryGetEdge( + TVertex source, + TVertex target, + out TEdge edge) + { + GraphContracts.AssumeInVertexSet(this, source, "source"); + GraphContracts.AssumeInVertexSet(this, target, "target"); + + EdgeList edgeList; + if (this.vertexOutEdges.TryGetValue(source, out edgeList) && + edgeList.Count > 0) + { + foreach (var e in edgeList) + { + if (e.Target.Equals(target)) + { + edge = e; + return true; + } + } + } + edge = default(TEdge); + return false; + } + + public bool TryGetEdges( + TVertex source, + TVertex target, + out IEnumerable edges) + { + GraphContracts.AssumeInVertexSet(this, source, "source"); + GraphContracts.AssumeInVertexSet(this, target, "target"); + + EdgeList edgeList; + if (this.vertexOutEdges.TryGetValue(source, out edgeList)) + { + List list = new List(edgeList.Count); + foreach (var edge in edgeList) + if (edge.Target.Equals(target)) + list.Add(edge); + edges = list; + return true; + } + else + { + edges = null; + return false; + } + } + + public bool ContainsEdge(TEdge edge) + { + GraphContracts.AssumeInVertexSet(this, edge, "edge"); + return this.vertexOutEdges[edge.Source].Contains(edge); + } + + public virtual void AddVertex(TVertex v) + { + GraphContracts.AssumeNotInVertexSet(this, v, "v"); + + if (this.EdgeCapacity > 0) + { + this.vertexOutEdges.Add(v, new EdgeList(this.EdgeCapacity)); + this.vertexInEdges.Add(v, new EdgeList(this.EdgeCapacity)); + } + else + { + this.vertexOutEdges.Add(v, new EdgeList()); + this.vertexInEdges.Add(v, new EdgeList()); + } + this.OnVertexAdded(new VertexEventArgs(v)); + } + + public virtual void AddVertexRange(IEnumerable vertices) + { + GraphContracts.AssumeNotNull(vertices, "vertices"); + foreach (var v in vertices) + this.AddVertex(v); + } + + public event VertexEventHandler VertexAdded; + protected virtual void OnVertexAdded(VertexEventArgs args) + { + VertexEventHandler eh = this.VertexAdded; + if (eh != null) + eh(this, args); + } + + public virtual bool RemoveVertex(TVertex v) + { + GraphContracts.AssumeNotNull(v, "v"); + if (!this.ContainsVertex(v)) + return false; + + // collect edges to remove + EdgeList edgesToRemove = new EdgeList(); + foreach (var outEdge in this.OutEdges(v)) + { + this.vertexInEdges[outEdge.Target].Remove(outEdge); + edgesToRemove.Add(outEdge); + } + foreach (var inEdge in this.InEdges(v)) + { + // might already have been removed + if(this.vertexOutEdges[inEdge.Source].Remove(inEdge)) + edgesToRemove.Add(inEdge); + } + + // notify users + if (this.EdgeRemoved != null) + { + foreach(TEdge edge in edgesToRemove) + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + } + + this.vertexOutEdges.Remove(v); + this.vertexInEdges.Remove(v); + this.edgeCount -= edgesToRemove.Count; + this.OnVertexRemoved(new VertexEventArgs(v)); + + GraphContracts.Assert(this.edgeCount >= 0); + return true; + } + + public event VertexEventHandler VertexRemoved; + protected virtual void OnVertexRemoved(VertexEventArgs args) + { + VertexEventHandler eh = this.VertexRemoved; + if (eh != null) + eh(this, args); + } + + public int RemoveVertexIf(VertexPredicate predicate) + { + GraphContracts.AssumeNotNull(predicate, "predicate"); + + VertexList vertices = new VertexList(); + foreach (var v in this.Vertices) + if (predicate(v)) + vertices.Add(v); + + foreach (var v in vertices) + this.RemoveVertex(v); + return vertices.Count; + } + + public virtual bool AddEdge(TEdge e) + { + GraphContracts.AssumeInVertexSet(this, e, "e"); + if (!this.AllowParallelEdges) + { + if (this.ContainsEdge(e.Source, e.Target)) + return false; + } + this.vertexOutEdges[e.Source].Add(e); + this.vertexInEdges[e.Target].Add(e); + this.edgeCount++; + + this.OnEdgeAdded(new EdgeEventArgs(e)); + + return true; + } + + public void AddEdgeRange(IEnumerable edges) + { + GraphContracts.AssumeNotNull(edges, "edges"); + foreach (var edge in edges) + this.AddEdge(edge); + } + + public virtual bool AddVerticesAndEdge(TEdge e) + { + GraphContracts.AssumeNotNull(e, "e"); + if (!this.ContainsVertex(e.Source)) + this.AddVertex(e.Source); + if (!this.ContainsVertex(e.Target)) + this.AddVertex(e.Target); + + return this.AddEdge(e); + } + + public event EdgeEventHandler EdgeAdded; + protected virtual void OnEdgeAdded(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeAdded; + if (eh != null) + eh(this, args); + } + + public virtual bool RemoveEdge(TEdge e) + { + GraphContracts.AssumeInVertexSet(this, e, "e"); + if (this.vertexOutEdges[e.Source].Remove(e)) + { + this.vertexInEdges[e.Target].Remove(e); + this.edgeCount--; + GraphContracts.Assert(this.edgeCount >= 0); + + this.OnEdgeRemoved(new EdgeEventArgs(e)); + return true; + } + else + { + return false; + } + } + + public event EdgeEventHandler EdgeRemoved; + protected virtual void OnEdgeRemoved(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeRemoved; + if (eh != null) + eh(this, args); + } + + public int RemoveEdgeIf(EdgePredicate predicate) + { + GraphContracts.AssumeNotNull(predicate, "predicate"); + EdgeList edges = new EdgeList(); + foreach (var edge in this.Edges) + if (predicate(edge)) + edges.Add(edge); + + foreach (var edge in edges) + this.RemoveEdge(edge); + return edges.Count; + } + + public int RemoveOutEdgeIf(TVertex v, EdgePredicate predicate) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + GraphContracts.AssumeNotNull(predicate, "predicate"); + EdgeList edges = new EdgeList(); + foreach (var edge in this.OutEdges(v)) + if (predicate(edge)) + edges.Add(edge); + foreach (var edge in edges) + this.RemoveEdge(edge); + return edges.Count; + } + + public int RemoveInEdgeIf(TVertex v, EdgePredicate predicate) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + GraphContracts.AssumeNotNull(predicate, "predicate"); + EdgeList edges = new EdgeList(); + foreach (var edge in this.InEdges(v)) + if (predicate(edge)) + edges.Add(edge); + foreach (var edge in edges) + this.RemoveEdge(edge); + return edges.Count; + } + + public void ClearOutEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + + EdgeList outEdges = this.vertexOutEdges[v]; + foreach (var edge in outEdges) + { + this.vertexInEdges[edge.Target].Remove(edge); + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + } + + this.edgeCount -= outEdges.Count; + outEdges.Clear(); + GraphContracts.Assert(this.edgeCount >= 0); + } + + public void ClearInEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + + EdgeList inEdges = this.vertexInEdges[v]; + foreach (var edge in inEdges) + { + this.vertexOutEdges[edge.Source].Remove(edge); + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + } + + this.edgeCount -= inEdges.Count; + inEdges.Clear(); + GraphContracts.Assert(this.edgeCount >= 0); + } + + public void ClearEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + + ClearOutEdges(v); + ClearInEdges(v); + } + + public void TrimEdgeExcess() + { + foreach (var edges in this.vertexInEdges.Values) + edges.TrimExcess(); + foreach (var edges in this.vertexOutEdges.Values) + edges.TrimExcess(); + } + + public void Clear() + { + this.vertexOutEdges.Clear(); + this.vertexInEdges.Clear(); + this.edgeCount = 0; + } + + public void MergeVertex(TVertex v, IEdgeFactory edgeFactory) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + GraphContracts.AssumeNotNull(edgeFactory, "edgeFactory"); + + // storing edges in local array + EdgeList inedges = this.vertexInEdges[v]; + EdgeList outedges = this.vertexOutEdges[v]; + + // remove vertex + this.RemoveVertex(v); + + // add edges from each source to each target + foreach (var source in inedges) + { + //is it a self edge + if (source.Source.Equals(v)) + continue; + foreach (var target in outedges) + { + if (v.Equals(target.Target)) + continue; + // we add an new edge + this.AddEdge(edgeFactory.CreateEdge(source.Source, target.Target)); + } + } + } + + public void MergeVertexIf(VertexPredicate vertexPredicate, IEdgeFactory edgeFactory) + { + GraphContracts.AssumeNotNull(vertexPredicate, "vertexPredicate"); + GraphContracts.AssumeNotNull(edgeFactory, "edgeFactory"); + + // storing vertices to merge + VertexList mergeVertices = new VertexList(this.VertexCount / 4); + foreach (var v in this.Vertices) + if (vertexPredicate(v)) + mergeVertices.Add(v); + + // applying merge recursively + foreach (var v in mergeVertices) + MergeVertex(v, edgeFactory); + } + + [Serializable] + private sealed class VertexList : List + { + public VertexList() { } + public VertexList(int capacity) + : base(capacity) { } + } + + [Serializable] + private sealed class EdgeList : List, ICloneable + { + public EdgeList() { } + public EdgeList(int capacity) + : base(capacity) + { } + private EdgeList(EdgeList list) + : base(list) + { } + + public EdgeList Clone() + { + return new EdgeList(this); + } + + object ICloneable.Clone() + { + return this.Clone(); + } + } + + [Serializable] + private sealed class VertexEdgeDictionary + : Dictionary, ICloneable, ISerializable + { + public VertexEdgeDictionary() { } + public VertexEdgeDictionary(int capacity) + : base(capacity) + { } + + public VertexEdgeDictionary(SerializationInfo info, StreamingContext context):base(info,context) { } + + public VertexEdgeDictionary Clone() + { + VertexEdgeDictionary clone = new VertexEdgeDictionary(this.Count); + foreach (KeyValuePair kv in this) + clone.Add(kv.Key, kv.Value.Clone()); + return clone; + } + + object ICloneable.Clone() + { + return this.Clone(); + } + } + + #region ICloneable Members + private BidirectionalGraph( + VertexEdgeDictionary vertexInEdges, + VertexEdgeDictionary vertexOutEdges, + int edgeCount, + int edgeCapacity, + bool allowParallelEdges + ) + { + this.vertexInEdges = vertexInEdges; + this.vertexOutEdges = vertexOutEdges; + this.edgeCount = edgeCount; + this.edgeCapacity = edgeCapacity; + this.allowParallelEdges = allowParallelEdges; + } + + public BidirectionalGraph Clone() + { + return new BidirectionalGraph( + this.vertexInEdges.Clone(), + this.vertexOutEdges.Clone(), + this.edgeCount, + this.edgeCapacity, + this.allowParallelEdges + ); + } + + object ICloneable.Clone() + { + return this.Clone(); + } + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs.meta new file mode 100644 index 0000000..ff228b6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f2797574f25e840379b8236311eafc32 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs new file mode 100755 index 0000000..b5b1092 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs @@ -0,0 +1,363 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public class BidirectionalMatrixGraph : + IBidirectionalGraph, + IMutableEdgeListGraph + where TEdge : IEdge + { + private readonly int vertexCount; + private int edgeCount; + private readonly TEdge[,] edges; + + public BidirectionalMatrixGraph(int vertexCount) + { + if (vertexCount < 1) + throw new ArgumentOutOfRangeException("vertexCount"); + this.vertexCount = vertexCount; + this.edgeCount = 0; + this.edges = new TEdge[vertexCount, vertexCount]; + } + + #region IGraph + public bool AllowParallelEdges + { + get { return false; } + } + + public bool IsDirected + { + get { return true; } + } + #endregion + + #region IVertexListGraph + public int VertexCount + { + get { return this.vertexCount; } + } + + public bool IsVerticesEmpty + { + get { return this.VertexCount == 0; } + } + #endregion + + #region IEdgeListGraph + public int EdgeCount + { + get { return this.edgeCount; } + } + + public bool IsEdgesEmpty + { + get { return this.EdgeCount == 0; } + } + + public IEnumerable Edges + { + get + { + for (int i = 0; i < this.VertexCount; ++i) + { + for (int j = 0; j < this.VertexCount; ++j) + { + TEdge e = this.edges[i, j]; + if (e != null) + yield return e; + } + } + } + } + #endregion + + #region IBidirectionalGraph Members + + public bool IsInEdgesEmpty(int v) + { + for (int i = 0; i < this.VertexCount; ++i) + if (this.edges[i, v] != null) + return false; + return true; + } + + public int InDegree(int v) + { + int count = 0; + for (int i = 0; i < this.VertexCount; ++i) + if (this.edges[i, v] != null) + count++; + return count; + } + + public IEnumerable InEdges(int v) + { + for (int i = 0; i < this.VertexCount; ++i) + { + TEdge e = this.edges[i, v]; + if (e != null) + yield return e; + } + } + + public TEdge InEdge(int v, int index) + { + int count = 0; + for (int i = 0; i < this.VertexCount; ++i) + { + TEdge e = this.edges[i, v]; + if (e != null) + { + if (count == index) + return e; + count++; + } + } + throw new ArgumentOutOfRangeException("index"); + } + + public int Degree(int v) + { + return this.InDegree(v) + this.OutDegree(v); + } + + #endregion + + #region IIncidenceGraph Members + + public bool ContainsEdge(int source, int target) + { + return this.edges[source, target] != null; + } + + public bool TryGetEdge(int source, int target, out TEdge edge) + { + edge = this.edges[source, target]; + return edge != null; + } + + public bool TryGetEdges(int source, int target, out IEnumerable edges) + { + TEdge edge; + if (this.TryGetEdge(source, target, out edge)) + { + edges = new TEdge[] { edge }; + return true; + } + else + { + edges = null; + return false; + } + } + + #endregion + + #region IImplicitGraph Members + + public bool IsOutEdgesEmpty(int v) + { + for (int j = 0; j < this.vertexCount; ++j) + if (this.edges[v, j] != null) + return false; + return true; + } + + public int OutDegree(int v) + { + int count = 0; + for (int j = 0; j < this.vertexCount; ++j) + if (this.edges[v, j] != null) + count++; + return count; + } + + public IEnumerable OutEdges(int v) + { + for (int j = 0; j < this.vertexCount; ++j) + { + TEdge e = this.edges[v, j]; + if (e != null) + yield return e; + } + } + + public TEdge OutEdge(int v, int index) + { + int count = 0; + for (int j = 0; j < this.vertexCount; ++j) + { + TEdge e = this.edges[v, j]; + if (e != null) + { + if (count==index) + return e; + count++; + } + } + throw new ArgumentOutOfRangeException("index"); + } + + #endregion + + #region IVertexSet Members + + public IEnumerable Vertices + { + get + { + for (int i = 0; i < this.VertexCount; ++i) + yield return i; + } + } + + public bool ContainsVertex(int vertex) + { + return vertex >= 0 && vertex < this.VertexCount; + } + + #endregion + + #region IEdgeListGraph Members + + public bool ContainsEdge(TEdge edge) + { + TEdge e = this.edges[edge.Source, edge.Target]; + return e!=null && + e.Equals(edge); + } + + #endregion + + #region IMutableBidirectionalGraph Members + + public int RemoveInEdgeIf(int v, EdgePredicate edgePredicate) + { + int count = 0; + for (int i = 0; i < this.VertexCount; ++i) + { + TEdge e = this.edges[i, v]; + if (e != null && edgePredicate(e)) + { + this.RemoveEdge(e); + count++; + } + } + return count; + } + + public void ClearInEdges(int v) + { + for (int i = 0; i < this.VertexCount; ++i) + { + TEdge e = this.edges[i, v]; + if (e != null) + this.RemoveEdge(e); + } + } + + public void ClearEdges(int v) + { + this.ClearInEdges(v); + this.ClearOutEdges(v); + } + + #endregion + + #region IMutableIncidenceGraph Members + + public int RemoveOutEdgeIf(int v, EdgePredicate predicate) + { + int count = 0; + for (int j = 0; j < this.VertexCount; ++j) + { + TEdge e = this.edges[v, j]; + if (e != null && predicate(e)) + { + this.RemoveEdge(e); + count++; + } + } + return count; + } + + public void ClearOutEdges(int v) + { + for (int j = 0; j < this.VertexCount; ++j) + { + TEdge e = this.edges[v, j]; + if (e != null) + this.RemoveEdge(e); + } + } + + #endregion + + #region IMutableGraph Members + + public void Clear() + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + + #region IMutableEdgeListGraph Members + + public bool AddEdge(TEdge edge) + { + GraphContracts.AssumeNotNull(edge, "edge"); + if (this.edges[edge.Source, edge.Target]!=null) + throw new ParallelEdgeNotAllowedException(); + this.edges[edge.Source,edge.Target] = edge; + this.edgeCount++; + this.OnEdgeAdded(new EdgeEventArgs(edge)); + return true; + } + + public void AddEdgeRange(IEnumerable edges) + { + GraphContracts.AssumeNotNull(edges, "edges"); + foreach (var edge in edges) + this.AddEdge(edge); + } + + public event EdgeEventHandler EdgeAdded; + protected virtual void OnEdgeAdded(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeAdded; + if (eh != null) + eh(this, args); + } + + public bool RemoveEdge(TEdge edge) + { + TEdge e = this.edges[edge.Source, edge.Target]; + this.edges[edge.Source, edge.Target] = default(TEdge); + if (!e.Equals(default(TEdge))) + { + this.edgeCount--; + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + return true; + } + else + return false; + } + + public event EdgeEventHandler EdgeRemoved; + protected virtual void OnEdgeRemoved(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeRemoved; + if (eh != null) + eh(this, args); + } + + public int RemoveEdgeIf(EdgePredicate predicate) + { + throw new NotImplementedException(); + } + #endregion +} +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs.meta new file mode 100644 index 0000000..8d98f56 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/BidirectionalMatrixGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 792f61542c47543078206dca465c270e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections.meta new file mode 100644 index 0000000..04bdee8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 8e344298df45d4ba8a927ac1a7f21c44 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs new file mode 100755 index 0000000..73793bb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Collections; + +namespace QuickGraph.Collections +{ + /// + /// Binary heap + /// + /// + /// + /// Indexing rules: + /// + /// parent index: index ¡ 1)/2 + /// left child: 2 * index + 1 + /// right child: 2 * index + 2 + /// + /// Reference: + /// http://dotnetslackers.com/Community/files/folders/data-structures-and-algorithms/entry28722.aspx + /// + [DebuggerDisplay("Count = {Count}")] + public class BinaryHeap : + IEnumerable> + { + readonly Comparison priorityComparsion; + KeyValuePair[] items; + int count; + int version; + + const int DefaultCapacity = 16; + + public BinaryHeap() + : this(DefaultCapacity, Comparer.Default.Compare) + { } + + public BinaryHeap(Comparison priorityComparison) + : this(DefaultCapacity, priorityComparison) + { } + + public BinaryHeap(int capacity, Comparison priorityComparison) + { + if (capacity < 0) + throw new ArgumentOutOfRangeException("capacity"); + if (priorityComparison == null) + throw new ArgumentNullException("priorityComparison"); + + this.items = new KeyValuePair[capacity]; + this.priorityComparsion = priorityComparison; + } + + public Comparison PriorityComparison + { + get { return this.priorityComparsion; } + } + + public int Capacity + { + get { return this.items.Length; } + } + + public int Count + { + get { return this.count; } + } + + public void Add(TPriority priority, TValue value) + { + GraphContracts.Assert(count <= this.items.Length); + + this.version++; + this.ResizeArray(); + this.items[this.count++] = new KeyValuePair(priority, value); + this.MinHeapifyDown(this.count - 1); + } + + private void MinHeapifyDown(int start) + { + int i = start; + int j = (i - 1) / 2; + while (i > 0 && + this.Less(i, j)) + { + this.Swap(i, j); + i = j; + j = (i - 1) / 2; + } + } + + private void ResizeArray() + { + if (this.count == this.items.Length) + { + var newItems = new KeyValuePair[this.count * 2 + 1]; + Array.Copy(this.items, newItems, this.count); + this.items = newItems; + } + } + + public KeyValuePair Minimum() + { + if (this.count == 0) + throw new InvalidOperationException(); + return this.items[0]; + } + + public KeyValuePair RemoveMinimum() + { + // shortcut for heap with 1 element. + if (this.count == 1) + { + this.version++; + return this.items[--this.count]; + } + return this.RemoveAt(0); + } + + public KeyValuePair RemoveAt(int index) + { + if (this.count == 0) + throw new InvalidOperationException("heap is empty"); + if (index < 0 | index >= this.count | index + this.count < this.count) + throw new ArgumentOutOfRangeException("index"); + + this.version++; + // shortcut for heap with 1 element. + if (this.count == 1) + return this.items[--this.count]; + + if (index < this.count - 1) + { + this.Swap(index, this.count - 1); + this.MinHeapifyUp(index); + } + + return this.items[--this.count]; + } + + private void MinHeapifyUp(int index) + { + var left = 2 * index + 1; + var right = 2 * index + 2; + while ( + (left < this.count - 1 && !this.Less(index, left)) || + (right < this.count - 1 && !this.Less(index, right)) + ) + { + if (right >= this.count - 1 || + this.Less(left, right)) + { + this.Swap(left, index); + index = left; + } + else + { + this.Swap(right, index); + index = right; + } + left = 2 * index + 1; + right = 2 * index + 2; + } + } + + public int IndexOf(TValue value) + { + for (int i = 0; i < this.count; i++) + { + if (object.Equals(value, this.items[i].Value)) + return i; + } + return -1; + } + + public void Update(TPriority priority, TValue value) + { + // find index + var index = this.IndexOf(value); + if (index < 0) + throw new InvalidOperationException("value was not found in the heap"); + + // remove and add + this.RemoveAt(index); + this.Add(priority, value); + } + + private bool Less(int i, int j) + { + GraphContracts.Assert(i >= 0 & i < this.count & + j >= 0 & j < this.count & + i != j, String.Format("i: {0}, j: {1}", i, j)); + + return this.priorityComparsion(this.items[i].Key, this.items[j].Key) <= 0; + } + + private void Swap(int i, int j) + { + GraphContracts.Assert(i >= 0 & i < this.count & + j >= 0 & j < this.count & + i != j); + + var kv = this.items[i]; + this.items[i] = this.items[j]; + this.items[j] = kv; + } + + [Conditional("DEBUG")] + public void ObjectInvariant() + { + GraphContracts.Assert(this.items != null); + GraphContracts.Assert( + this.count > -1 & + this.count <= this.items.Length); + for (int index = 0; index < this.count; ++index) + { + var left = 2 * index + 1; + GraphContracts.Assert(left >= count || this.Less(index, left)); + var right = 2 * index + 2; + GraphContracts.Assert(right >= count || this.Less(index, right)); + } + } + + #region IEnumerable> Members + public IEnumerator> GetEnumerator() + { + return new Enumerator(this); + } + + struct Enumerator : + IEnumerator> + { + BinaryHeap owner; + KeyValuePair[] items; + readonly int count; + readonly int version; + int index; + + public Enumerator(BinaryHeap owner) + { + this.owner = owner; + this.items = owner.items; + this.count = owner.count; + this.version = owner.version; + this.index = -1; + } + + public KeyValuePair Current + { + get + { + if (this.version != this.owner.version) + throw new InvalidOperationException(); + if (this.index < 0 | this.index == this.count) + throw new InvalidOperationException(); + GraphContracts.Assert(this.index <= this.count); + return this.items[this.index]; + } + } + + void IDisposable.Dispose() + { + this.owner = null; + this.items = null; + } + + object IEnumerator.Current + { + get { return this.Current; } + } + + public bool MoveNext() + { + if (this.version != this.owner.version) + throw new InvalidOperationException(); + return ++this.index < this.count; + } + + public void Reset() + { + if (this.version != this.owner.version) + throw new InvalidOperationException(); + this.index = -1; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs.meta new file mode 100644 index 0000000..4346cc8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/BinaryHeap.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1927e045a2139404caeaed833a97569c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs new file mode 100755 index 0000000..66618b0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Collections +{ + public interface IQueue + { + int Count { get; } + + bool Contains(T value); + void Enqueue(T value); + T Dequeue(); + T Peek(); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs.meta new file mode 100644 index 0000000..7ddc39d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/IQueue.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b6e0ff9e40b094355b40b6a258d1dea9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs new file mode 100755 index 0000000..3a758ab --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace QuickGraph.Collections +{ + [Serializable] + public sealed class PriorityQueue : + IQueue + { + private readonly IDictionary distances; + private readonly BinaryHeap heap; + + public PriorityQueue( + IDictionary distances + ) + : this(distances, Comparer.Default.Compare) + { } + + public PriorityQueue( + IDictionary distances, + Comparison distanceComparison + ) + { + if (distances == null) + throw new ArgumentNullException("distances"); + if (distanceComparison == null) + throw new ArgumentNullException("distanceComparison"); + + this.distances = distances; + this.heap = new BinaryHeap(distanceComparison); + } + + public void Update(TVertex v) + { + this.heap.Update(this.distances[v], v); + } + + public int Count + { + get { return this.heap.Count; } + } + + public bool Contains(TVertex value) + { + return this.heap.IndexOf(value) > -1; + } + + public void Enqueue(TVertex value) + { + GraphContracts.AssumeNotNull(value, "value"); + GraphContracts.Assume(this.distances.ContainsKey(value), "this.distances.ContainsKey(value)"); + this.heap.Add(this.distances[value], value); + } + + public TVertex Dequeue() + { + return this.heap.RemoveMinimum().Value; + } + + public TVertex Peek() + { + return this.heap.Minimum().Value; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs.meta new file mode 100644 index 0000000..b9bf895 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorithizedQueue.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: de1f214c191c54ff4b98b8c206983fed +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs new file mode 100755 index 0000000..a3336a7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; + +namespace ModelDriven.Graph.Collections +{ + /// + /// + /// + /// + /// Algorithms in Java 3rd edition. Chapter 9.6 + /// + /// + public class PriorityQueue : IEnumerable + { + private T[] items; + private int[] pq; + private int[] qp; + private int count; + private IComparer comparer; + + public PriorityQueue(T[] items, IComparer comparer) + { + this.items = items; + this.count = 0; + this.comparer = comparer; + this.pq = new int[this.items.Length + 1]; + this.qp = new int[this.items.Length + 1]; + } + + #region Heap methods + private bool Less(int left, int right) + { + return this.comparer.Compare( + this.items[pq[left]], + this.items[pq[right]] + ) < 0; + } + + private void Exchange(int i, int j) + { + int t = pq[i]; + pq[i] = pq[j]; + pq[j] = t; + qp[pq[i]] = i; + qp[pq[j]] = j; + } + + private void Swim(int k) + { + while (k > 1 && Less(k / 2, k)) + { + Exchange(k, k / 2); + k = k / 2; + } + } + + private void Sink(int k, int N) + { + while (2 * k <= N) + { + int j = 2 * k; + if (j < N && Less(j, j + 1)) + j++; + if (!Less(k, j)) + break; + Exchange(k, j); + k = j; + } + } + #endregion + + public int Count + { + get { return this.count; } + } + + public int Capacity + { + get { return this.items.Length - 1; } + } + + public void Add(int v) + { + pq[++this.count] = v; + qp[v] = this.Count; + Swim(this.Count); + } + + public void Update(int k) + { + Swim(qp[k]); + Sink(qp[k], this.Count); + } + + public int Pop() + { + Exchange(1, this.Count); + Sink(1, this.Count - 1); + return pq[this.count--]; + } + + public IEnumerator GetEnumerator() + { + return (IEnumerator)this.items.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs.meta new file mode 100644 index 0000000..a2cefff --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/PriorityQueue.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e6d90b51c3b7c46c19b3d9eceffa0f4f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs new file mode 100755 index 0000000..bc6abd0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs @@ -0,0 +1,12 @@ +namespace QuickGraph.Collections +{ + using System; + using System.Collections.Generic; + + [Serializable] + public class Queue : + System.Collections.Generic.Queue, + IQueue + { + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs.meta new file mode 100644 index 0000000..4745387 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Collections/Queue.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e2085439d61254eec8b0a587641fe77c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs new file mode 100755 index 0000000..a039f0b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs @@ -0,0 +1,10 @@ +using System; +namespace QuickGraph +{ + [Serializable] + public delegate TEdge CreateEdgeDelegate( + IVertexListGraph g, + TVertex source, + TVertex target) + where TEdge : IEdge; +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs.meta new file mode 100644 index 0000000..c1581f5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateEdgeDelegate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 40ab73837de614aa0a8f4b1ebeb9c083 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs new file mode 100755 index 0000000..a81d8b3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs @@ -0,0 +1,8 @@ +using System; +namespace QuickGraph +{ + [Serializable] + public delegate TVertex CreateVertexDelegate( + IVertexListGraph g) + where TEdge : IEdge; +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs.meta new file mode 100644 index 0000000..2f3d6d5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/CreateVertexDelegate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7bb9ebce4b9ed4407b927c009a3f80e7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams.meta new file mode 100644 index 0000000..1c4f9c1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 3f008bd24ddb54b8f86cb4054a58431b +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd new file mode 100755 index 0000000..4482a5d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd @@ -0,0 +1,67 @@ + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + IEdgeListAndIncidenceGraph.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + IEdgeListGraph.cs + + + + + + AAAAQAAgAAAAAAAAAAAAAAAAAAAAABAAAAAEAAAAAAA= + IImplicitGraph.cs + + + + + + AIAAAAAAAAAAAAAAECAAAAAAAAAAAAAAAAAAAAAAAAA= + IIncidenceGraph.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + IVertexAndEdgeListGraph.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + IVertexListGraph.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAEABAAACAAAA= + IVertexSet.cs + + + + + + AAAAgAAAAAAAAAAAACAAAAAQAAAAAAAAAAgAAAAAAAA= + IEdgeSet.cs + + + + + + gAAAAAQAAAAAAAAAAAAAAAASAAAAAAAAAAAAAAAAABA= + IBidirectionalGraph.cs + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd.meta new file mode 100644 index 0000000..77fcfa6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Diagrams/TraversalInterfaces.cd.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 2ec65a898edae4ea7bc6315534b080ed +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs new file mode 100755 index 0000000..02509ab --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs @@ -0,0 +1,40 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public class Edge : IEdge + { + private readonly TVertex source; + private readonly TVertex target; + + public Edge(TVertex source, TVertex target) + { + GraphContracts.AssumeNotNull(source, "source"); + GraphContracts.AssumeNotNull(target, "target"); + + this.source = source; + this.target = target; + } + + public static Type VertexType + { + get { return typeof(TVertex); } + } + + public TVertex Source + { + get { return this.source; } + } + + public TVertex Target + { + get { return this.target; } + } + + public override string ToString() + { + return String.Format("{0}->{1}", this.Source, this.Target); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs.meta new file mode 100644 index 0000000..490bdab --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Edge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d46206581d4b34d5a80c55f26ecdcd70 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs new file mode 100755 index 0000000..10ba863 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs @@ -0,0 +1,34 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public sealed class EdgeEdgeEventArgs : EventArgs + where TEdge : IEdge + { + private readonly TEdge edge; + private readonly TEdge targetEdge; + public EdgeEdgeEventArgs(TEdge edge, TEdge targetEdge) + { + GraphContracts.AssumeNotNull(edge, "edge"); + GraphContracts.AssumeNotNull(targetEdge, "targetEdge"); + this.edge = edge; + this.targetEdge = targetEdge; + } + + public TEdge Edge + { + get { return this.edge; } + } + + public TEdge TargetEdge + { + get { return this.targetEdge;} + } + } + + public delegate void EdgeEdgeEventHandler( + Object sender, + EdgeEdgeEventArgs e) + where TEdge : IEdge; +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs.meta new file mode 100644 index 0000000..c4dff13 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEdgeEventArgs.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3602a50dc872b4d509d185dafd4b6e0b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs new file mode 100755 index 0000000..8f8a599 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs @@ -0,0 +1,27 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public class EdgeEventArgs : EventArgs + where TEdge : IEdge + { + private TEdge edge; + public EdgeEventArgs(TEdge edge) + { + if (edge == null) + throw new ArgumentNullException("edge"); + this.edge = edge; + } + + public TEdge Edge + { + get { return this.edge; } + } + } + + public delegate void EdgeEventHandler( + Object sender, + EdgeEventArgs e) + where TEdge : IEdge; +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs.meta new file mode 100644 index 0000000..927b381 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeEventArgs.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41f246e17504b4ff9a47455bbaafc833 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs new file mode 100755 index 0000000..4f0993d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs @@ -0,0 +1,13 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public sealed class EdgeFactory : IEdgeFactory> + { + public Edge CreateEdge(TVertex source, TVertex target) + { + return new Edge(source, target); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs.meta new file mode 100644 index 0000000..97e5cac --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 276086653c01f40438c5f0a8a9e5fbb6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs new file mode 100755 index 0000000..912d1a8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + [Serializable] + public class EdgeListGraph : + IEdgeListGraph, + IMutableEdgeListGraph + where TEdge : IEdge + { + private readonly bool isDirected = true; + private readonly bool allowParralelEdges = true; + private readonly EdgeEdgeDictionary edges = new EdgeEdgeDictionary(); + + [Serializable] + public class EdgeEdgeDictionary : Dictionary + { } + + public EdgeListGraph() + {} + + public EdgeListGraph(bool isDirected, bool allowParralelEdges) + { + this.isDirected = isDirected; + this.allowParralelEdges = allowParralelEdges; + } + + public bool IsEdgesEmpty + { + get + { + return this.edges.Count==0; + } + } + + public int EdgeCount + { + get + { + return this.edges.Count; + } + } + + public IEnumerable Edges + { + get + { + return this.edges.Keys; + } + } + + public bool ContainsEdge(TEdge edge) + { + return this.edges.ContainsKey(edge); + } + + public bool IsDirected + { + get + { + return this.isDirected; + } + } + + public bool AllowParallelEdges + { + get + { + return this.allowParralelEdges; + } + } + + public bool AddEdge(TEdge edge) + { + GraphContracts.AssumeNotNull(edge, "edge"); + if(this.ContainsEdge(edge)) + return false; + this.edges.Add(edge, edge); + this.OnEdgeAdded(new EdgeEventArgs(edge)); + return true; + } + + public void AddEdgeRange(IEnumerable edges) + { + GraphContracts.AssumeNotNull(edges, "edges"); + foreach (var edge in edges) + this.AddEdge(edge); + } + + public event EdgeEventHandler EdgeAdded; + protected virtual void OnEdgeAdded(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeAdded; + if (eh != null) + eh(this, args); + } + + public bool RemoveEdge(TEdge edge) + { + if (this.edges.Remove(edge)) + { + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + return true; + } + else + return false; + } + + public event EdgeEventHandler EdgeRemoved; + protected virtual void OnEdgeRemoved(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeRemoved; + if (eh != null) + eh(this, args); + } + + public int RemoveEdgeIf(EdgePredicate predicate) + { + List edgesToRemove = new List(); + foreach (var edge in this.Edges) + if (predicate(edge)) + edgesToRemove.Add(edge); + + foreach (var edge in edgesToRemove) + edges.Remove(edge); + return edgesToRemove.Count; + } + + public void Clear() + { + this.edges.Clear(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs.meta new file mode 100644 index 0000000..08f00dd --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 039368e32b41649daa0fd08a398d7d38 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs new file mode 100755 index 0000000..41dfa69 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + + [global::System.Serializable] + public class EdgeNotFoundException : Exception + { + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public EdgeNotFoundException() { } + public EdgeNotFoundException(string message) : base(message) { } + public EdgeNotFoundException(string message, Exception inner) : base(message, inner) { } + protected EdgeNotFoundException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs.meta new file mode 100644 index 0000000..8b1a88d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/EdgeNotFoundException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6b8ffe2bbd8ce4d658426c97a85e292b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs new file mode 100755 index 0000000..3fef4dc --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; + +namespace QuickGraph +{ + public static class FactoryCompiler + { + private static readonly object syncRoot = new object(); + private static AssemblyBuilder assembly; + private static ModuleBuilder module; + + private static void CreateAssembly() + { + if (assembly == null) + { + assembly = AppDomain.CurrentDomain.DefineDynamicAssembly( + new AssemblyName("QuickGraph.FactoryCompilers"), + AssemblyBuilderAccess.Run + ); + module = assembly.DefineDynamicModule("QuickGraph.FactoryCompilers"); + } + } + + private static string GetVertexFactoryName(Type factoredType) + { + return string.Format( + "{0}VertexFactory", factoredType.MetadataToken + ); + } + + private static string GetEdgeFactoryName(Type vertexType, Type edgeType) + { + return string.Format( + "{0}{1}EdgeFactory", vertexType.MetadataToken, edgeType.MetadataToken); + } + + public static IVertexFactory GetVertexFactory() + { + return (IVertexFactory)Activator.CreateInstance(GetVertexFactoryType()); + } + + private static Type GetVertexFactoryType() + { + lock (syncRoot) + { + CreateAssembly(); + Type factoryType = assembly.GetType(GetVertexFactoryName(typeof(TVertex)), false); + if (factoryType != null) + return factoryType; + + ConstructorInfo constructor = + typeof(TVertex).GetConstructor(new Type[] { }); + if (constructor == null) + throw new ArgumentException(String.Format("Type {0} does not have public construtor", typeof(TVertex))); + + TypeBuilder type = module.DefineType(GetVertexFactoryName(typeof(TVertex)), + TypeAttributes.Sealed | TypeAttributes.Public); + type.AddInterfaceImplementation(typeof(IVertexFactory)); + + + // CreateVertex method + MethodBuilder createVertex = type.DefineMethod( + "CreateVertex", + MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.VtableLayoutMask, + typeof(TVertex), + Type.EmptyTypes + ); + ILGenerator gen = createVertex.GetILGenerator(); + gen.Emit(OpCodes.Newobj, constructor); + gen.Emit(OpCodes.Ret); + factoryType = type.CreateType(); + return factoryType; + } + } + + public static IEdgeFactory GetEdgeFactory() + where TEdge : IEdge + { + return (IEdgeFactory)Activator.CreateInstance(GetEdgeFactoryType()); + } + + private static Type GetEdgeFactoryType() + where TEdge : IEdge + { + lock (syncRoot) + { + CreateAssembly(); + string typeName = GetEdgeFactoryName(typeof(TVertex), typeof(TEdge)); + Type factoryType = assembly.GetType(typeName, false); + if (factoryType != null) + return factoryType; + + ConstructorInfo constructor = + typeof(TEdge).GetConstructor(new Type[] { typeof(TVertex), typeof(TVertex) }); + if (constructor == null) + throw new ArgumentException(String.Format("Type {0} does not have a construtor that takes 2 Vertex", typeof(TVertex))); + + TypeBuilder type = module.DefineType(typeName, + TypeAttributes.Sealed | TypeAttributes.Public); + type.AddInterfaceImplementation(typeof(IEdgeFactory)); + + // CreateVertex method + MethodBuilder createEdge = type.DefineMethod( + "CreateEdge", + MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.VtableLayoutMask, + typeof(TEdge), + new Type[] { typeof(TVertex), typeof(TVertex) } + ); + ILGenerator gen = createEdge.GetILGenerator(); + gen.Emit(OpCodes.Ldarg_1); + gen.Emit(OpCodes.Ldarg_2); + gen.Emit(OpCodes.Newobj, constructor); + gen.Emit(OpCodes.Ret); + factoryType = type.CreateType(); + return factoryType; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs.meta new file mode 100644 index 0000000..aff1b29 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/FactoryCompiler.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3e686553a9c3b46809dfd089f726091e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs new file mode 100755 index 0000000..a548de3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public enum GraphColor + { + White, + Gray, + Black + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs.meta new file mode 100644 index 0000000..8d38d2b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphColor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 907f03884462740f99619331131fa55e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs new file mode 100755 index 0000000..745f878 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; + +namespace QuickGraph +{ + internal static class GraphContracts + { + [Conditional("DEBUG")] + public static void Assert(bool value) + { + if (!value) + throw new InvalidOperationException(); + } + + [Conditional("DEBUG")] + public static void Assert(bool value, string message) + { + if (!value) + throw new InvalidOperationException(message); + } + + [Conditional("DEBUG")] + public static void AssumeNotNull(T v, string parameterName) + { + if (object.Equals(v, null)) + throw new ArgumentNullException(parameterName); + } + + [Conditional("DEBUG")] + public static void Assume(bool value, string message) + { + if (!value) + throw new ArgumentException(message); + } + + [Conditional("DEBUG")] + public static void AssumeInVertexSet( + IVertexSet g, + TVertex v, + string parameterName) + { + AssumeNotNull(g, "g"); + AssumeNotNull(v, parameterName); + if (!g.ContainsVertex(v)) + throw new VertexNotFoundException(parameterName); + } + + [Conditional("DEBUG")] + public static void AssumeNotInVertexSet( + IVertexSet g, + TVertex v, + string parameterName) + { + AssumeNotNull(g, "g"); + AssumeNotNull(v, parameterName); + if (g.ContainsVertex(v)) + throw new ArgumentException("vertex already in set", parameterName); + } + + [Conditional("DEBUG")] + public static void AssumeInVertexSet( + IVertexAndEdgeSet g, + TEdge e, + string parameterName) + where TEdge : IEdge + { + AssumeNotNull(g, "g"); + AssumeNotNull(e, parameterName); + AssumeInVertexSet(g, e.Source, parameterName + ".Source"); + AssumeInVertexSet(g, e.Target, parameterName + ".Target"); + } + + [Conditional("DEBUG")] + public static void AssumeInEdgeSet( + IVertexAndEdgeSet g, + TEdge e, + string parameterName) + where TEdge : IEdge + { + AssumeInVertexSet(g, e, parameterName); + if (!g.ContainsEdge(e)) + throw new EdgeNotFoundException(parameterName); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs.meta new file mode 100644 index 0000000..afcfebb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/GraphContracts.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc078e3eefd694b4c9f10ad991138e9f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs new file mode 100755 index 0000000..67e76d5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + static class HashCodeHelper + { + const Int32 FNV1_prime_32 = 16777619; + const Int32 FNV1_basis_32 = unchecked((int)2166136261); + const Int64 FNV1_prime_64 = 1099511628211; + const Int64 FNV1_basis_64 = unchecked((int)14695981039346656037); + + public static Int32 GetHashCode(Int64 x) + { + return Combine((Int32)x, (Int32)(((UInt64)x) >> 32)); + } + + private static Int32 Fold(Int32 hash, byte value) + { + return (hash * FNV1_prime_32) ^ (Int32)value; + } + + private static Int32 Fold(Int32 hash, Int32 value) + { + return Fold(Fold(Fold(Fold(hash, + (byte)value), + (byte)(((UInt32)value) >> 8)), + (byte)(((UInt32)value) >> 16)), + (byte)(((UInt32)value) >> 24)); + } + + /// + /// Combines two hashcodes in a strong way. + /// + /// + /// + /// + public static Int32 Combine(Int32 x, Int32 y) + { + return Fold(Fold(FNV1_basis_32, x), y); + } + + /// + /// Combines three hashcodes in a strong way. + /// + /// + /// + /// + /// + public static Int32 Combine(Int32 x, Int32 y, Int32 z) + { + return Fold(Fold(Fold(FNV1_basis_32, x), y), z); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs.meta new file mode 100644 index 0000000..6fb755f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/HashCodeHelper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4bd0a9fc8e82045f68652f21138ba149 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs new file mode 100755 index 0000000..f205310 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IBidirectionalGraph : + IVertexAndEdgeListGraph + where TEdge : IEdge + { + bool IsInEdgesEmpty(TVertex v); + int InDegree(TVertex v); + + IEnumerable InEdges(TVertex v); + TEdge InEdge(TVertex v, int index); + + int Degree(TVertex v); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs.meta new file mode 100644 index 0000000..8666abf --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IBidirectionalGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9e07e4b3f25924949bfc3178b19f2a21 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs new file mode 100755 index 0000000..2991d76 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs @@ -0,0 +1,9 @@ +using System; + +namespace QuickGraph +{ + public interface ICloneableEdge : IEdge + { + ICloneableEdge Clone(TVertex source, TVertex target); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs.meta new file mode 100644 index 0000000..d2da092 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ICloneableEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d6775900d389a439b9fb23b1d451a735 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs new file mode 100755 index 0000000..0e1137d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs @@ -0,0 +1,8 @@ +namespace QuickGraph +{ + public interface IEdge + { + TVertex Source { get;} + TVertex Target { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs.meta new file mode 100644 index 0000000..0413714 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: aa9936237c4024b26811cfd4030da056 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs new file mode 100755 index 0000000..589f55d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs @@ -0,0 +1,9 @@ +using System; + +namespace QuickGraph +{ + public interface IEdgeFactory where TEdge : IEdge + { + TEdge CreateEdge(TVertex source, TVertex target); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs.meta new file mode 100644 index 0000000..bde8b0c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a17c7006ca0c4626b971181d08e0ec3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs new file mode 100755 index 0000000..424131c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs @@ -0,0 +1,8 @@ +namespace QuickGraph +{ + public interface IEdgeListAndIncidenceGraph : + IEdgeListGraph, IIncidenceGraph + where TEdge : IEdge + { + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs.meta new file mode 100644 index 0000000..45ff55b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListAndIncidenceGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d3defe4fcbf8740f3bb30bedc7571f44 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs new file mode 100755 index 0000000..c38e248 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IEdgeListGraph : + IGraph, + IEdgeSet + where TEdge : IEdge + {} +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs.meta new file mode 100644 index 0000000..cdf571b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f7848c33465c54d17a14d7d8d12e9b6f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs new file mode 100755 index 0000000..8be8c5b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IEdgeSet + where TEdge : IEdge + { + bool IsEdgesEmpty { get; } + int EdgeCount { get; } + IEnumerable Edges { get; } + bool ContainsEdge(TEdge edge); + } + + +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs.meta new file mode 100644 index 0000000..d741c6e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IEdgeSet.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 195b5b93ba7bc4051b0e7173e7556f08 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs new file mode 100755 index 0000000..a5fae2d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs @@ -0,0 +1,11 @@ +using System; + +namespace QuickGraph +{ + public interface IGraph + where TEdge : IEdge + { + bool IsDirected { get;} + bool AllowParallelEdges { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs.meta new file mode 100644 index 0000000..e87fab8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c097df43759c04098a6ac59d8fee2e70 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs new file mode 100755 index 0000000..ef7ef95 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IHierarchy : + IMutableVertexAndEdgeListGraph + where TEdge : IEdge + { + /// + /// Gets the roots of the hierarchy + /// + TVertex Root { get;} + + /// + /// Gets the parent of + /// + /// + /// + /// + /// is the root of the graph. + /// + TVertex GetParent(TVertex vertex); + + /// + /// Gets the parent of + /// + /// + /// + /// + /// is the root of the graph. + /// + TEdge GetParentEdge(TVertex vertex); + + /// + /// Gets a value indicating if is + /// a cross edge. + /// + /// + /// + bool IsCrossEdge(TEdge edge); + + /// + /// Gets a value indicating whether + /// exists really or is just an induced edge. + /// + /// + /// + bool IsRealEdge(TEdge edge); + + /// + /// Gets a value indicating if + /// is a predecessor of + /// + /// + /// + /// + /// true if is a predecessor of + /// + /// + bool IsPredecessorOf(TVertex source, TVertex target); + + /// + /// Gets the number of edges between + /// and . + /// + /// + /// + /// + /// + /// is a predecessor of + /// or the otherway round. + /// + int InducedEdgeCount(TVertex source, TVertex target); + + /// + /// Gets a value indicating if is + /// inner node or a leaf. + /// + /// + /// + /// true if not a leaf + /// + bool IsInnerNode(TVertex vertex); + + /// + /// Gets the collection of children + /// from + /// + /// + /// + IEnumerable ChildrenEdges(TVertex vertex); + + + /// + /// Gets the collection of children + /// from + /// + /// + /// + IEnumerable ChildrenVertices(TVertex vertex); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs.meta new file mode 100644 index 0000000..7516d5f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHierarchy.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f827700fc6a664642a75115a6e66d586 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs new file mode 100755 index 0000000..ff87852 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IHyperEdge + { + int EndPointCount { get;} + IEnumerable EndPoints { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs.meta new file mode 100644 index 0000000..71594a5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IHyperEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b6bd2553961534246aa49b69fb0e7eb6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs new file mode 100755 index 0000000..b5604e6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IIdentifiable + { + string ID { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs.meta new file mode 100644 index 0000000..576b740 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiable.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9bb0b28dbc8c84a8f8f25ac100c837d7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs new file mode 100755 index 0000000..7908dd4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IIdentifiableEdgeFactory + where TEdge: IIdentifiable, IEdge + { + TEdge CreateEdge(string id, TVertex source, TVertex target); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs.meta new file mode 100644 index 0000000..34e9474 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableEdgeFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 757d25b1ec45541e1acc72e9194f56de +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs new file mode 100755 index 0000000..fdf01fb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IIdentifiableVertexFactory + where TVertex : IIdentifiable + { + TVertex CreateVertex(string id); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs.meta new file mode 100644 index 0000000..31afe8b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIdentifiableVertexFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c9bd09bb65e374d65b166f09e2c889d7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs new file mode 100755 index 0000000..ecab155 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IImplicitGraph : IGraph + where TEdge : IEdge + { + bool IsOutEdgesEmpty(TVertex v); + int OutDegree(TVertex v); + IEnumerable OutEdges(TVertex v); + TEdge OutEdge(TVertex v, int index); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs.meta new file mode 100644 index 0000000..07bcebc --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IImplicitGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 66c15c074a5a648a088c388db612cdf3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs new file mode 100755 index 0000000..80084f8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IIncidenceGraph : IImplicitGraph + where TEdge : IEdge + { + bool ContainsEdge(TVertex source, TVertex target); + bool TryGetEdges( + TVertex source, + TVertex target, + out IEnumerable edges); + bool TryGetEdge( + TVertex source, + TVertex target, + out TEdge edge); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs.meta new file mode 100644 index 0000000..fc38156 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIncidenceGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 34c75defbe4234c21abadebb31230258 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs new file mode 100755 index 0000000..0bfd7c3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface ICountable : IEnumerable + { + int Count { get;} + } + + public interface IIndexable : ICountable + { + T this[int index] { get;} + int IndexOf(T v); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs.meta new file mode 100644 index 0000000..8209419 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedEnumerable.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78f86e9bc7c4e468282fa4204625e4cf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs new file mode 100755 index 0000000..a4f730e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IIndexedImplicitGraph : IImplicitGraph + where TEdge : IEdge + { + IIndexable Vertices { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs.meta new file mode 100644 index 0000000..14223b3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedImplicitGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b96547dc665794dd89f749e1930c71a4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs new file mode 100755 index 0000000..e0b90c4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IIndexedVertexListGraph : + IVertexListGraph, + IIndexedImplicitGraph + where TEdge : IEdge + { + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs.meta new file mode 100644 index 0000000..5040b65 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IIndexedVertexListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 47d23c3d8005848dd853a60f4a5149e6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs new file mode 100755 index 0000000..1a7199f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs @@ -0,0 +1,12 @@ +namespace QuickGraph +{ + public interface IMutableBidirectionalGraph : + IMutableVertexAndEdgeListGraph, + IBidirectionalGraph + where TEdge : IEdge + { + int RemoveInEdgeIf(TVertex v, EdgePredicate edgePredicate); + void ClearInEdges(TVertex v); + void ClearEdges(TVertex v); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs.meta new file mode 100644 index 0000000..f1060c3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableBidirectionalGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 94992bb5b50fc4b5fa30b8cf31d73fdc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs new file mode 100755 index 0000000..54b71c2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IMutableEdgeListGraph : + IMutableGraph, + IEdgeListGraph + where TEdge : IEdge + { + bool AddEdge(TEdge edge); + event EdgeEventHandler EdgeAdded; + + void AddEdgeRange(IEnumerable edges); + + bool RemoveEdge(TEdge edge); + event EdgeEventHandler EdgeRemoved; + + int RemoveEdgeIf(EdgePredicate predicate); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs.meta new file mode 100644 index 0000000..0e0b218 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableEdgeListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d15c0347c1b82451eab9189740a74818 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs new file mode 100755 index 0000000..88883fe --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs @@ -0,0 +1,10 @@ +using System; + +namespace QuickGraph +{ + public interface IMutableGraph : IGraph + where TEdge : IEdge + { + void Clear(); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs.meta new file mode 100644 index 0000000..c4b8aff --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1fa89b06a7e3d4a98b3c0f9407fc31a7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs new file mode 100755 index 0000000..1b7305e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs @@ -0,0 +1,17 @@ +using System; + +namespace QuickGraph +{ + public interface IMutableIncidenceGraph : + IMutableGraph, + IIncidenceGraph + where TEdge : IEdge + { + int RemoveOutEdgeIf( + TVertex v, + EdgePredicate predicate); + void ClearOutEdges(TVertex v); + + void TrimEdgeExcess(); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs.meta new file mode 100644 index 0000000..5a4ec5c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableIncidenceGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 617ac68d3ef3240bf83a07a340c3e6b6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs new file mode 100755 index 0000000..1c04545 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IMutableUndirectedGraph : + IMutableEdgeListGraph, + IUndirectedGraph + where TEdge : IEdge + { + int RemoveAdjacentEdgeIf(TVertex vertex, EdgePredicate predicate); + void ClearAdjacentEdges(TVertex vertex); + + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs.meta new file mode 100644 index 0000000..83034ce --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableUndirectedGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 84cb84bd5ae704832addcb42fdfa956f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs new file mode 100755 index 0000000..ef609fa --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs @@ -0,0 +1,13 @@ +using System; + +namespace QuickGraph +{ + public interface IMutableVertexAndEdgeListGraph : + IMutableVertexListGraph, + IMutableEdgeListGraph, + IVertexAndEdgeListGraph + where TEdge : IEdge + { + bool AddVerticesAndEdge(TEdge e); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs.meta new file mode 100644 index 0000000..1fa714d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexAndEdgeListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9094cb7a18d04733a3498c4fb56d64d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs new file mode 100755 index 0000000..f207346 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public delegate bool EdgePredicate(TEdge e) + where TEdge : IEdge; + + public delegate bool VertexPredicate(TVertex v); + + public interface IMutableVertexListGraph : + IMutableIncidenceGraph, + IVertexListGraph + where TEdge : IEdge + { + event VertexEventHandler VertexAdded; + void AddVertex(TVertex v); + void AddVertexRange(IEnumerable vertices); + + event VertexEventHandler VertexRemoved; + bool RemoveVertex(TVertex v); + int RemoveVertexIf(VertexPredicate pred); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs.meta new file mode 100644 index 0000000..38acdad --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IMutableVertexListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bef1ab22e478f4b9f8fe56da8b6cfcb5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs new file mode 100755 index 0000000..322f9d7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs @@ -0,0 +1,9 @@ +using System; + +namespace QuickGraph +{ + public interface IPredicate + { + bool Test(T t); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs.meta new file mode 100644 index 0000000..da7abfe --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IPredicate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fb703a21c4bdf48b4b4cbd9c89a67a47 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs new file mode 100755 index 0000000..1060c55 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IUndirectedGraph : + IVertexAndEdgeSet, + IGraph + where TEdge : IEdge + { + IEnumerable AdjacentEdges(TVertex v); + int AdjacentDegree(TVertex v); + bool IsAdjacentEdgesEmpty(TVertex v); + TEdge AdjacentEdge(TVertex v, int index); + + bool ContainsEdge(TVertex source, TVertex target); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs.meta new file mode 100644 index 0000000..343f1ac --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IUndirectedGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 70e83054455104f97b5197ca9ea02ba1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs new file mode 100755 index 0000000..01aba20 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs @@ -0,0 +1,11 @@ +using System; + +namespace QuickGraph +{ + public interface IVertexAndEdgeListGraph : + IVertexListGraph, + IEdgeListGraph, + IVertexAndEdgeSet + where TEdge : IEdge + {} +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs.meta new file mode 100644 index 0000000..2a12d57 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f4c444d4914b4e3e98085c99ea5ac4f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs new file mode 100755 index 0000000..fbc1a57 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IVertexAndEdgeSet : + IVertexSet, + IEdgeListGraph + where TEdge : IEdge + { + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs.meta new file mode 100644 index 0000000..3bffc9e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexAndEdgeSet.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 025f7bf79d2af427ab048d4e50691e7f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs new file mode 100755 index 0000000..ab59492 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs @@ -0,0 +1,9 @@ +using System; + +namespace QuickGraph +{ + public interface IVertexFactory + { + TVertex CreateVertex(); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs.meta new file mode 100644 index 0000000..2331f52 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8b92d61fb306f4a028b182501424f70d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs new file mode 100755 index 0000000..61e095f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public interface IVertexListGraph : + IIncidenceGraph, + IVertexSet + where TEdge : IEdge + { + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs.meta new file mode 100644 index 0000000..bce3cef --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a82a088642ce4e32b5869e261cb7459 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs new file mode 100755 index 0000000..60bc4a2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IVertexSet + { + bool IsVerticesEmpty { get;} + int VertexCount { get;} + IEnumerable Vertices { get;} + bool ContainsVertex(TVertex vertex); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs.meta new file mode 100644 index 0000000..da9d579 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IVertexSet.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f548e9bd90b34eabacbeb22e430424b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs new file mode 100755 index 0000000..b7a7ad6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public interface IView + where TEdge : IEdge + { + IHierarchy Hierarchy { get;} + void Expand(TVertex vertex); + void Collapse(TVertex vertex); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs.meta new file mode 100644 index 0000000..f08be1d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IView.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b9f7546e5357d4b789586a7c1ffc036d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs new file mode 100755 index 0000000..6202398 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs @@ -0,0 +1,33 @@ +using System; + +namespace QuickGraph +{ + public class IdentifiableEdge : Edge, IIdentifiable + { + private string id; + + public IdentifiableEdge(string id, TVertex source, TVertex target) + : base(source, target) + { + this.id = id; + } + + public string ID + { + get { return this.id; } + } + + public override string ToString() + { + return this.id; + } + } + + public sealed class IdentifiableEdgeFactory : IIdentifiableEdgeFactory> + { + public IdentifiableEdge CreateEdge(string id, TVertex source, TVertex target) + { + return new IdentifiableEdge(id, source, target); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs.meta new file mode 100644 index 0000000..f28f834 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a4340b56909914a8eac85bcc017f991b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs new file mode 100755 index 0000000..a3765e5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace QuickGraph +{ + public class IdentifiableVertex : IIdentifiable + { + private string id; + + public IdentifiableVertex(string id) + { + this.id = id; + } + + public string ID + { + get { return this.id; } + } + + public override string ToString() + { + return this.id; + } + } + + public sealed class IdentifiableVertexFactory : IIdentifiableVertexFactory + { + public IdentifiableVertex CreateVertex(string id) + { + return new IdentifiableVertex(id); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs.meta new file mode 100644 index 0000000..8fdaf5d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IdentifiableVertex.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 04fd1f235bda64e64a61ba929efffa79 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs new file mode 100755 index 0000000..d8cb0cf --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + [Serializable] + public sealed class IntVertexFactory :IVertexFactory + { + private int current; + + public int CreateVertex() + { + return current++; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs.meta new file mode 100644 index 0000000..7b5180f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/IntVertexFactory.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 111fb918911de4b9386e73cb91007134 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs new file mode 100755 index 0000000..e82b465 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs @@ -0,0 +1,26 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public class NamedEdge : Edge + { + private readonly string name; + public NamedEdge(TVertex source, TVertex target, string name) + :base(source,target) + { + GraphContracts.AssumeNotNull(name, "name"); + this.name = name; + } + + public string Name + { + get { return this.name; } + } + + public override string ToString() + { + return this.Name; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs.meta new file mode 100644 index 0000000..f10c7d0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NamedEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a815de1dd19b4fb5a995543aa2eb3fb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs new file mode 100755 index 0000000..f680131 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs @@ -0,0 +1,17 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public class NonAcyclicGraphException : ApplicationException + { + public NonAcyclicGraphException() { } + public NonAcyclicGraphException(string message) : base( message ) { } + public NonAcyclicGraphException(string message, System.Exception inner) : base( message, inner ) { } + protected NonAcyclicGraphException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base( info, context ) { } + } +} + + diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs.meta new file mode 100644 index 0000000..15ecd88 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NonAcyclicGraphException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e73657fedd18e48668c9563a9dc75920 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs new file mode 100755 index 0000000..ff5c833 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs @@ -0,0 +1,14 @@ +using System; +namespace QuickGraph +{ + [System.Serializable] + public class NotStronglyConnectedGraphException : System.ApplicationException + { + public NotStronglyConnectedGraphException() { } + public NotStronglyConnectedGraphException(string message) : base( message ) { } + public NotStronglyConnectedGraphException(string message, System.Exception inner) : base( message, inner ) { } + protected NotStronglyConnectedGraphException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base( info, context ) { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs.meta new file mode 100644 index 0000000..5398500 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/NotStronglyConnectedGraphException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7e6bc7bef35bd414c91d584975e3ee09 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs new file mode 100755 index 0000000..94b0259 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs @@ -0,0 +1,15 @@ +using System; + +namespace QuickGraph +{ + [System.Serializable] + public class ParallelEdgeNotAllowedException : System.ApplicationException + { + public ParallelEdgeNotAllowedException() { } + public ParallelEdgeNotAllowedException(string message) : base( message ) { } + public ParallelEdgeNotAllowedException(string message, System.Exception inner) : base( message, inner ) { } + protected ParallelEdgeNotAllowedException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base( info, context ) { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs.meta new file mode 100644 index 0000000..606aba3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ParallelEdgeNotAllowedException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d0add793b3a34dc2ba918a767969384 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri.meta new file mode 100644 index 0000000..877e6a4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: eb431530743fa4a01a7a618b2492f4dd +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs new file mode 100755 index 0000000..5eb42aa --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Petri +{ + [Serializable] + public sealed class AllwaysTrueConditionExpression : IConditionExpression + { + public bool IsEnabled(IList tokens) + { + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs.meta new file mode 100644 index 0000000..a67bada --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/AllwaysTrueConditionExpression.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2bc883b74e52e4f6196ffb5f734b49c9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs new file mode 100755 index 0000000..5e620d2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs @@ -0,0 +1,73 @@ +using System; + +namespace QuickGraph.Petri +{ + [Serializable] + internal sealed class Arc : Edge, + IArc + { + private bool isInputArc; + private IPlace place; + private ITransition transition; + private IExpression annotation = new IdentityExpression(); + + public Arc(IPlace place, ITransition transition) + :base(place,transition) + { + this.place=place; + this.transition=transition; + this.isInputArc=true; + } + public Arc(ITransition transition,IPlace place) + :base(place,transition) + { + this.place=place; + this.transition=transition; + this.isInputArc=false; + } + + public bool IsInputArc + { + get + { + return this.isInputArc; + } + } + + public IPlace Place + { + get + { + return this.place; + } + } + + public ITransition Transition + { + get + { + return this.transition; + } + } + + public IExpression Annotation + { + get + { + return this.annotation; + } + set + { + this.annotation=value; + } + } + + public override string ToString() + { + if (this.IsInputArc) + return String.Format("{0} -> {1}",this.place,this.transition); + else + return String.Format("{0} -> {1}",this.transition,this.place); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs.meta new file mode 100644 index 0000000..6e30383 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Arc.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a978eddba0b404902958613263bd49d7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs new file mode 100755 index 0000000..df90fd3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs @@ -0,0 +1,72 @@ +using System; + +namespace QuickGraph.Petri +{ + /// + /// A directed edge of a net which may connect a + /// to a or a to + /// a . + /// + /// + /// + /// Usually represented by an arrow. + /// + /// + public interface IArc : IEdge + { + /// + /// Gets or sets a value indicating if the + /// instance is a input arc. + /// + /// + /// + /// An arc that leads from an input to a + /// is called an Input Arc of + /// the transition. + /// + /// + bool IsInputArc {get;} + + /// + /// Gets or sets the instance attached to the + /// . + /// + /// + /// The attached to the . + /// + /// + /// set property, value is a null reference (Nothing in Visual Basic). + /// + IPlace Place {get;} + + /// + /// Gets or sets the instance attached to the + /// . + /// + /// + /// The attached to the . + /// + /// + /// set property, value is a null reference (Nothing in Visual Basic). + /// + ITransition Transition{get;} + + /// + /// Gets or sets the arc annotation. + /// + /// + /// The annotation instance. + /// + /// + /// + /// An expression that may involve constans, variables and operators + /// used to annotate the arc. The expression evaluates over the type + /// of the arc's associated place. + /// + /// + /// + /// set property, value is a null reference (Nothing in Visual Basic). + /// + IExpression Annotation {get;set;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs.meta new file mode 100644 index 0000000..ec5716a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IArc.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7ee7b0f50dfcc41b7b93b9e3a801e1be +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs new file mode 100755 index 0000000..7556282 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Petri +{ + public interface IConditionExpression + { + bool IsEnabled(IList tokens); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs.meta new file mode 100644 index 0000000..c78cb9a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IConditionExpression.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 571a1cefd96384e479e7b4d0daf0fa8a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs new file mode 100755 index 0000000..818aad6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Petri +{ + public interface IExpression + { + IList Eval(IList marking); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs.meta new file mode 100644 index 0000000..321f2d6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IExpression.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d7812067b92945b787d5d85b8c79dfa +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs new file mode 100755 index 0000000..556d9a0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs @@ -0,0 +1,12 @@ +using System; + +namespace QuickGraph.Petri +{ + public interface IMutablePetriNet : IPetriNet + { + IPlace AddPlace(string name); + ITransition AddTransition(string name); + IArc AddArc(IPlace place, ITransition transition); + IArc AddArc(ITransition transition, IPlace place); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs.meta new file mode 100644 index 0000000..4ac00d1 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IMutablePetriNet.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 51716fab6203e482f8f047de24c29ab6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs new file mode 100755 index 0000000..89e15e0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs @@ -0,0 +1,7 @@ +using System; + +namespace QuickGraph.Petri +{ + public interface IPetriGraph : IMutableBidirectionalGraph> + {} +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs.meta new file mode 100644 index 0000000..27c0cbf --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e2acb5dddcc04dbf84980c516ff88b7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs new file mode 100755 index 0000000..5939ff4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Petri +{ + /// + /// A High Level Petri Graph. + /// + /// + /// + /// This object is called a Petri Net in honour of Petri's work. In fact, + /// it should be named High Level Petri Graph. + /// + /// + public interface IPetriNet + { + /// + /// Gets a collection of instances. + /// + /// + /// A collection of instances. + /// + IList> Places {get;} + + /// + /// Gets a collection of instances. + /// + /// + /// A collection of instances. + /// + IList> Transitions { get;} + + /// + /// Gets a collection of instances. + /// + /// + /// A collection of instances. + /// + IList> Arcs { get;} + + IPetriGraph Graph { get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs.meta new file mode 100644 index 0000000..a6d229d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriNet.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 187e5a8292f4d401b8430565e7ef45b7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs new file mode 100755 index 0000000..64252cb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs @@ -0,0 +1,18 @@ +using System; + +namespace QuickGraph.Petri +{ + /// + /// A vertex (node) of a Petri Graph. + /// + public interface IPetriVertex + { + /// + /// Gets or sets the name of the node + /// + /// + /// A representing the name of the node. + /// + String Name {get;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs.meta new file mode 100644 index 0000000..e87043a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPetriVertex.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3e0160ec1afc41239acf01ff59efedb +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs new file mode 100755 index 0000000..1569b65 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Petri +{ + /// + /// A Place in the HLPN framework + /// + /// + /// + /// A is characterized by a set of tokens, called the + /// of the place. The place is typed + /// by the instance. This means only object + /// of assignable to can reside + /// in the place. + /// + /// + /// Usually represented by an ellipses (often circles). + /// + /// + public interface IPlace : IPetriVertex + { + IList Marking {get;} + + string ToStringWithMarking(); + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs.meta new file mode 100644 index 0000000..252d430 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IPlace.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48948ea1afc404c8784fa5f490671f56 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs new file mode 100755 index 0000000..4d4d5d5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs @@ -0,0 +1,20 @@ +using System; + +namespace QuickGraph.Petri +{ + /// + /// A node of a net, taken from the transition kind. + /// + /// + /// + /// Usually represented by a rectangle. + /// + /// + public interface ITransition : IPetriVertex + { + /// + /// A boolean expression associated with the transition + /// + IConditionExpression Condition {get;set;} + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs.meta new file mode 100644 index 0000000..e9f8ac8 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/ITransition.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e0e98a11a7f14ef59fe4c8e96882c52 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs new file mode 100755 index 0000000..d7d6b5e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Petri +{ + public sealed class IdentityExpression :IExpression + { + public IList Eval(IList marking) + { + return marking; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs.meta new file mode 100644 index 0000000..4a042a0 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/IdentityExpression.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22d42e25780ad4fbcae00177a3096526 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs new file mode 100755 index 0000000..32ae96a --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs @@ -0,0 +1,14 @@ +using System; + +namespace QuickGraph.Petri +{ + [Serializable] + internal sealed class PetriGraph : + BidirectionalGraph>, + IPetriGraph + { + public PetriGraph() + :base(true) + { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs.meta new file mode 100644 index 0000000..e0d30bb --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fc31dee79315f4b49afc0750e31bc20f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs new file mode 100755 index 0000000..9d93738 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace QuickGraph.Petri +{ + [Serializable] + public sealed class PetriNet : IMutablePetriNet + { + private List> places = new List>(); + private List> transitions = new List>(); + private List> arcs = new List>(); + private PetriGraph graph = new PetriGraph(); + + public PetriNet() + {} + + public IPetriGraph Graph + { + get + { + return this.graph; + } + } + + public IPlace AddPlace(string name) + { + IPlace p = new Place(name); + this.places.Add(p); + this.graph.AddVertex(p); + return p; + } + public ITransition AddTransition(string name) + { + ITransition tr = new Transition(name); + this.transitions.Add(tr); + this.graph.AddVertex(tr); + return tr; + } + public IArc AddArc(IPlace place, ITransition transition) + { + IArc arc = new Arc(place, transition); + this.arcs.Add(arc); + this.graph.AddEdge(arc); + return arc; + } + public IArc AddArc(ITransition transition,IPlace place) + { + IArc arc=new Arc(transition,place); + this.arcs.Add(arc); + this.graph.AddEdge(arc); + return arc; + } + + public IList> Places + { + get + { + return this.places; + } + } + + public IList> Transitions + { + get + { + return this.transitions; + } + } + + public IList> Arcs + { + get + { + return this.arcs; + } + } + + public override string ToString() + { + StringWriter sw = new StringWriter(); + sw.WriteLine("-----------------------------------------------"); + sw.WriteLine("Places ({0})",this.places.Count); + foreach (IPlace place in this.places) + { + sw.WriteLine("\t{0}",place.ToStringWithMarking()); + } + + sw.WriteLine("Transitions ({0})",this.transitions.Count); + foreach (ITransition transition in this.transitions) + { + sw.WriteLine("\t{0}",transition); + } + + sw.WriteLine("Arcs"); + foreach (IArc arc in this.arcs) + { + sw.WriteLine("\t{0}",arc); + } + return sw.ToString(); + } + + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs.meta new file mode 100644 index 0000000..e605a17 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNet.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82e27f8dd90a94acbb514c7fc2e1b81a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs new file mode 100755 index 0000000..cd716d5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Petri +{ + [Serializable] + public sealed class PetriNetSimulator + { + private IPetriNet net; + private Dictionary, TransitionBuffer> transitionBuffers = new Dictionary, TransitionBuffer>(); + + public PetriNetSimulator(IPetriNet net) + { + if (net == null) + throw new ArgumentNullException("net"); + this.net = net; + } + + public IPetriNet Net + { + get + { + return this.net; + } + } + + public void Initialize() + { + this.transitionBuffers.Clear(); + foreach(ITransition tr in this.Net.Transitions) + { + this.transitionBuffers.Add(tr, new TransitionBuffer()); + } + } + + public void SimulateStep() + { + // first step, iterate over arc and gather tokens in transitions + foreach(IArc arc in this.Net.Arcs) + { + if(!arc.IsInputArc) + continue; + + IList tokens = this.transitionBuffers[arc.Transition].Tokens; + // get annotated tokens + IList annotatedTokens = arc.Annotation.Eval(arc.Place.Marking); + //add annontated tokens + foreach(Token annotatedToken in annotatedTokens) + tokens.Add(annotatedToken); + } + + // second step, see which transition was enabled + foreach(ITransition tr in this.Net.Transitions) + { + // get buffered tokens + IList tokens = this.transitionBuffers[tr].Tokens; + // check if enabled, store value + this.transitionBuffers[tr].Enabled = tr.Condition.IsEnabled(tokens); + } + + // third step, iterate over the arcs + foreach(IArc arc in this.Net.Arcs) + { + if (!this.transitionBuffers[arc.Transition].Enabled) + continue; + + if(arc.IsInputArc) + { + // get annotated tokens + IList annotatedTokens = arc.Annotation.Eval(arc.Place.Marking); + // remove annotated comments from source place + foreach(Token annotatedToken in annotatedTokens) + arc.Place.Marking.Remove(annotatedToken); + } + else + { + IList tokens = this.transitionBuffers[arc.Transition].Tokens; + // get annotated tokens + IList annotatedTokens = arc.Annotation.Eval(tokens); + // IList annotated comments to target place + foreach(Token annotatedToken in annotatedTokens) + arc.Place.Marking.Add(annotatedToken); + } + } + // step four, clear buffers + foreach(ITransition tr in this.Net.Transitions) + { + this.transitionBuffers[tr].Tokens.Clear(); + this.transitionBuffers[tr].Enabled = false; + } + } + + private sealed class TransitionBuffer + { + private IList tokens = new List(); + private bool enabled = true; + + public IList Tokens + { + get { return this.tokens;} + } + public bool Enabled + { + get { return this.enabled; } + set { this.enabled = value; } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs.meta new file mode 100644 index 0000000..48a178b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/PetriNetSimulator.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6cad41f0e341d41148d5bf3b10acca25 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs new file mode 100755 index 0000000..a77b29f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace QuickGraph.Petri +{ + [Serializable] + internal sealed class Place : IPlace + { + private string name; + private IList marking = new List(); + + public Place(string name) + { + this.name=name; + } + + public IList Marking + { + get + { + return this.marking; + } + } + + public String Name + { + get + { + return this.name; + } + } + + public string ToStringWithMarking() + { + StringWriter sw = new StringWriter(); + sw.WriteLine(this.ToString()); + foreach(object token in this.marking) + sw.WriteLine("\t{0}",token.GetType().Name); + + return sw.ToString(); + + } + public override string ToString() + { + return String.Format("P({0}|{1})",this.name,this.marking.Count); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs.meta new file mode 100644 index 0000000..1abbf92 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Place.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d4fbf1953e38c45138d9c49c3cd38f44 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs new file mode 100755 index 0000000..82f7d1e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs @@ -0,0 +1,36 @@ +using System; + +namespace QuickGraph.Petri +{ + [Serializable] + internal sealed class Transition : ITransition + { + private string name; + private IConditionExpression condition = new AllwaysTrueConditionExpression(); + + public Transition(string name) + {this.name=name;} + + public IConditionExpression Condition + { + get + { + return this.condition; + } + set + { + this.condition=value; + } + } + + public string Name + { + get{return name;} + } + + public override string ToString() + { + return String.Format("T({0})",this.name); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs.meta new file mode 100644 index 0000000..620be62 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Petri/Transition.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 64b2b6e1c40054eec84b16390d06770b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates.meta new file mode 100644 index 0000000..81ebf2d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 5fbd20515f48941528ee10c8397f5617 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs new file mode 100755 index 0000000..6408907 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs @@ -0,0 +1,14 @@ +using System; + +namespace QuickGraph.Predicates +{ + [Serializable] + public sealed class AnyEdgePredicate + where TEdge : IEdge + { + public bool Test(TEdge edge) + { + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs.meta new file mode 100644 index 0000000..d6626db --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyEdgePredicate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cecd169aa868746678e86135e54e9c4b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs new file mode 100755 index 0000000..460c8dd --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs @@ -0,0 +1,13 @@ +using System; + +namespace QuickGraph.Predicates +{ + [Serializable] + public sealed class AnyVertexPredicate + { + public bool Test(TVertex vertex) + { + return true; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs.meta new file mode 100644 index 0000000..c0b1945 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/AnyVertexPredicate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7f463f9d95e344b168420e236dca53ab +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs new file mode 100755 index 0000000..aef8712 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Predicates +{ + [Serializable] + public class FilteredBidirectionalGraph : + FilteredVertexListGraph, + IBidirectionalGraph + where TEdge : IEdge + where TGraph : IVertexAndEdgeListGraph + { + public FilteredBidirectionalGraph( + TGraph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + :base(baseGraph,vertexPredicate,edgePredicate) + { } + + public bool IsInEdgesEmpty(TVertex v) + { + return this.InDegree(v) == 0; + } + + public int InDegree(TVertex v) + { + int count = 0; + foreach (var edge in this.InEdges(v)) + if (TestEdge(edge)) + count++; + return count; + } + + public IEnumerable InEdges(TVertex v) + { + foreach (var edge in this.InEdges(v)) + if (TestEdge(edge)) + yield return edge; + } + + public int Degree(TVertex v) + { + return this.OutDegree(v) + this.InDegree(v); + } + + public bool IsEdgesEmpty + { + get + { + foreach (var edge in this.BaseGraph.Edges) + if (TestEdge(edge)) + return false; + return true; + } + } + + public int EdgeCount + { + get + { + int count = 0; + foreach (var edge in this.BaseGraph.Edges) + if (TestEdge(edge)) + count++; + return count; + } + } + + public IEnumerable Edges + { + get + { + foreach (var edge in this.BaseGraph.Edges) + if (TestEdge(edge)) + yield return edge; + } + } + + public bool ContainsEdge(TEdge edge) + { + if (!TestEdge(edge)) + return false; + return this.BaseGraph.ContainsEdge(edge); + } + + public TEdge InEdge(TVertex v, int index) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs.meta new file mode 100644 index 0000000..2ca994c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredBidirectionalGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ae3019de17a6e4105ac4426a1e43045c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs new file mode 100755 index 0000000..36e825c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Predicates +{ + [Serializable] + public sealed class FilteredEdgeListGraph : + FilteredGraph, + IEdgeListGraph + where TGraph : IEdgeListGraph + where TEdge : IEdge + { + public FilteredEdgeListGraph( + TGraph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + :base(baseGraph, vertexPredicate, edgePredicate) + { + } + public bool IsEdgesEmpty + { + get + { + foreach(TEdge edge in this.Edges) + return false; + return true; + } + } + + public int EdgeCount + { + get + { + int count = 0; + foreach(TEdge edge in this.Edges) + count++; + return count; + } + } + + public IEnumerable Edges + { + get + { + foreach(TEdge edge in this.BaseGraph.Edges) + { + if ( + this.VertexPredicate(edge.Source) + && this.VertexPredicate(edge.Target) + && this.EdgePredicate(edge) + ) + yield return edge; + } + } + } + + public bool ContainsEdge(TEdge edge) + { + if ( + this.VertexPredicate(edge.Source) + && this.VertexPredicate(edge.Target) + && this.EdgePredicate(edge) + ) + return this.BaseGraph.ContainsEdge(edge); + else + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs.meta new file mode 100644 index 0000000..d8a923f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredEdgeListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 64294ec0ba8fa413795327ec5852ba44 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs new file mode 100755 index 0000000..92cdbc9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs @@ -0,0 +1,81 @@ +using System; + +namespace QuickGraph.Predicates +{ + [Serializable] + public class FilteredGraph : IGraph + where TEdge : IEdge + where TGraph : IGraph + { + private TGraph baseGraph; + private EdgePredicate edgePredicate; + private VertexPredicate vertexPredicate; + + public FilteredGraph( + TGraph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + { + if (baseGraph == null) + throw new ArgumentNullException("baseGraph"); + if (vertexPredicate == null) + throw new ArgumentNullException("vertexPredicate"); + if (edgePredicate == null) + throw new ArgumentNullException("edgePredicate"); + this.baseGraph = baseGraph; + this.vertexPredicate = vertexPredicate; + this.edgePredicate = edgePredicate; + } + + /// + /// Underlying filtered graph + /// + public TGraph BaseGraph + { + get + { + return baseGraph; + } + } + + /// + /// Edge predicate used to filter the edges + /// + public EdgePredicate EdgePredicate + { + get + { + return edgePredicate; + } + } + + public VertexPredicate VertexPredicate + { + get + { + return vertexPredicate; + } + } + + protected bool TestEdge(TEdge edge) + { + return this.VertexPredicate(edge.Source) + && this.VertexPredicate(edge.Target) + && this.EdgePredicate(edge); + } + + public bool IsDirected + { + get { return this.BaseGraph.IsDirected; } + } + + public bool AllowParallelEdges + { + get + { + return baseGraph.AllowParallelEdges; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs.meta new file mode 100644 index 0000000..8ba1e4d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5cbe97477fbb84f58850c3c8f0750e72 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs new file mode 100755 index 0000000..6557826 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Predicates +{ + [Serializable] + public class FilteredImplicitGraph : + FilteredGraph, + IImplicitGraph + where TEdge : IEdge + where TGraph : IImplicitGraph + { + public FilteredImplicitGraph( + TGraph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + :base(baseGraph,vertexPredicate,edgePredicate) + { } + + public bool IsOutEdgesEmpty(TVertex v) + { + return this.OutDegree(v) == 0; + } + + public int OutDegree(TVertex v) + { + int count =0; + foreach (var edge in this.BaseGraph.OutEdges(v)) + if (this.TestEdge(edge)) + count++; + return count; + } + + public IEnumerable OutEdges(TVertex v) + { + foreach (var edge in this.BaseGraph.OutEdges(v)) + if (this.TestEdge(edge)) + yield return edge; + } + + public TEdge OutEdge(TVertex v, int index) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs.meta new file mode 100644 index 0000000..c6b43c4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredImplicitGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cf8673f01bcd1488a85b8e848a920008 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs new file mode 100755 index 0000000..3aca99c --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Predicates +{ + [Serializable] + public class FilteredIncidenceGraph : + FilteredImplicitGraph, + IIncidenceGraph + where TEdge : IEdge + where TGraph : IIncidenceGraph + { + public FilteredIncidenceGraph( + TGraph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + :base(baseGraph,vertexPredicate,edgePredicate) + {} + + public bool ContainsEdge(TVertex source, TVertex target) + { + if (!this.VertexPredicate(source)) + return false; + if (!this.VertexPredicate(target)) + return false; + + foreach (var edge in this.BaseGraph.OutEdges(source)) + if (edge.Target.Equals(target) && this.EdgePredicate(edge)) + return true; + return false; + } + + public bool TryGetEdge( + TVertex source, + TVertex target, + out TEdge edge) + { + IEnumerable unfilteredEdges; + if (this.VertexPredicate(source) && + this.VertexPredicate(target) && + this.BaseGraph.TryGetEdges(source, target, out unfilteredEdges)) + { + foreach (var ufe in unfilteredEdges) + if (this.EdgePredicate(ufe)) + { + edge = ufe; + return true; + } + } + edge = default(TEdge); + return false; + } + + public bool TryGetEdges( + TVertex source, + TVertex target, + out IEnumerable edges) + { + edges = null; + if (!this.VertexPredicate(source)) + return false; + if (!this.VertexPredicate(target)) + return false; + + IEnumerable unfilteredEdges; + if (this.BaseGraph.TryGetEdges(source, target, out unfilteredEdges)) + { + List filtered = new List(); + foreach (var edge in unfilteredEdges) + if (this.EdgePredicate(edge)) + filtered.Add(edge); + edges = filtered; + return true; + } + + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs.meta new file mode 100644 index 0000000..696a83e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredIncidenceGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f9b27f111ee74551b8e1b3a902eb811 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs new file mode 100755 index 0000000..b612d65 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph.Predicates +{ + [Serializable] + public sealed class FilteredUndirectedGraph : + FilteredGraph, + IUndirectedGraph + where TEdge : IEdge + where TGraph : IUndirectedGraph + { + public FilteredUndirectedGraph( + TGraph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + : base(baseGraph, vertexPredicate, edgePredicate) + { } + + public IEnumerable AdjacentEdges(TVertex v) + { + if (this.VertexPredicate(v)) + { + foreach (var edge in this.BaseGraph.AdjacentEdges(v)) + { + if (TestEdge(edge)) + yield return edge; + } + } + } + + public int AdjacentDegree(TVertex v) + { + int count = 0; + foreach (var edge in this.AdjacentEdges(v)) + count++; + return count; + } + + public bool IsAdjacentEdgesEmpty(TVertex v) + { + foreach (var edge in this.AdjacentEdges(v)) + return false; + return true; + } + + public TEdge AdjacentEdge(TVertex v, int index) + { + if (this.VertexPredicate(v)) + { + int count = 0; + foreach (var edge in this.AdjacentEdges(v)) + { + if (count == index) + return edge; + count++; + } + } + + throw new IndexOutOfRangeException(); + } + + public bool ContainsEdge(TVertex source, TVertex target) + { + if (!this.VertexPredicate(source)) + return false; + if (!this.VertexPredicate(target)) + return false; + if (!this.BaseGraph.ContainsEdge(source, target)) + return false; + // we need to find the edge + foreach (var edge in this.Edges) + { + if (edge.Source.Equals(source) && edge.Target.Equals(target) + && this.EdgePredicate(edge)) + return true; + } + + return false; + } + + public bool IsEdgesEmpty + { + get + { + foreach (var edge in this.Edges) + return false; + return true; + } + } + + public int EdgeCount + { + get + { + int count = 0; + foreach (var edge in this.Edges) + count++; + return count; + } + } + + public IEnumerable Edges + { + get + { + foreach (var edge in this.BaseGraph.Edges) + if (this.TestEdge(edge)) + yield return edge; + } + } + + public bool ContainsEdge(TEdge edge) + { + if (!this.TestEdge(edge)) + return false; + return this.BaseGraph.ContainsEdge(edge); + } + + public bool IsVerticesEmpty + { + get + { + foreach (var vertex in this.Vertices) + return false; + return true; + } + } + + public int VertexCount + { + get + { + int count = 0; + foreach (var vertex in this.Vertices) + count++; + return count; + } + } + + public IEnumerable Vertices + { + get + { + foreach (var vertex in this.BaseGraph.Vertices) + if (this.VertexPredicate(vertex)) + yield return vertex; + } + } + + public bool ContainsVertex(TVertex vertex) + { + if (!this.VertexPredicate(vertex)) + return false; + else + return this.BaseGraph.ContainsVertex(vertex); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs.meta new file mode 100644 index 0000000..a7dba5f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredUndirectedGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ad496f4316c9e42e7b91caf61ee530dc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs new file mode 100755 index 0000000..b809138 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Predicates +{ + [Serializable] + public class FilteredVertexAndEdgeListGraph : + FilteredVertexListGraph, + IVertexAndEdgeListGraph + where TEdge : IEdge + where TGraph : IVertexAndEdgeListGraph + { + public FilteredVertexAndEdgeListGraph( + TGraph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + :base(baseGraph,vertexPredicate,edgePredicate) + { } + + public bool IsEdgesEmpty + { + get + { + return this.EdgeCount == 0; + } + } + + public int EdgeCount + { + get + { + int count = 0; + foreach (var edge in this.BaseGraph.Edges) + { + if ( + this.VertexPredicate(edge.Source) + && this.VertexPredicate(edge.Target) + && this.EdgePredicate(edge)) + count++; + } + return count; + } + } + + public IEnumerable Edges + { + get + { + foreach(TEdge edge in this.BaseGraph.Edges) + { + if ( + this.VertexPredicate(edge.Source) + && this.VertexPredicate(edge.Target) + && this.EdgePredicate(edge)) + yield return edge; + } + } + } + + public bool ContainsEdge(TEdge edge) + { + foreach (var e in this.Edges) + if (Comparison.Equals(edge, e)) + return true; + return false; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs.meta new file mode 100644 index 0000000..9cec13d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexAndEdgeListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b8d60db21c374a7a9ce1ef6d4ba356d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs new file mode 100755 index 0000000..6b1ce22 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +namespace QuickGraph.Predicates +{ + [Serializable] + public class FilteredVertexListGraph : + FilteredIncidenceGraph, + IVertexListGraph + where TEdge : IEdge + where Graph : IVertexListGraph + { + public FilteredVertexListGraph( + Graph baseGraph, + VertexPredicate vertexPredicate, + EdgePredicate edgePredicate + ) + :base(baseGraph,vertexPredicate,edgePredicate) + { } + + public bool IsVerticesEmpty + { + get + { + foreach (var v in this.Vertices) + return false; + return true; + } + } + + public int VertexCount + { + get + { + int count = 0; + foreach (var v in this.Vertices) + count++; + return count; + } + } + + public IEnumerable Vertices + { + get + { + foreach (var v in this.BaseGraph.Vertices) + if (this.VertexPredicate(v)) + yield return v; + } + } + + public bool ContainsVertex(TVertex vertex) + { + if (!this.VertexPredicate(vertex)) + return false; + return this.ContainsVertex(vertex); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs.meta new file mode 100644 index 0000000..5da0fd2 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/FilteredVertexListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a13407d7965d40f489f97a8575361de +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs new file mode 100755 index 0000000..98eaff3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Predicates +{ + [Serializable] + public sealed class InDictionaryVertexPredicate + { + private IDictionary dictionary; + + public InDictionaryVertexPredicate( + IDictionary dictionary) + { + this.dictionary = dictionary; + } + + public bool Test(TVertex v) + { + if (v == null) + throw new ArgumentNullException("v"); + return this.dictionary.ContainsKey(v); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs.meta new file mode 100644 index 0000000..3f96420 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/InDictionaryVertexPredicate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e1890ebbd76bd4de2a94b5a6f61e9e90 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs new file mode 100755 index 0000000..593a476 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs @@ -0,0 +1,21 @@ +using System; + +namespace QuickGraph.Predicates +{ + public sealed class IsolatedVertexPredicate + where TEdge : IEdge + { + private IBidirectionalGraph visitedGraph; + + public IsolatedVertexPredicate(IBidirectionalGraph visitedGraph) + { + this.visitedGraph = visitedGraph; + } + + public bool Test(TVertex v) + { + return this.visitedGraph.IsInEdgesEmpty(v) + && this.visitedGraph.IsOutEdgesEmpty(v); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs.meta new file mode 100644 index 0000000..d6c05ec --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/IsolatedVertexPredicate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: abdeeb51692a9411ba012bd6b5125ff2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs new file mode 100755 index 0000000..77c2dbf --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph.Predicates +{ + public sealed class ResidualEdgePredicate + where TEdge : IEdge + { + private IDictionary residualCapacities; + + public ResidualEdgePredicate( + IDictionary residualCapacities) + { + if (residualCapacities == null) + throw new ArgumentNullException("residualCapacities"); + this.residualCapacities = residualCapacities; + } + + public IDictionary ResidualCapacities + { + get + { + return this.residualCapacities; + } + } + + public bool Test(TEdge e) + { + if (e == null) + throw new ArgumentNullException("e"); + + return 0 < this.residualCapacities[e]; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs.meta new file mode 100644 index 0000000..25629e3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ResidualEdgePrediate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f90b18959e824cbf9f43323dde682b3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs new file mode 100755 index 0000000..b710a4f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +namespace QuickGraph.Predicates +{ + [Serializable] + public sealed class ReversedResidualEdgePredicate + where TEdge : IEdge + { + private IDictionary residualCapacities; + private IDictionary reversedEdges; + + public ReversedResidualEdgePredicate( + IDictionary residualCapacities, + IDictionary reversedEdges) + { + if (residualCapacities == null) + throw new ArgumentNullException("residualCapacities"); + if (reversedEdges == null) + throw new ArgumentNullException("reversedEdges"); + this.residualCapacities = residualCapacities; + this.reversedEdges = reversedEdges; + } + + /// + /// Residual capacities map + /// + public IDictionary ResidualCapacities + { + get + { + return this.residualCapacities; + } + } + + /// + /// Reversed edges map + /// + public IDictionary ReversedEdges + { + get + { + return this.reversedEdges; + } + } + + public bool Test(TEdge e) + { + if (e == null) + throw new ArgumentNullException("e"); + + return 0 < this.residualCapacities[reversedEdges[e]]; + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs.meta new file mode 100644 index 0000000..89f1cf6 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/ReversedResidualEdgePredicate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 210290ab67b6148f29a617e0e2ace6c6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs new file mode 100755 index 0000000..3247cf4 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs @@ -0,0 +1,23 @@ +using System; + +namespace QuickGraph.Predicates +{ + [Serializable] + public sealed class SinkVertexPredicate + where TEdge : IEdge + { + private IIncidenceGraph visitedGraph; + + public SinkVertexPredicate(IIncidenceGraph visitedGraph) + { + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + this.visitedGraph = visitedGraph; + } + + public bool Test(TVertex v) + { + return this.visitedGraph.IsOutEdgesEmpty(v); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs.meta new file mode 100644 index 0000000..e170f0d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Predicates/SinkVertexPredicate.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22cd39f5c3ec64dc2b1321d43118a1d4 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj new file mode 100755 index 0000000..8e8fbab --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj @@ -0,0 +1,273 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {A9A5C115-0680-44B3-A87E-5ECF4C93814E} + Library + QuickGraph + QuickGraph + 4 + quickgraph.snk + File + true + SAK + SAK + SAK + SAK + + + 2.0 + + + + + true + full + false + .\bin\Debug\ + DEBUG;TRACE + true + 4 + + + Off + 1591 + + + false + true + .\bin\Release\ + TRACE + + + Off + + + + + + + + + + Properties\version.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.meta new file mode 100644 index 0000000..6514e97 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 3f5b494f5091c4385a69c3c4654840fd +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc new file mode 100755 index 0000000..feffdec --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc.meta new file mode 100644 index 0000000..9a4f388 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraph.csproj.vspscc.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: b7e71bab2d13e4f4f9b8f08150a23329 +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs new file mode 100755 index 0000000..3b03996 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.IO; + +namespace QuickGraph +{ + public static class QuickGraphResourceManager + { + public static Image GetLogo() + { + return GetImage("quickgraph"); + } + + public static Image GetBanner() + { + return GetImage("quickgraph.banner"); + } + + private static Image GetImage(string name) + { + using (Stream stream = typeof(QuickGraphResourceManager).Assembly.GetManifestResourceStream(String.Format("QuickGraph.{0}.png", name))) + return Image.FromStream(stream); + } + + public static void DumpResources(string path) + { + if (String.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + GetLogo().Save(Path.Combine(path, "quickgraph.png"), System.Drawing.Imaging.ImageFormat.Png); + GetBanner().Save(Path.Combine(path, "quickgraph.banner.png"), System.Drawing.Imaging.ImageFormat.Png); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs.meta new file mode 100644 index 0000000..f010871 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/QuickGraphResourceManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f466ffd1f349a4baaa902bda1b5e0eb6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs new file mode 100755 index 0000000..7dde126 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public sealed class ReversedBidirectionalGraph : + IBidirectionalGraph> + where TEdge : IEdge + { + private readonly IBidirectionalGraph originalGraph; + public ReversedBidirectionalGraph(IBidirectionalGraph originalGraph) + { + if (originalGraph==null) + throw new ArgumentNullException("originalGraph"); + this.originalGraph = originalGraph; + } + + public IBidirectionalGraph OriginalGraph + { + get { return this.originalGraph;} + } + + public bool IsVerticesEmpty + { + get { return this.OriginalGraph.IsVerticesEmpty; } + } + + public bool IsDirected + { + get { return this.OriginalGraph.IsDirected; } + } + + public bool AllowParallelEdges + { + get { return this.OriginalGraph.AllowParallelEdges; } + } + + public int VertexCount + { + get { return this.OriginalGraph.VertexCount; } + } + + public IEnumerable Vertices + { + get { return this.OriginalGraph.Vertices; } + } + + + public bool ContainsVertex(TVertex vertex) + { + return this.OriginalGraph.ContainsVertex(vertex); + } + + public bool ContainsEdge(TVertex source, TVertex target) + { + return this.OriginalGraph.ContainsEdge(target,source); + } + + public bool TryGetEdge( + TVertex source, + TVertex target, + out ReversedEdge edge) + { + TEdge oedge; + if (this.OriginalGraph.TryGetEdge(target, source, out oedge)) + { + edge = new ReversedEdge(oedge); + return true; + } + else + { + edge = default(ReversedEdge); + return false; + } + } + + public bool TryGetEdges( + TVertex source, + TVertex target, + out IEnumerable> edges) + { + IEnumerable oedges; + if (this.OriginalGraph.TryGetEdges(target, source, out oedges)) + { + List> list = new List>(); + foreach (var oedge in oedges) + list.Add(new ReversedEdge(oedge)); + edges = list; + return true; + } + else + { + edges = null; + return false; + } + } + + public bool IsOutEdgesEmpty(TVertex v) + { + return this.OriginalGraph.IsInEdgesEmpty(v); + } + + public int OutDegree(TVertex v) + { + return this.OriginalGraph.InDegree(v); + } + + public IEnumerable> InEdges(TVertex v) + { + foreach(TEdge edge in this.OriginalGraph.OutEdges(v)) + yield return new ReversedEdge(edge); + } + + public ReversedEdge InEdge(TVertex v, int index) + { + TEdge edge = this.OriginalGraph.OutEdge(v, index); + if (edge == null) + return default(ReversedEdge); + return new ReversedEdge(edge); + } + + public bool IsInEdgesEmpty(TVertex v) + { + return this.OriginalGraph.IsOutEdgesEmpty(v); + } + + public int InDegree(TVertex v) + { + return this.OriginalGraph.OutDegree(v); + } + + public IEnumerable> OutEdges(TVertex v) + { + foreach(TEdge edge in this.OriginalGraph.InEdges(v)) + yield return new ReversedEdge(edge); + } + + public ReversedEdge OutEdge(TVertex v, int index) + { + TEdge edge = this.OriginalGraph.InEdge(v, index); + if (edge == null) + return default(ReversedEdge); + return new ReversedEdge(edge); + } + + public IEnumerable> Edges + { + get + { + foreach(TEdge edge in this.OriginalGraph.Edges) + yield return new ReversedEdge(edge); + } + } + + public bool ContainsEdge(ReversedEdge edge) + { + return this.OriginalGraph.ContainsEdge(edge.OriginalEdge); + } + + public int Degree(TVertex v) + { + return this.OriginalGraph.Degree(v); + } + + public bool IsEdgesEmpty + { + get { return this.OriginalGraph.IsEdgesEmpty; } + } + + public int EdgeCount + { + get { return this.OriginalGraph.EdgeCount; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs.meta new file mode 100644 index 0000000..699f815 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedBidirectionalListGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e269240fbe4c24ee6b02b4df55b1b619 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs new file mode 100755 index 0000000..5f6486b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs @@ -0,0 +1,55 @@ +using System; + +namespace QuickGraph +{ + public struct ReversedEdge : + IEdge, + IEquatable> + where TEdge : IEdge + { + private readonly TEdge originalEdge; + public ReversedEdge(TEdge originalEdge) + { + GraphContracts.AssumeNotNull(originalEdge, "originalEdge"); + this.originalEdge = originalEdge; + } + + public TEdge OriginalEdge + { + get { return this.originalEdge; } + } + + public TVertex Source + { + get { return this.OriginalEdge.Target; } + } + + public TVertex Target + { + get { return this.OriginalEdge.Source; } + } + + public override bool Equals(object obj) + { + if (!(obj is ReversedEdge)) + return false; + + return Equals((ReversedEdge)obj); + } + + public override int GetHashCode() + { + return this.OriginalEdge.GetHashCode(); + } + + public override string ToString() + { + return String.Format("R({0})", this.OriginalEdge); + } + + public bool Equals(ReversedEdge other) + { + return this.OriginalEdge.Equals(other.OriginalEdge); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs.meta new file mode 100644 index 0000000..68349b7 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/ReversedEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a759536443b04adbbdecac8a6bc4de3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs new file mode 100755 index 0000000..1ee7d5f --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs @@ -0,0 +1,15 @@ +using System; + +namespace QuickGraph +{ + [System.Serializable] + public class RootVertexNotSpecifiedException : System.ApplicationException + { + public RootVertexNotSpecifiedException() { } + public RootVertexNotSpecifiedException(string message) : base( message ) { } + public RootVertexNotSpecifiedException(string message, System.Exception inner) : base( message, inner ) { } + protected RootVertexNotSpecifiedException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base( info, context ) { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs.meta new file mode 100644 index 0000000..1415df3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/RootVertexNotSpecifiedException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 97a5fce77186e4ec083824f55763505c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization.meta new file mode 100644 index 0000000..963c274 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 79e8f7f7f1edf4ef5bb684fa623651e3 +folderAsset: yes +DefaultImporter: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs new file mode 100755 index 0000000..8f523f5 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs @@ -0,0 +1,702 @@ +using System; +using System.Collections.Generic; +using System.Xml; +using System.IO; +using System.Text; +using System.Reflection; +using System.Xml.Serialization; +using System.Reflection.Emit; + +namespace QuickGraph.Serialization +{ + /// + /// A GraphML ( http://graphml.graphdrawing.org/ ) format serializer. + /// + /// + /// + /// + /// + /// Custom vertex and edge attributes can be specified by + /// using the + /// attribute on properties (field not suppored). + /// + /// + /// The serializer uses LCG (lightweight code generation) to generate the + /// methods that writes the attributes to avoid paying the price of + /// Reflection on each vertex/edge. Since nothing is for free, the first + /// time you will use the serializer *on a particular pair of types*, it + /// will have to bake that method. + /// + /// + /// Hyperedge, nodes, nested graphs not supported. + /// + /// + public sealed class GraphMLSerializer + : SerializerBase + where TVertex : IIdentifiable + where TEdge : IIdentifiable, IEdge + { + #region Attributes + private delegate void WriteVertexAttributesDelegate( + XmlWriter writer, + TVertex v); + private delegate void WriteEdgeAttributesDelegate( + XmlWriter writer, + TEdge e); + private delegate void ReadVertexAttributesDelegate( + XmlReader reader, + TVertex v); + private delegate void ReadEdgeAttributesDelegate( + XmlReader reader, + TEdge e); + + private static class DelegateCompiler + { + private static readonly object syncRoot = new object(); + private static WriteVertexAttributesDelegate writeVertexAttributesDelegate; + private static WriteEdgeAttributesDelegate writeEdgeAttributesDelegate; + private static ReadVertexAttributesDelegate readVertexAttributesDelegate; + private static ReadEdgeAttributesDelegate readEdgeAttributesDelegate; + + public static WriteVertexAttributesDelegate VertexAttributesWriter + { + get + { + lock (syncRoot) + { + if (writeVertexAttributesDelegate == null) + DelegateCompiler.CreateWriteDelegates(); + return writeVertexAttributesDelegate; + } + } + } + + public static WriteEdgeAttributesDelegate EdgeAttributesWriter + { + get + { + lock (syncRoot) + { + if (writeEdgeAttributesDelegate == null) + DelegateCompiler.CreateWriteDelegates(); + return writeEdgeAttributesDelegate; + } + } + } + + public static ReadVertexAttributesDelegate VertexAttributesReader + { + get + { + lock (syncRoot) + { + if (readVertexAttributesDelegate == null) + DelegateCompiler.CreateReadDelegates(); + return readVertexAttributesDelegate; + } + } + } + + public static ReadEdgeAttributesDelegate EdgeAttributesReader + { + get + { + lock (syncRoot) + { + if (readEdgeAttributesDelegate == null) + DelegateCompiler.CreateReadDelegates(); + return readEdgeAttributesDelegate; + } + } + } + + public static void CreateReadDelegates() + { + readVertexAttributesDelegate = + (ReadVertexAttributesDelegate)CreateReadDelegate( + typeof(ReadVertexAttributesDelegate), + typeof(TVertex), + "id" + ); + readEdgeAttributesDelegate = + (ReadEdgeAttributesDelegate)CreateReadDelegate( + typeof(ReadEdgeAttributesDelegate), + typeof(TEdge), + "id", "source", "target" + ); + } + + public static void CreateWriteDelegates() + { + writeVertexAttributesDelegate = + (WriteVertexAttributesDelegate)CreateWriteDelegate( + typeof(TVertex), + typeof(WriteVertexAttributesDelegate)); + writeEdgeAttributesDelegate = + (WriteEdgeAttributesDelegate)CreateWriteDelegate( + typeof(TEdge), + typeof(WriteEdgeAttributesDelegate) + ); + } + + public static Delegate CreateWriteDelegate(Type nodeType, Type delegateType) + { + DynamicMethod method = new DynamicMethod( + "Write"+delegateType.Name + nodeType.Name, + typeof(void), + new Type[] { typeof(XmlWriter), nodeType }, + nodeType.Module + ); + ILGenerator gen = method.GetILGenerator(); + + MethodInfo writeStartElement = + typeof(XmlWriter).GetMethod( + "WriteStartElement", + BindingFlags.Instance | BindingFlags.Public, + null, + new Type[] { typeof(string) }, + null); + MethodInfo writeEndElement = + typeof(XmlWriter).GetMethod( + "WriteEndElement", + BindingFlags.Instance | BindingFlags.Public, + null, + new Type[] { }, + null); + MethodInfo writeString = + typeof(XmlWriter).GetMethod( + "WriteString", + BindingFlags.Instance | BindingFlags.Public, + null, + new Type[] { typeof(string) }, + null); + MethodInfo writeAttributeString = + typeof(XmlWriter).GetMethod( + "WriteAttributeString", + BindingFlags.Instance | BindingFlags.Public, + null, + new Type[] { typeof(string), typeof(string) }, + null); + MethodInfo toString = typeof(object).GetMethod( + "ToString", + BindingFlags.Public | BindingFlags.Instance, + null, + new Type[] { }, + null); + + foreach (KeyValuePair kv in SerializationHelper.GetAttributeProperties(nodeType)) + { + // for each property of the type, + // write it to the xmlwriter (we need to take care of value types, etc...) + // writer.WriteStartElement("data") + gen.Emit(OpCodes.Ldarg_0); + gen.Emit(OpCodes.Ldstr, "data"); + gen.EmitCall(OpCodes.Callvirt, writeStartElement, null); + + // writer.WriteAttributeString("key", name); + gen.Emit(OpCodes.Ldarg_0); + gen.Emit(OpCodes.Ldstr, "key"); + gen.Emit(OpCodes.Ldstr, kv.Value); + gen.EmitCall(OpCodes.Callvirt, writeAttributeString, null); + + + // writer.WriteString(v.xxx); + gen.Emit(OpCodes.Ldarg_0); + + // we now need to load the vertex and invoke the property + // load vertex + gen.Emit(OpCodes.Ldarg_1); + // invoke property + MethodInfo getMethod = kv.Key.GetGetMethod(); + gen.EmitCall( + (getMethod.IsVirtual) ? OpCodes.Callvirt : OpCodes.Call, + getMethod, + null); + + // since XmlWrite takes to string, we need to convert that + // object to a string... + // of course, if it's a string, we don't need to do anything + Type propertyType = kv.Key.PropertyType; + if (propertyType != typeof(string)) + { + // if it's a value type, it has to be boxed before + // invoking ToString + if (propertyType.IsValueType) + gen.Emit(OpCodes.Box, propertyType); + gen.Emit( + (toString.IsVirtual) ? OpCodes.Callvirt : OpCodes.Call, + toString); + } + + // we now have two string on the stack... + gen.EmitCall(OpCodes.Callvirt, writeString, null); + + // writer.WriteEndElement() + gen.Emit(OpCodes.Ldarg_0); + gen.EmitCall(OpCodes.Callvirt, writeEndElement, null); + } + + gen.Emit(OpCodes.Ret); + + //let's bake the method + return method.CreateDelegate(delegateType); + } + + public static Delegate CreateReadDelegate( + Type delegateType, + Type elementType, + params string[] ignoredAttributes + ) + { + DynamicMethod method = new DynamicMethod( + "Read"+elementType.Name, + typeof(void), + new Type[] { typeof(XmlReader), elementType }, + elementType.Module + ); + ILGenerator gen = method.GetILGenerator(); + + MethodInfo readToFollowing = + typeof(XmlReader).GetMethod( + "ReadToFollowing", + BindingFlags.Instance | BindingFlags.Public, + null, + new Type[] { typeof(string) }, + null); + MethodInfo getAttribute = + typeof(XmlReader).GetMethod( + "GetAttribute", + BindingFlags.Instance | BindingFlags.Public, + null, + new Type[] { typeof(string) }, + null); + MethodInfo stringEquals = + typeof(string).GetMethod( + "op_Equality", + BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, + null, + new Type[] { typeof(string), typeof(string) }, + null); + ConstructorInfo argumentException = + typeof(ArgumentException).GetConstructor(new Type[] { }); + + + // read content as methods + Dictionary readContentMethods = new Dictionary(); + readContentMethods.Add(typeof(int), typeof(XmlReader).GetMethod("ReadElementContentAsInt", new Type[] { })); + readContentMethods.Add(typeof(double), typeof(XmlReader).GetMethod("ReadElementContentAsDouble", new Type[] { })); + readContentMethods.Add(typeof(bool), typeof(XmlReader).GetMethod("ReadElementContentAsBoolean", new Type[] { })); + readContentMethods.Add(typeof(DateTime), typeof(XmlReader).GetMethod("ReadElementContentAsDateTime", new Type[] { })); + readContentMethods.Add(typeof(long), typeof(XmlReader).GetMethod("ReadElementContentAsLong", new Type[] { })); + readContentMethods.Add(typeof(string), typeof(XmlReader).GetMethod("ReadElementContentAsString", new Type[] { })); + + + LocalBuilder key= gen.DeclareLocal(typeof(string)); + + Label start = gen.DefineLabel(); + Label doWhile = gen.DefineLabel(); + + gen.Emit(OpCodes.Br_S, doWhile); + gen.MarkLabel(start); + gen.Emit(OpCodes.Ldarg_0); + gen.Emit(OpCodes.Ldstr, "key"); + gen.EmitCall(OpCodes.Callvirt, getAttribute, null); + gen.Emit(OpCodes.Stloc_0); + + + // if (key.Equals("id")) continue; + foreach (string ignoredAttribute in ignoredAttributes) + { + gen.Emit(OpCodes.Ldloc_0); + gen.Emit(OpCodes.Ldstr, ignoredAttribute); + gen.EmitCall(OpCodes.Call, stringEquals, null); + gen.Emit(OpCodes.Brtrue_S, doWhile); + } + + // we need to create the swicth for each property + Label next = gen.DefineLabel(); + bool first = true; + foreach (KeyValuePair kv in SerializationHelper.GetAttributeProperties(elementType)) + { + if (!first) + { + gen.MarkLabel(next); + next = gen.DefineLabel(); + } + first = false; + + // if (!key.Equals("foo")) + gen.Emit(OpCodes.Ldloc_0); + gen.Emit(OpCodes.Ldstr, kv.Value); + gen.EmitCall(OpCodes.Callvirt, stringEquals,null); + // if false jump to next + gen.Emit(OpCodes.Brfalse_S, next); + + // do our stuff + MethodInfo readMethod = null; + if (!readContentMethods.TryGetValue(kv.Key.PropertyType, out readMethod)) + throw new ArgumentException(String.Format("Property {0} has a non-supported type",kv.Key.Name)); + + // do we have a set method ? + MethodInfo setMethod = kv.Key.GetSetMethod(); + if (setMethod==null) + throw new ArgumentException( + String.Format("Property {0} is readonly", kv.Key.Name) + ); + // reader.ReadXXX + gen.Emit(OpCodes.Ldarg_1); + gen.Emit(OpCodes.Ldarg_0); + gen.EmitCall(OpCodes.Callvirt, readMethod, null); + gen.EmitCall(OpCodes.Callvirt, setMethod, null); + + // jump to do while + gen.Emit(OpCodes.Br_S, doWhile); + } + + // we don't know this parameter.. we throw + gen.MarkLabel(next); + gen.Emit(OpCodes.Newobj, argumentException); + gen.Emit(OpCodes.Throw); + + gen.MarkLabel(doWhile); + gen.Emit(OpCodes.Ldarg_0); + gen.Emit(OpCodes.Ldstr, "data"); + gen.EmitCall(OpCodes.Callvirt, readToFollowing,null); + gen.Emit(OpCodes.Brtrue_S, start); + + gen.Emit(OpCodes.Ret); + + //let's bake the method + return method.CreateDelegate(delegateType); + } + } + #endregion + + public void Serialize(TextWriter writer, IVertexAndEdgeSet visitedGraph) + { + GraphContracts.AssumeNotNull(writer, "writer"); + GraphContracts.AssumeNotNull(visitedGraph, "visitedGraph"); + + using (var xwriter = new XmlTextWriter(writer)) + { + xwriter.Formatting = Formatting.Indented; + Serialize(xwriter, visitedGraph); + } + } + + public void Serialize(Stream stream, Encoding encoding, IVertexAndEdgeSet visitedGraph) + { + if (stream == null) + throw new ArgumentNullException("stream"); + if (encoding == null) + throw new ArgumentNullException("encoding"); + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + + using (var xwriter = new XmlTextWriter(stream, encoding)) + { + xwriter.Formatting = Formatting.Indented; + Serialize(xwriter, visitedGraph); + } + } + + public void Serialize(XmlWriter writer, IVertexAndEdgeSet visitedGraph) + { + if (writer == null) + throw new ArgumentNullException("writer"); + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + + var worker = new WriterWorker(this, writer, visitedGraph); + worker.Serialize(); + } + + public void Deserialize( + XmlReader reader, + IMutableVertexAndEdgeListGraph visitedGraph, + IIdentifiableVertexFactory vertexFactory, + IIdentifiableEdgeFactory edgeFactory) + { + if (reader == null) + throw new ArgumentNullException("reader"); + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + if (vertexFactory == null) + throw new ArgumentNullException("vertexFactory"); + if (edgeFactory == null) + throw new ArgumentNullException("edgeFactory"); + + ReaderWorker worker = new ReaderWorker( + this, + reader, + visitedGraph, + vertexFactory, + edgeFactory); + worker.Deserialize(); + } + + class ReaderWorker + { + private GraphMLSerializer serializer; + private XmlReader reader; + private IMutableVertexAndEdgeListGraph visitedGraph; + private IIdentifiableVertexFactory vertexFactory; + private IIdentifiableEdgeFactory edgeFactory; + + public ReaderWorker( + GraphMLSerializer serializer, + XmlReader reader, + IMutableVertexAndEdgeListGraph visitedGraph, + IIdentifiableVertexFactory vertexFactory, + IIdentifiableEdgeFactory edgeFactory + ) + { + this.serializer = serializer; + this.reader = reader; + this.visitedGraph = visitedGraph; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + } + + public GraphMLSerializer Serializer + { + get { return this.serializer; } + } + + public XmlReader Reader + { + get { return this.reader; } + } + + public IMutableVertexAndEdgeListGraph VisitedGraph + { + get { return this.visitedGraph; } + } + + public void Deserialize() + { + this.ReadHeader(); + this.ReadGraphHeader(); + this.ReadElements(); + } + + private void ReadHeader() + { + // read flow until we hit the graphml node + if (!this.Reader.ReadToFollowing("graphml")) + throw new ArgumentException("graphml node not found"); + } + + private void ReadGraphHeader() + { + if (!this.Reader.ReadToDescendant("graph")) + throw new ArgumentException("graph node not found"); + } + + private void ReadElements() + { + this.Reader.ReadStartElement("graph"); + + Dictionary vertices = new Dictionary(); + + // read vertices or edges + while (this.Reader.Read()) + { + if (this.Reader.NodeType == XmlNodeType.Element) + { + if (this.Reader.Name == "node") + { + // get subtree + XmlReader subReader = this.Reader.ReadSubtree(); + // read id + string id = this.ReadAttributeValue("id"); + // create new vertex + TVertex vertex = vertexFactory.CreateVertex(id); + // read data + GraphMLSerializer.DelegateCompiler.VertexAttributesReader(subReader, vertex); + // add to graph + this.VisitedGraph.AddVertex(vertex); + vertices.Add(vertex.ID, vertex); + } + else if (this.Reader.Name == "edge") + { + // get subtree + XmlReader subReader = reader.ReadSubtree(); + // read id + string id = this.ReadAttributeValue("id"); + string sourceid = this.ReadAttributeValue("source"); + TVertex source; + if (!vertices.TryGetValue(sourceid, out source)) + throw new ArgumentException("Could not find vertex " + sourceid); + string targetid = this.ReadAttributeValue("target"); + TVertex target; + if (!vertices.TryGetValue(targetid, out target)) + throw new ArgumentException("Could not find vertex " + targetid); + + TEdge edge = this.edgeFactory.CreateEdge(id, source, target); + + // read data + GraphMLSerializer.DelegateCompiler.EdgeAttributesReader(subReader, edge); + + this.VisitedGraph.AddEdge(edge); + } + } + } + } + + private string ReadAttributeValue(string attributeName) + { + this.Reader.MoveToAttribute(attributeName); + if (!this.Reader.ReadAttributeValue()) + throw new ArgumentException("missing "+ attributeName +" attribute"); + return this.Reader.Value; + } + } + + private sealed class WriterWorker + { + private GraphMLSerializer serializer; + private XmlWriter writer; + private IVertexAndEdgeSet visitedGraph; + + public WriterWorker( + GraphMLSerializer serializer, + XmlWriter writer, + IVertexAndEdgeSet visitedGraph) + { + this.serializer = serializer; + this.writer = writer; + this.visitedGraph = visitedGraph; + } + + public GraphMLSerializer Serializer + { + get { return this.serializer; } + } + + public XmlWriter Writer + { + get { return this.writer; } + } + + public IVertexAndEdgeSet VisitedGraph + { + get { return this.visitedGraph; } + } + + public void Serialize() + { + this.WriteHeader(); + this.WriteVertexAttributeDefinitions(); + this.WriteEdgeAttributeDefinitions(); + this.WriteGraphHeader(); + this.WriteVertices(); + this.WriteEdges(); + this.WriteGraphFooter(); + this.WriteFooter(); + } + + private void WriteHeader() + { + if (this.Serializer.EmitDocumentDeclaration) + this.Writer.WriteStartDocument(); + this.Writer.WriteStartElement("graphml"); + this.Writer.WriteAttributeString("xmlns","http://graphml.graphdrawing.org/xmlns"); + this.Writer.WriteAttributeString("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); + this.Writer.WriteAttributeString("xsi:schemaLocation", "http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"); + } + + private void WriteFooter() + { + this.Writer.WriteEndElement(); + this.Writer.WriteEndDocument(); + } + + private void WriteGraphHeader() + { + this.Writer.WriteStartElement("graph"); + this.Writer.WriteAttributeString("id", "G"); + this.Writer.WriteAttributeString("edgedefault", + (this.VisitedGraph.IsDirected) ? "directed" : "undirected" + ); + this.Writer.WriteAttributeString("parse.nodes", this.VisitedGraph.VertexCount.ToString()); + this.Writer.WriteAttributeString("parse.edges", this.VisitedGraph.EdgeCount.ToString()); + this.Writer.WriteAttributeString("parse.order", "nodefirst"); + this.Writer.WriteAttributeString("parse.nodeids", "free"); + this.Writer.WriteAttributeString("parse.edgeids", "free"); + } + + private void WriteGraphFooter() + { + this.Writer.WriteEndElement(); + } + + private void WriteVertexAttributeDefinitions() + { + string forNode = "node"; + Type nodeType = typeof(TVertex); + + WriteAttributeDefinitions(forNode, nodeType); + } + + private void WriteEdgeAttributeDefinitions() + { + string forNode = "edge"; + Type nodeType = typeof(TEdge); + + WriteAttributeDefinitions(forNode, nodeType); + } + + private void WriteAttributeDefinitions(string forNode, Type nodeType) + { + foreach (KeyValuePair kv in SerializationHelper.GetAttributeProperties(nodeType)) + { + // + this.Writer.WriteStartElement("key"); + this.Writer.WriteAttributeString("id", kv.Value); + this.Writer.WriteAttributeString("for", forNode); + this.Writer.WriteAttributeString("attr.name", kv.Value); + + Type propertyType = kv.Key.PropertyType; + if (propertyType == typeof(bool)) + this.Writer.WriteAttributeString("attr.type", "boolean"); + else if (propertyType == typeof(int)) + this.Writer.WriteAttributeString("attr.type", "int"); + else if (propertyType == typeof(long)) + this.Writer.WriteAttributeString("attr.type", "long"); + else if (propertyType == typeof(float)) + this.Writer.WriteAttributeString("attr.type", "float"); + else if (propertyType == typeof(double)) + this.Writer.WriteAttributeString("attr.type", "double"); + else + this.Writer.WriteAttributeString("attr.type", "string"); + this.Writer.WriteEndElement(); + } + } + + private void WriteVertices() + { + foreach (var v in this.VisitedGraph.Vertices) + { + this.Writer.WriteStartElement("node"); + this.Writer.WriteAttributeString("id", v.ID); + GraphMLSerializer.DelegateCompiler.VertexAttributesWriter(this.Writer, v); + this.Writer.WriteEndElement(); + } + } + + private void WriteEdges() + { + foreach (var e in this.VisitedGraph.Edges) + { + this.Writer.WriteStartElement("edge"); + this.Writer.WriteAttributeString("id", e.ID); + this.Writer.WriteAttributeString("source", e.Source.ID); + this.Writer.WriteAttributeString("target", e.Target.ID); + GraphMLSerializer.DelegateCompiler.EdgeAttributesWriter(this.Writer, e); + this.Writer.WriteEndElement(); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs.meta new file mode 100644 index 0000000..95f2e08 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/GraphMLSerializer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7cdec9573f05040cfaa52653d6ccafc3 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs new file mode 100755 index 0000000..48d3396 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Xml.Serialization; + +namespace QuickGraph.Serialization +{ + internal static class SerializationHelper + { + public static IEnumerable> GetAttributeProperties(Type type) + { + foreach (PropertyInfo property in type.GetProperties()) + { + // must have a get, and not be an index + if (!property.CanRead || property.GetIndexParameters().Length > 0) + continue; + // is it tagged with XmlAttributeAttribute? + string name = GetAttributeName(property); + if (name != null) + yield return new KeyValuePair(property, name); + } + } + + public static string GetAttributeName(PropertyInfo property) + { + object[] attributes = property.GetCustomAttributes(typeof(XmlAttributeAttribute), true); + if (attributes.Length == 0) + return null; + else + { + XmlAttributeAttribute attribute = attributes[0] as XmlAttributeAttribute; + if (String.IsNullOrEmpty(attribute.AttributeName)) + return property.Name; + else + return attribute.AttributeName; + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs.meta new file mode 100644 index 0000000..d69bcad --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializationHelper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed289c003d82f409ea760ea433847613 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs new file mode 100755 index 0000000..da5b389 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs @@ -0,0 +1,17 @@ +using System; +using System.Xml; + +namespace QuickGraph.Serialization +{ + public abstract class SerializerBase + where TEdge :IEdge + { + private bool emitDocumentDeclaration = true; + + public bool EmitDocumentDeclaration + { + get { return this.emitDocumentDeclaration; } + set { this.emitDocumentDeclaration = value; } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs.meta new file mode 100644 index 0000000..2d26193 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/Serialization/SerializerBase.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e6c80f1b4bd7846019f8345f30ee01f2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs new file mode 100755 index 0000000..b71155e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs @@ -0,0 +1,37 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public class TaggedEdge : Edge + { + private TTag tag; + + public TaggedEdge(TVertex source, TVertex target, TTag tag) + :base(source,target) + { + this.tag = tag; + } + + public event EventHandler TagChanged; + + protected virtual void OnTagChanged(EventArgs e) + { + if (this.TagChanged != null) + this.TagChanged(this, e); + } + + public TTag Tag + { + get { return this.tag; } + set + { + if (!object.Equals(this.tag, value)) + { + this.tag = value; + this.OnTagChanged(EventArgs.Empty); + } + } + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs.meta new file mode 100644 index 0000000..b3d1ee3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TaggedEdge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ebb112f45b0714bdaa9eb2834395a39e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs new file mode 100755 index 0000000..d193215 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + public static class TraversalHelper + { + public static TVertex GetFirstVertex(IVertexListGraph g) + where TEdge : IEdge + { + foreach (var v in g.Vertices) + return v; + return default(TVertex); + } + + public static TVertex GetFirstVertex(IUndirectedGraph g) + where TEdge : IEdge + { + foreach (var v in g.Vertices) + return v; + return default(TVertex); + } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs.meta new file mode 100644 index 0000000..506f06d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/TraversalHelper.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc83fe0d8102d42118d23ddf81ad0949 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs new file mode 100755 index 0000000..31b638b --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace QuickGraph +{ + [Serializable] + public sealed class UndirectedBidirectionalGraph : + IUndirectedGraph + where TEdge : IEdge + { + private readonly IBidirectionalGraph visitedGraph; + + public UndirectedBidirectionalGraph(IBidirectionalGraph visitedGraph) + { + if (visitedGraph == null) + throw new ArgumentNullException("visitedGraph"); + this.visitedGraph = visitedGraph; + } + + public IBidirectionalGraph VisitedGraph + { + get { return this.visitedGraph; } + } + + #region IUndirectedGraph Members + + public IEnumerable AdjacentEdges(TVertex v) + { + foreach (var e in this.VisitedGraph.OutEdges(v)) + yield return e; + foreach (var e in this.VisitedGraph.InEdges(v)) + { + // we skip selfedges here since + // we already did those in the outedge run + if (e.Source.Equals(e.Target)) + continue; + yield return e; + } + } + + public int AdjacentDegree(TVertex v) + { + return this.VisitedGraph.Degree(v); + } + + public bool IsAdjacentEdgesEmpty(TVertex v) + { + return this.VisitedGraph.IsOutEdgesEmpty(v) && this.VisitedGraph.IsInEdgesEmpty(v); + } + + public TEdge AdjacentEdge(TVertex v, int index) + { + throw new NotSupportedException(); + } + + public bool ContainsEdge(TVertex source, TVertex target) + { + throw new NotSupportedException(); + } + + #endregion + + #region IVertexSet Members + + public bool IsVerticesEmpty + { + get { return this.VisitedGraph.IsVerticesEmpty; } + } + + public int VertexCount + { + get { return this.VisitedGraph.VertexCount; } + } + + public IEnumerable Vertices + { + get { return this.VisitedGraph.Vertices; } + } + + public bool ContainsVertex(TVertex vertex) + { + return this.VisitedGraph.ContainsVertex(vertex); + } + + #endregion + + #region IEdgeListGraph Members + + public bool IsEdgesEmpty + { + get { return this.VisitedGraph.IsEdgesEmpty; } + } + + public int EdgeCount + { + get { return this.VisitedGraph.EdgeCount; } + } + + public IEnumerable Edges + { + get { return this.VisitedGraph.Edges; } + } + + public bool ContainsEdge(TEdge edge) + { + return this.VisitedGraph.ContainsEdge(edge); + } + + #endregion + + #region IGraph Members + + public bool IsDirected + { + get { return false; } + } + + public bool AllowParallelEdges + { + get { return this.VisitedGraph.AllowParallelEdges; } + } + + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs.meta new file mode 100644 index 0000000..5407a06 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedBidirectionalGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3ce634f6854dd4086b0d37a9df28bb3a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs new file mode 100755 index 0000000..a1caece --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs @@ -0,0 +1,302 @@ +using System; +using System.Collections.Generic; + +namespace QuickGraph +{ + public class UndirectedGraph : + IMutableUndirectedGraph + where TEdge : IEdge + { + private readonly bool allowParallelEdges = true; + private readonly Dictionary> adjacentEdges = + new Dictionary>(); + private int edgeCount = 0; + + public UndirectedGraph() + :this(true) + {} + + public UndirectedGraph(bool allowParallelEdges) + { + this.allowParallelEdges = allowParallelEdges; + } + + #region IGraph Members + public bool IsDirected + { + get { return false; } + } + + public bool AllowParallelEdges + { + get { return this.allowParallelEdges; } + } + #endregion + + #region IMutableUndirected Members + + public void AddVertex(TVertex v) + { + GraphContracts.AssumeNotInVertexSet(this, v, "v"); + this.adjacentEdges.Add(v, new List()); + } + + public bool RemoveVertex(TVertex v) + { + GraphContracts.AssumeNotNull(v, "v"); + this.ClearAdjacentEdges(v); + return this.adjacentEdges.Remove(v); + } + + public int RemoveVertexIf(VertexPredicate pred) + { + GraphContracts.AssumeNotNull(pred, "pred"); + List vertices = new List(); + foreach (var v in this.Vertices) + if (pred(v)) + vertices.Add(v); + + foreach (var v in vertices) + RemoveVertex(v); + return vertices.Count; + } + #endregion + + #region IMutableIncidenceGraph Members + public int RemoveAdjacentEdgeIf(TVertex v, EdgePredicate predicate) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + GraphContracts.AssumeNotNull(predicate, "predicate"); + + IList outEdges = this.adjacentEdges[v]; + List edges = new List(outEdges.Count); + foreach (var edge in outEdges) + if (predicate(edge)) + edges.Add(edge); + + this.RemoveEdges(edges); + return edges.Count; + } + + public void ClearAdjacentEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + IList edges = this.adjacentEdges[v]; + this.edgeCount -= edges.Count; + foreach (var edge in edges) + { + if (edge.Source.Equals(v)) + this.adjacentEdges[edge.Target].Remove(edge); + else + this.adjacentEdges[edge.Source].Remove(edge); + } + System.Diagnostics.Debug.Assert(this.edgeCount >= 0); + } + #endregion + + #region IMutableGraph Members + public void TrimEdgeExcess() + { + foreach (var edges in this.adjacentEdges.Values) + edges.TrimExcess(); + } + + public void Clear() + { + this.adjacentEdges.Clear(); + this.edgeCount = 0; + } + #endregion + + #region IUndirectedGraph Members + + public bool ContainsEdge(TVertex source, TVertex target) + { + foreach(TEdge edge in this.AdjacentEdges(source)) + { + if (edge.Source.Equals(source) && edge.Target.Equals(target)) + return true; + + if (edge.Target.Equals(source) && edge.Source.Equals(target)) + return true; + } + return false; + } + + public TEdge AdjacentEdge(TVertex v, int index) + { + return this.adjacentEdges[v][index]; + } + + public bool IsVerticesEmpty + { + get { return this.adjacentEdges.Count == 0; } + } + + public int VertexCount + { + get { return this.adjacentEdges.Count; } + } + + public IEnumerable Vertices + { + get { return this.adjacentEdges.Keys; } + } + + + public bool ContainsVertex(TVertex vertex) + { + GraphContracts.AssumeNotNull(vertex, "vertex"); + return this.adjacentEdges.ContainsKey(vertex); + } + #endregion + + #region IMutableEdgeListGraph Members + + public bool AddEdge(TEdge edge) + { + GraphContracts.AssumeInVertexSet(this, edge, "edge"); + + if (!this.AllowParallelEdges) + { + if (this.adjacentEdges[edge.Source].Contains(edge)) + return false; + } + this.adjacentEdges[edge.Source].Add(edge); + this.adjacentEdges[edge.Target].Add(edge); + this.edgeCount++; + + this.OnEdgeAdded(new EdgeEventArgs(edge)); + + return true; + } + + public void AddEdgeRange(IEnumerable edges) + { + GraphContracts.AssumeNotNull(edges, "edges"); + foreach (var edge in edges) + this.AddEdge(edge); + } + + public event EdgeEventHandler EdgeAdded; + protected virtual void OnEdgeAdded(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeAdded; + if (eh != null) + eh(this, args); + } + + public bool RemoveEdge(TEdge edge) + { + GraphContracts.AssumeInVertexSet(this, edge, "edge"); + + this.adjacentEdges[edge.Source].Remove(edge); + if (this.adjacentEdges[edge.Target].Remove(edge)) + { + this.edgeCount--; + System.Diagnostics.Debug.Assert(this.edgeCount >= 0); + this.OnEdgeRemoved(new EdgeEventArgs(edge)); + return true; + } + else + return false; + } + + public event EdgeEventHandler EdgeRemoved; + protected virtual void OnEdgeRemoved(EdgeEventArgs args) + { + EdgeEventHandler eh = this.EdgeRemoved; + if (eh != null) + eh(this, args); + } + + public int RemoveEdgeIf(EdgePredicate predicate) + { + GraphContracts.AssumeNotNull(predicate, "predicate"); + + List edges = new List(); + foreach (var edge in this.Edges) + { + if (predicate(edge)) + edges.Add(edge); + } + return this.RemoveEdges(edges); + } + + public int RemoveEdges(IEnumerable edges) + { + GraphContracts.AssumeNotNull(edges, "edges"); + + int count = 0; + foreach (var edge in edges) + { + if (RemoveEdge(edge)) + count++; + } + return count; + } + #endregion + + #region IEdgeListGraph Members + public bool IsEdgesEmpty + { + get { return this.EdgeCount==0; } + } + + public int EdgeCount + { + get { return this.edgeCount; } + } + + public IEnumerable Edges + { + get + { + Dictionary edgeColors = new Dictionary(this.EdgeCount); + foreach (IList edges in this.adjacentEdges.Values) + { + foreach(TEdge edge in edges) + { + GraphColor c; + if (edgeColors.TryGetValue(edge, out c)) + continue; + edgeColors.Add(edge, GraphColor.Black); + yield return edge; + } + } + } + } + + public bool ContainsEdge(TEdge edge) + { + GraphContracts.AssumeInVertexSet(this, edge, "edge"); + foreach (var e in this.Edges) + if (e.Equals(edge)) + return true; + return false; + } + #endregion + + #region IUndirectedGraph Members + + public IEnumerable AdjacentEdges(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.adjacentEdges[v]; + } + + public int AdjacentDegree(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.adjacentEdges[v].Count; + } + + public bool IsAdjacentEdgesEmpty(TVertex v) + { + GraphContracts.AssumeInVertexSet(this, v, "v"); + return this.adjacentEdges[v].Count == 0; + } + + #endregion + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs.meta new file mode 100644 index 0000000..0e25309 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/UndirectedGraph.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ba27481ebda464d629207af8377e1af1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs new file mode 100755 index 0000000..ae61226 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs @@ -0,0 +1,24 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public class VertexEventArgs : EventArgs + { + private readonly TVertex vertex; + public VertexEventArgs(TVertex vertex) + { + GraphContracts.AssumeNotNull(vertex, "vertex"); + this.vertex = vertex; + } + + public TVertex Vertex + { + get { return this.vertex; } + } + } + + public delegate void VertexEventHandler( + object sender, + VertexEventArgs e); +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs.meta new file mode 100644 index 0000000..55cb27e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexEventArgs.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e91533ad7f884e3c94994f1c2de8c17 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs new file mode 100755 index 0000000..b8a4534 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs @@ -0,0 +1,18 @@ +using System; + +namespace QuickGraph +{ + /// + /// Specialized exception to report unconnected vertices + /// + [Serializable] + public sealed class VertexNotConnectedException : ApplicationException + { + public VertexNotConnectedException() { } + public VertexNotConnectedException(string message) : base( message ) { } + public VertexNotConnectedException(string message, System.Exception inner) : base( message, inner ) { } + public VertexNotConnectedException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base( info, context ) { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs.meta new file mode 100644 index 0000000..6f5483e --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotConnectedException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8c7bbec090b554842959c6a9a4083e4f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs new file mode 100755 index 0000000..1a57525 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs @@ -0,0 +1,15 @@ +using System; + +namespace QuickGraph +{ + [Serializable] + public class VertexNotFoundException : ApplicationException + { + public VertexNotFoundException() { } + public VertexNotFoundException(string message) : base( message ) { } + public VertexNotFoundException(string message, System.Exception inner) : base( message, inner ) { } + public VertexNotFoundException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base( info, context ) { } + } +} diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs.meta new file mode 100644 index 0000000..f27fff9 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/VertexNotFoundException.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d5b737e14a6964326ac7b3f936d02f3f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.banner.png b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.banner.png new file mode 100755 index 0000000000000000000000000000000000000000..80774354979b60252619aee310002f84cd63208b GIT binary patch literal 8655 zcmV;=Au!&FP)P96ggchyxd(J$k zciuTObDGAKdp{rZdG$GSdV2bvXP)<2-t(RazJC3>YsYpahXDSyfB7ox_n%*cGt#3*nkJO2fgj)(eNroy{@mW_ z=`jXH=gysHX<-IGiGvo+u4!YWIRGy|w1L+DE|>?GGFg%_a4gvFk1Bc57g0Sq-E_2-v-gMH?wX$set1;q_!nYnkFlQc>p=8wNi7_JsGYrotZ2;h&w`W3 zkI`B|TCP?QjmT*b6crXK>8@}Yf{xCwXz8Z5&idBQ56zu#KYw}C^rfodOGSOhi;o?p zA3C1ZwHLl?&wJZ0Xzl2<5e)*5?N&6Wrd`m|(Fs~XH;Ur#0Z}}lMIXLt6Cgl(Rt~LI zTjM97gs-$H}@cPm>3D0(953Y^Wa`oy^`)QVv6c?pme-oRzaWxZ40_)t$%r{8~4Dq01y zcAd3gF?tJXjehVPw1Q|7c&zM4fLisn`-3R3643^sNIwkW_Rgp~{~*DHCgrgy%F{~0BiV!_d-&JU#1XU-u%Ne0>!Lmg%(RGLJRWVg<*h!kxqs}v#$n^8e2UOs$Pq||ru za{ANfR|*k|Nxz^Pm8Lu?gRfW9^FS$+0xBC5^IyTi?lV_F>1@B{Bi+EtkWg$PqKz;B@Abx(se$GgC`=m?-z;Ob}(dauV_C)e`rdJBkZ ztj#eG3^o!P>JIouz2IYvY8OZQR&gFc)j>NaVnzQgda*PG)gnwWFsyBi@PMg@{;nW; z;S8-eHu)aEUUXkZHGXba5NYFrm?E+MI1W_#hoXy zgED%B;u4?e#jGZ9v=?#gyTETrc1e{odeOd@Gm1bGji9TgiRpq>%_$bhP)0BPxkYIA zGu2=l4pueo4`fmZyZUQo^g6n@S!?`+b%;=0gfOZd>_xKkt+SJvmbyYsW%Pn6LJpr7 zc9l3naUH^{ru}T;61L{M|GXOX#@@|_V-hDhdedIDps>prPh!U4BTj+dxbCjN4Uxw!>hlW=MWR&}>}IdKO*jH*{miK0j^)Fg~*XmOR- zOIKxkFC{C|8&6dC$bZRv6s!8y<7X!>#UG2gk^8z)u3kNDtsd!(EoBN~fk-40 zcGZ%b!uDXC%qU~l4}wB>W4-{@pcjgMCH0;!{>-W_sA(SOHED4`;6|}(;5{0f%%~38 zom^Cns)5(c++0b$hw>X4)y9L26xnxm$nKun0rl>D+`y==tgMjr*>4|AISKzp3?0JE zG$#jlX9qVNPI88;%y6NHqhvVC3@3UxFvC&t;JobZ*)hb>fJuK9<%00A9Z=+88H|JMICUL3f%JNNOx>zA>lix@mm7f-5y3z3*@Vi;&~izGKP ztXL5+&U36XzKbY&+WmtzY%X|JhZPu%EgLs{m3|E|(1Y_+eP;9&7jg&N9sx8qUy34w zP~3~DFx6JBUPsaad3~s>!;?vmihGKiNg6MN=7|i@OJ9t=p+aPU#>YTcTW(epiR@Lt zm9%sS%@Y~ol5T^XGPoCSq;TMjjSS`bZuToC(O*f;=@G7^Sp;ZoMR}&0uxmlM;$s`X zb>r@2($M@EBPu$e^R8 z;W^$b^EFe@>g#Cp;HHrV7omBk+F%2H0xcI;Ut7yaUsvV0yK&b6+Ach}P-n8OGXpJd z%z36-ZW&Yj&YnA;#?3CPfs^z9yF_JNbcT=vr)g+gJ9|aAP#LpLIY48}uV|`m-4V`l zlFfhZg0D9p7JehHtnc0{Z?v?ul8rXb?qkW4vjkdEWWb-XG9Q6amMmcTuUMsCT(s`y zJ;&I5DQ@p^SZT26*nmi&6$LWc>=3vzK$*zUQ(Sb0G2@t8z*rhOPDcZOBeqN|G%kS1 z4P;?^56R6A0J=4NKOS$}eUO8DJ~1P!vawrSprZgx3simV&VwXq}-SIYYcP;bZcFECl?wNry97y*25Rf%q<2P z8q8W8kkZwYN|sd+TD|oyJ=TZqOUSFF&rF!&V>)~|9IOo91(9LRPA25Jd5$Mj4Sg4# zfyR|A*bwM%#|2MVv^+2{I4tzw=>stdQMVrh?uPJ#^u(Apc_O~$1TtlCB}+j7Z7&ji zJFX(%4L^MaDXU+<2556r6MU-zu4Iu3p?d?D_%4J6U15LX9-H=_R1H_Me1*`6d-TFp zi7$ri>?y9EwwCYW<@`zbTW}={V*o7@iGX;Nx!E8CeU5dnXXN2ExQ!XReC=j(Nq`#^ zx*OsHzIAYN$rMA68fA%R!p~k+J8sPL&+L*LLIdb88Yt zlc8`H%EjP(q9L4e`&B#ELR8oi0c;1KPrZ0(QFtO&q*=6A5k8r%e9m5W}#wvkMQ~ zA=#sW#L$q+R*Ch^?f(Q~h!A#mA{LquPaOXXYv8%I=hBu2Y#WbnA%6c8h`G@8ih9t_ ziDaGkQuYcw`L6!+cPEA@EP*C75Bca7b+SHv{$k8`Cx&55Lu0JqfsRkS`Q3>j(@CI7 zbVEK%YePc3WSxhw>)yq8C+0$9JU)3!vTow&W}>Yr=__$KIf%|hU6M=uw1TOzo>je< zOPq8+=Wb5%Hxf%h(-|aS#c~el=uzfq|1K>ZHiX@MdLiMS3dB;-Je5%STjtYLfjBuUf11y4ie_haWxWc-(2sJV z6=i9m_-DPn=%WDuL!9j=z;Q@PiLuH~Xz*x{dplpLvMWXlR}+&4HFnocg2$z7@1-t7^5|eE$_h|Aw9W zd5B?*CeS=tI;*IRXoR{#miSmyER!s5q^MkN4xkn-hMSo15U0M9hUUq6tJkr0Sz`Jl z4zYj0Dmee3xKcIZJI`ul^9~QO6m+*)+SJ5YNNr`Xr zK8d02B+&eQ9%sy$JvY1JgM~Tsmpb6V=V0zzx&RIlaPv|Q!qz!y*Pk# z5-M+UBTovNe{C}$9=o~ya(bSUGY`j_umhMu zlK-xs^y@5WZLDqVA}^)Tw;mROGxa_BI*~MKy%@*SSouPId$V zB7MJ9(almRXmzb0ySRk-Li4lf!(JspS*GJYUZ;$rR;9$6@U0c z#B6P4?Yi$$lH9xK{KPP<2((&=dG=@vr61CT;lE~!3d9L7q@jC>m^}XG>Szzd&x)Vo z+cURwRUnpv?mc1{8+RX(^=Z|J<2lg1M2yjG+4>NI3qeC=VkzieC6?PYsYZOGti_Us zMqF~2#6VYD1!7^>W7EAv97jVVvA(vJv5_I#7}EU^Bg3BBSlC@J{f)%2rOg(jrJ>=V z=v^DfE8wKPgQHNqVT|~tuiqc|IFgGyoBz@)n-H3$@!lXlU;J4L`bibDc>c8O&uQSu z6F*1i;W-X%d_A+6Y;?oNk+vT>2R0r)Y?za)J4QFsHT4GZ>7phx>n>=Vd2nzurv#ug zN^AF@y-c8kwuUkOP|YMW(_zD={5Fd~$2}|o15ckd7h(c|#@eknh!5pAjwI0N$M)hs z_jB@U@~OBKJ@KcEF0uX48Gzol=crJ;@lho97Myla5TjQ>7flRIpw&*i|4HKrD_aRP z`ti#3!RQ!ce;J=s-9keHF5cxnlX#y%AC6@nA+ob~;CKb55496V z!T7G{^?NB+aEL=6H5eEgo;-d`FlFKd=r!_cTYH*8CQYA_TwL3i#IwWB3dtkb)4eCj zmIwdLfy+khwoQ2RFGByf3@|BKoMQ~_?Zs@r8>Fujd-+mF#~0iWNj4bLTRG_son*97 z19y(l`$y;<4xD@N^gUPlt|0xGA-S_c->u-Rr_<}F^a>xn21T!ua2}7Ln@zeMq6>CT zNl6Mz`Y{B$$jq;8-Fqq;*CoKbjG-ZZz?)%1jJ|+{c}?8h+I}}R_2`i!p&{G$L`Gh| zeED@v?GF=kOib5p`ET2d2QfPsm>|7t2Xk*78aPEJPQ7<;*kB|6IkGx1u)ewNhlz=a z>FvB=A0~wpL(7^tKfh4X^V4$2`gQAmn3%4F_zX<~1voNoL_O_(yDrS)Y@5COIKa`( zgch6U>-)pRWZ<@GuAw>U&cSvxG2c+*0rAg*I94WOQJ@=b>pS-{ewY|*WI2X*=`u8_ zCFq^5lV?~dvNDXw7^y!|dgAn%A10=^r*jR>DcWYvklIam@cMj3hPHDULQ9sESN$+C zy*r&_Xc4C_uB&e}9V%r(i%|o^qh=HPUd&qVGf!%V1{2DKnv*9^4Boo!dO~t#?MIbO zY-45l$BLDeA6x&uCgwA=Z0oVqe+kEwiiYXX!3imMjvhbd=jUf_VJ<6RHr&M5*Ee$i zp?eQ=YZ}{my!b-w4f0dgqb$;Mi}_8QUHUp`!xkIyL!4yj!bk2s^}wm9lDf9o0!kgJ?ie(tX(Ul{?3?c zvG_@8#mNgX%LD#&v=?b>aG(E?9iE<^PhQr5mA6M8;CyS~04=|T^N$}r5*>8`E^Mru z3rE06U-$mAsy;I@dD=qS&<>)WHqejqitqw5bMn=g?xs$g-mSUyr0-Ub^KfrzX_0-h z16~g^GihNREse)7-}jA)`3&9D270V`j;~s^T3r=IYIdO_?)r0cJ!+tjo?y0O8S3f0``n?HqHW%SMG(X% zPxjst8Wwjez4Tp^Y(02kPtDlZ zoV|FdFY97!D@$THV?+Ihh6WxhN1Z=Me=y9>t3EL?d3uOzXw}vz{1!9y-{eV?`m*&% z&dTRx&b<-4Wlj9<-P;MC9<-RNn|q&`n9tBEtWhMVvVTA`ucW*$ySwbN8nY3m%G7pb z_%2-BmnJ5UmT?WO@-mQ(cp`5O4(UA;XB3p}K74Yf@4R7Dw8b&nTF&34<7Clkzs;Q&S%ahV!+R$ja&mK1 zOaewStgmYc-W%`zti!&0?|b&%bE^jr;$s%Bx|Mqu`NcJ@-3d3-&;1y4I_O+vT*9rq zd+p;3SVQ6J=>yM7D=HTQV(f-rHqaucfktK);SD^jZP>z9d@H+tp|-ULzP*=|-qAYz+m=LkwXeq1Rg`5IwIce>qYDV}^~_><8EKm% z_M1Wcf?1M^2QBO>zEe=bpK`#NAfXV`Cl}B&(8vGu@WKbqOj}Y$Uh(6`tqq_ruW!-= z@(KvDr#NA6q2y_&$cRxHEf>(jMt9S1*Y=aiTq%QfH!!m-AmYlVml~>!l_j@pCpEiB z{K?GpvO2DJ;pFZuGGbIk%MO}E6ghytS6Rz>iLuvi2!i-(5*2#5y4qUx?R{cK+&=rK z53?4Qmmbk4L_^FEw8#PU)Voi1cJ}DvG}TllSN`UMcyMmj+0`8$eC#--cV9~Q%-P#25w2?uWu3GD*9wfQB_Pz*5$PPv9bBA5}8bHAD!LKh;g>KVRXsBz)-3qL`YT*xAw1)BU=*FyGvm?Gk}iX`&BH3Syv|zFAy#ZM4h|T%mo>9w`TDwuCLw z(hA#w*q9TvusI6vQ~uchpzUQVXGZw#^0J09Yn+FkuC7ENhWgIU6MKU+c_|!aq*Ph9 z2DO)N=E5omexL=sbh7LYCH7;`^bphn0}ooXWG1gPCQha%#$D5ISxb2FV|q!2 z%^_QKfU1&0a71)t-xRM^?C8q)1#$|tbj4o=#d8b47p`{zIKHx$hSZ_ZteRZ~_%Ct6t_yj55Zs~rK>z_3WH z{keVr@#YOhMnxkZYKn5QW$mNLDZZL{S4&Ha*TLiihqCLtaEMW>5j^N^vNN-L{!><2 z?O}V?7)4w!EvS9_be|5*iEN7t8al0PYST-R!?$8T+bi$cH8`V zJ-vVz4u(NIeHI~Z{cSBaHOm;|Dlj%TSsh5sD~E8KC*Fr#x~9l%qX;Z=V*bM?L-T4X zO4!f5n3S<4h*3)yJm~F)80cO@J0Hquy{8sd64>|b@;TTuAh@RgcWfG{Y3ffS0^@W= z`Q2shV_St7Rt56|y&Vt(J?WX+&23V}X9c{Sg1p@9%nWNX+hapjS*dwyl~<-MEIw&# z5u?^QTtIIV#6o!#-k5|kuoX*7i&#g#v!esc`a(h~pG@1g(;nf(Cv)_FtotGQ@_MA85%!41I~F@fCIUxJgM~*7bxVFd*{mEv`+?iQ+_zIuzkS zOB`aX)8^_Mz~69(#@!GzVt$|{5ivGLQPDYeCNj=qzqO{inwF-fmCfO>_{7Kk|NSb6 z;p{aopg9ru&aP$@mtTmvaylq9JmyMrW2@wF2GiBCKjvU+!U_Z~C#QYsRSYvb*fEt7hqz+w1CXH!J7_o$6DlNpqdW4= zoMN1zh)ziMJoSC-&o^I=F95htdnPDOE)GsEkJ<*j`~wLDf^T3jOi)};&$qQZs;{S~ ztE02u>cEfJlDp2?vyS!k4I~9I zoIJ_}G+Muj85+H$jix2PQ3Be$8Afr h06>5djSGig{|Bq(HExwhcsKw6002ovPDHLkV1js##M}S? literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.banner.png.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.banner.png.meta new file mode 100644 index 0000000..b71703d --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.banner.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: c3b75faf76b1d4ab0a648bc19a4c85a1 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.png b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.png new file mode 100755 index 0000000000000000000000000000000000000000..5d7bb7133489f78ce24f17f7380f140c9fa87144 GIT binary patch literal 4297 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 literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.png.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.png.meta new file mode 100644 index 0000000..014fb96 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.png.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 48cbaeedad2bd45e991563abd0655cd8 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.snk b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.snk new file mode 100755 index 0000000000000000000000000000000000000000..a630ef50c86fa24e26a52eec015fa55208e88f88 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098C00=AIu009kK;!dACRXV-KH)dj;nb`? zQ-=oWiUP?hh*WlnvfVGfm9#9y3TlZ|`s83+8-J3WMR2A z=(@EZk;?n=R>be9Rx*auG5x-%)9XA~D_w_2_|t+K16R$vK4oKp(9|K;Hjx2NDzuZZ&_)S*sKMY5pd*oMVL^RY7a>LF)jWaD zH9+7eB}>7|QdR8LGqPH(c?4W_-Zl{b(M|kwR&4er(F;*P-Z(LSEDmFar`aqbIZM%6 zw)(nzh2eWNj--p4f84EudoAu?TDH4kOeNxk{9`(IPx;9YXQl5(Ka9&b?c;|mU04rN z;2YM972RJ?l%aG3p`TCVBgEtsqB;;xUn?(_NJ}fTk@tJCdf!LrWd@ikgm3K{=HtB zzaG%6^UQJ>-L@jy`SMVEVAnMS4b zz{rCok_J%M80o1MkST42B@}*!gK(`UND()vgy*%*qU`n-fDxg7McjZBIF!xWZvQ#J i7M{3*W_%R=cpVx!)OoGh(&7BFE!7GIWyT37q2QHHg&b@E literal 0 HcmV?d00001 diff --git a/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.snk.meta b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.snk.meta new file mode 100644 index 0000000..f00c7a3 --- /dev/null +++ b/src/Assets/quickgraph4unity/Runtime/QuickGraph/quickgraph.snk.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 89e74692ab5fb44a7ab2c83772dafb4c +DefaultImporter: + userData: diff --git a/src/ProjectSettings/AudioManager.asset b/src/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..ec6be29 --- /dev/null +++ b/src/ProjectSettings/AudioManager.asset @@ -0,0 +1,12 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + m_Volume: 1 + Rolloff Scale: 1 + m_SpeedOfSound: 347 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_DSPBufferSize: 0 + m_DisableAudio: 0 diff --git a/src/ProjectSettings/DynamicsManager.asset b/src/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..717b5c2 --- /dev/null +++ b/src/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + m_Gravity: {x: 0, y: -9.81000042, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepVelocity: .150000006 + m_SleepAngularVelocity: .140000001 + m_MaxAngularVelocity: 7 + m_MinPenetrationForPenalty: .00999999978 + m_SolverIterationCount: 6 + m_RaycastsHitTriggers: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/src/ProjectSettings/EditorBuildSettings.asset b/src/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..6dc24f7 --- /dev/null +++ b/src/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: [] diff --git a/src/ProjectSettings/EditorSettings.asset b/src/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..f6bcc6a --- /dev/null +++ b/src/ProjectSettings/EditorSettings.asset @@ -0,0 +1,12 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 3 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_WebSecurityEmulationEnabled: 0 + m_WebSecurityEmulationHostUrl: http://www.mydomain.com/mygame.unity3d + m_DefaultBehaviorMode: 0 + m_SpritePackerMode: 0 diff --git a/src/ProjectSettings/GraphicsSettings.asset b/src/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..553f97d --- /dev/null +++ b/src/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} diff --git a/src/ProjectSettings/InputManager.asset b/src/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..c95d27b --- /dev/null +++ b/src/ProjectSettings/InputManager.asset @@ -0,0 +1,246 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: .00100000005 + 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: .00100000005 + 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: .00100000005 + 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: .00100000005 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left cmd + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: .00100000005 + 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: .00100000005 + 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: .100000001 + 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: .100000001 + 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: .100000001 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: .189999998 + 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: .189999998 + 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: .00100000005 + 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: .00100000005 + 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: .00100000005 + 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: .00100000005 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/src/ProjectSettings/NavMeshLayers.asset b/src/ProjectSettings/NavMeshLayers.asset new file mode 100644 index 0000000..79cb3ae --- /dev/null +++ b/src/ProjectSettings/NavMeshLayers.asset @@ -0,0 +1,133 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshLayers: + m_ObjectHideFlags: 0 + Built-in Layer 0: + name: Default + cost: 1 + editType: 2 + Built-in Layer 1: + name: Not Walkable + cost: 1 + editType: 0 + Built-in Layer 2: + name: Jump + cost: 2 + editType: 2 + User Layer 0: + name: + cost: 1 + editType: 3 + User Layer 1: + name: + cost: 1 + editType: 3 + User Layer 2: + name: + cost: 1 + editType: 3 + User Layer 3: + name: + cost: 1 + editType: 3 + User Layer 4: + name: + cost: 1 + editType: 3 + User Layer 5: + name: + cost: 1 + editType: 3 + User Layer 6: + name: + cost: 1 + editType: 3 + User Layer 7: + name: + cost: 1 + editType: 3 + User Layer 8: + name: + cost: 1 + editType: 3 + User Layer 9: + name: + cost: 1 + editType: 3 + User Layer 10: + name: + cost: 1 + editType: 3 + User Layer 11: + name: + cost: 1 + editType: 3 + User Layer 12: + name: + cost: 1 + editType: 3 + User Layer 13: + name: + cost: 1 + editType: 3 + User Layer 14: + name: + cost: 1 + editType: 3 + User Layer 15: + name: + cost: 1 + editType: 3 + User Layer 16: + name: + cost: 1 + editType: 3 + User Layer 17: + name: + cost: 1 + editType: 3 + User Layer 18: + name: + cost: 1 + editType: 3 + User Layer 19: + name: + cost: 1 + editType: 3 + User Layer 20: + name: + cost: 1 + editType: 3 + User Layer 21: + name: + cost: 1 + editType: 3 + User Layer 22: + name: + cost: 1 + editType: 3 + User Layer 23: + name: + cost: 1 + editType: 3 + User Layer 24: + name: + cost: 1 + editType: 3 + User Layer 25: + name: + cost: 1 + editType: 3 + User Layer 26: + name: + cost: 1 + editType: 3 + User Layer 27: + name: + cost: 1 + editType: 3 + User Layer 28: + name: + cost: 1 + editType: 3 diff --git a/src/ProjectSettings/NetworkManager.asset b/src/ProjectSettings/NetworkManager.asset new file mode 100644 index 0000000..5dc6a83 --- /dev/null +++ b/src/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/src/ProjectSettings/Physics2DSettings.asset b/src/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..28cf91b --- /dev/null +++ b/src/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,21 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + m_Gravity: {x: 0, y: -9.81000042} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: .200000003 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: .200000003 + m_BaumgarteTimeOfImpactScale: .75 + m_TimeToSleep: .5 + m_LinearSleepTolerance: .00999999978 + m_AngularSleepTolerance: 2 + m_RaycastsHitTriggers: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/src/ProjectSettings/ProjectSettings.asset b/src/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..39e3068 --- /dev/null +++ b/src/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,226 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 3 + AndroidProfiler: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + targetGlesGraphics: 1 + targetResolution: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: graph4unity + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + m_ActiveColorSpace: 0 + m_MTRendering: 1 + m_MobileMTRendering: 0 + m_UseDX11: 1 + m_Stereoscopic3D: 0 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + displayResolutionDialog: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + use24BitDepthBuffer: 1 + defaultIsFullScreen: 1 + defaultIsNativeResolution: 1 + runInBackground: 0 + captureSingleScreen: 0 + Override IPod Music: 0 + Prepare IOS For Recording: 0 + enableHWStatistics: 1 + usePlayerLog: 1 + stripPhysics: 0 + forceSingleInstance: 0 + resizableWindow: 0 + useMacAppStoreValidation: 0 + gpuSkinning: 0 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + macFullscreenMode: 2 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + videoMemoryForVertexBuffers: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + iPhoneBundleIdentifier: com.Company.ProductName + metroEnableIndependentInputSource: 0 + metroEnableLowLatencyPresentationAPI: 0 + productGUID: 71088effccc53408a8e844fdddf3ca84 + iPhoneBundleVersion: 1.0 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 9 + AndroidPreferredInstallLocation: 1 + aotOptions: + apiCompatibilityLevel: 2 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + StripUnusedMeshComponents: 0 + iPhoneSdkVersion: 988 + iPhoneTargetOSVersion: 16 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + iPhoneSplashScreen: {fileID: 0} + iPhoneHighResSplashScreen: {fileID: 0} + iPhoneTallHighResSplashScreen: {fileID: 0} + iPadPortraitSplashScreen: {fileID: 0} + iPadHighResPortraitSplashScreen: {fileID: 0} + iPadLandscapeSplashScreen: {fileID: 0} + iPadHighResLandscapeSplashScreen: {fileID: 0} + AndroidTargetDevice: 0 + AndroidSplashScreenScale: 0 + AndroidKeystoreName: + AndroidKeyaliasName: + resolutionDialogBanner: {fileID: 0} + m_BuildTargetIcons: [] + m_BuildTargetBatching: [] + webPlayerTemplate: APPLICATION:Default + m_TemplateCustomTags: {} + XboxTitleId: + XboxImageXexPath: + XboxSpaPath: + XboxGenerateSpa: 0 + XboxDeployKinectResources: 0 + XboxSplashScreen: {fileID: 0} + xboxEnableSpeech: 0 + xboxAdditionalTitleMemorySize: 0 + xboxDeployKinectHeadOrientation: 0 + xboxDeployKinectHeadPosition: 0 + ps3TitleConfigPath: + ps3DLCConfigPath: + ps3ThumbnailPath: + ps3BackgroundPath: + ps3SoundPath: + ps3TrophyCommId: + ps3NpCommunicationPassphrase: + ps3TrophyPackagePath: + ps3BootCheckMaxSaveGameSizeKB: 128 + ps3TrophyCommSig: + ps3SaveGameSlots: 1 + ps3TrialMode: 0 + psp2Splashimage: {fileID: 0} + psp2LiveAreaGate: {fileID: 0} + psp2LiveAreaBackround: {fileID: 0} + psp2NPTrophyPackPath: + psp2NPCommsID: + psp2NPCommsPassphrase: + psp2NPCommsSig: + psp2ParamSfxPath: + psp2PackagePassword: + psp2DLCConfigPath: + psp2ThumbnailPath: + psp2BackgroundPath: + psp2SoundPath: + psp2TrophyCommId: + psp2TrophyPackagePath: + psp2PackagedResourcesPath: + flashStrippingLevel: 2 + spritePackerPolicy: + scriptingDefineSymbols: {} + metroPackageName: graph4unity + metroPackageLogo: + metroPackageLogo140: + metroPackageLogo180: + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: graph4unity + metroTileLogo80: + metroTileLogo: + metroTileLogo140: + metroTileLogo180: + metroTileWideLogo80: + metroTileWideLogo: + metroTileWideLogo140: + metroTileWideLogo180: + metroTileSmallLogo80: + metroTileSmallLogo: + metroTileSmallLogo140: + metroTileSmallLogo180: + metroSmallTile80: + metroSmallTile: + metroSmallTile140: + metroSmallTile180: + metroLargeTile80: + metroLargeTile: + metroLargeTile140: + metroLargeTile180: + metroTileShortName: + metroCommandLineArgsFile: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 1 + metroTileBackgroundColor: {r: 0, g: 0, b: 0, a: 1} + metroSplashScreenImage: + metroSplashScreenImage140: + metroSplashScreenImage180: + metroSplashScreenBackgroundColor: {r: 0, g: 0, b: 0, a: 1} + metroSplashScreenUseBackgroundColor: 0 + metroCapabilities: {} + metroUnprocessedPlugins: [] + metroCompilationOverrides: 1 + blackberryDeviceAddress: + blackberryDevicePassword: + blackberryTokenPath: + blackberryTokenExires: + blackberryTokenAuthor: + blackberryTokenAuthorId: + blackberryAuthorId: + blackberryCskPassword: + blackberrySaveLogPath: + blackberryAuthorIdOveride: 0 + blackberrySharedPermissions: 0 + blackberryCameraPermissions: 0 + blackberryGPSPermissions: 0 + blackberryDeviceIDPermissions: 0 + blackberryMicrophonePermissions: 0 + blackberryGamepadSupport: 0 + blackberryBuildId: 0 + blackberryLandscapeSplashScreen: {fileID: 0} + blackberryPortraitSplashScreen: {fileID: 0} + blackberrySquareSplashScreen: {fileID: 0} + tizenProductDescription: + tizenProductURL: + tizenCertificatePath: + tizenCertificatePassword: + tizenGPSPermissions: 0 + tizenMicrophonePermissions: 0 + stvDeviceAddress: + firstStreamedLevelWithResources: 0 + unityRebuildLibraryVersion: 9 + unityForwardCompatibleVersion: 39 + unityStandardAssetsVersion: 0 diff --git a/src/ProjectSettings/QualitySettings.asset b/src/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..080f046 --- /dev/null +++ b/src/ProjectSettings/QualitySettings.asset @@ -0,0 +1,140 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 3 + m_QualitySettings: + - serializedVersion: 2 + name: Fastest + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + vSyncCount: 0 + lodBias: .300000012 + maximumLODLevel: 0 + particleRaycastBudget: 4 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Fast + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + vSyncCount: 0 + lodBias: .400000006 + maximumLODLevel: 0 + particleRaycastBudget: 16 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Simple + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + vSyncCount: 0 + lodBias: .699999988 + maximumLODLevel: 0 + particleRaycastBudget: 64 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Good + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + particleRaycastBudget: 256 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Beautiful + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + particleRaycastBudget: 1024 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Fantastic + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + particleRaycastBudget: 4096 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + BlackBerry: 2 + FlashPlayer: 3 + GLES Emulation: 3 + PS3: 3 + PS4: 3 + PSM: 3 + PSP2: 3 + Samsung TV: 2 + Standalone: 3 + Tizen: 2 + WP8: 3 + Web: 3 + Windows Store Apps: 3 + XBOX360: 3 + XboxOne: 3 + iPhone: 2 diff --git a/src/ProjectSettings/TagManager.asset b/src/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..e903991 --- /dev/null +++ b/src/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + tags: + - + Builtin Layer 0: Default + Builtin Layer 1: TransparentFX + Builtin Layer 2: Ignore Raycast + Builtin Layer 3: + Builtin Layer 4: Water + Builtin Layer 5: UI + Builtin Layer 6: + Builtin Layer 7: + User Layer 8: + User Layer 9: + User Layer 10: + User Layer 11: + User Layer 12: + User Layer 13: + User Layer 14: + User Layer 15: + User Layer 16: + User Layer 17: + User Layer 18: + User Layer 19: + User Layer 20: + User Layer 21: + User Layer 22: + User Layer 23: + User Layer 24: + User Layer 25: + User Layer 26: + User Layer 27: + User Layer 28: + User Layer 29: + User Layer 30: + User Layer 31: + m_SortingLayers: + - name: Default + userID: 0 + uniqueID: 0 + locked: 0 diff --git a/src/ProjectSettings/TimeManager.asset b/src/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..f0e494b --- /dev/null +++ b/src/ProjectSettings/TimeManager.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: .0199999996 + Maximum Allowed Timestep: .333333343 + m_TimeScale: 1

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 G4E#TkJM+B& literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.dll.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.dll.meta new file mode 100644 index 0000000..7517631 --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.dll.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e8950b8b4aa418a458a503526c8a2f65 +MonoAssemblyImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.interfaces.dll b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.interfaces.dll new file mode 100644 index 0000000000000000000000000000000000000000..1f2e48a67627ff338cb0d991c1584ae7aaa8d1b7 GIT binary patch literal 53248 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 PEpX5R2QBd5V}bt*w%2z> literal 0 HcmV?d00001 diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.interfaces.dll.meta b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.interfaces.dll.meta new file mode 100644 index 0000000..b68531c --- /dev/null +++ b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.core.interfaces.dll.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ef8ce5f8e3e580349ac63ac38e87ee2f +MonoAssemblyImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + userData: diff --git a/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.framework.dll b/src/Assets/UnityTestTools/UnitTesting/Editor/NUnit/Libs/nunit.framework.dll new file mode 100644 index 0000000000000000000000000000000000000000..3c08520d900146bac5533b74b73ff9a0e0eedd04 GIT binary patch literal 131072 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