From e000291f51adcda9965cdc7dcc9c5d3d1384d6b9 Mon Sep 17 00:00:00 2001 From: im-mi Date: Fri, 10 Aug 2018 18:51:30 -0400 Subject: [PATCH] first commit --- .gitignore | 5 + KoiCatalog.App/ActionLockTarget.cs | 56 +++ KoiCatalog.App/CancellableTask.cs | 19 + KoiCatalog.App/CancellableTaskGroup.cs | 42 ++ KoiCatalog.App/Data/DataColumn.cs | 16 + KoiCatalog.App/Data/DataRow.cs | 23 ++ KoiCatalog.App/Data/DataTable.cs | 23 ++ KoiCatalog.App/DatabaseLoadMode.cs | 10 + KoiCatalog.App/DatabaseLoadingState.cs | 9 + KoiCatalog.App/DatabaseStatus.cs | 87 +++++ KoiCatalog.App/DatabaseStatusState.cs | 10 + .../DatabaseToDatabaseStatusService.cs | 152 ++++++++ .../DatabaseToQueryFormatService.cs | 179 +++++++++ KoiCatalog.App/DatabaseToStatsService.cs | 171 ++++++++ KoiCatalog.App/DatabaseUtil.cs | 81 ++++ KoiCatalog.App/GlobalOptions.cs | 70 ++++ KoiCatalog.App/IOUtil.cs | 29 ++ KoiCatalog.App/KoiCatalog.App.csproj | 81 ++++ KoiCatalog.App/KoiCatalogApp.cs | 54 +++ KoiCatalog.App/ProgramInfo.cs | 33 ++ KoiCatalog.App/Properties/AssemblyInfo.cs | 36 ++ KoiCatalog.App/QueryCleanupService.cs | 70 ++++ KoiCatalog.App/QueryEditor.cs | 50 +++ KoiCatalog.App/QueryEditorParameter.cs | 101 +++++ .../QueryEditorParameterSelectableValue.cs | 45 +++ .../QueryFormatToQueryEditorService.cs | 112 ++++++ KoiCatalog.App/QueryToQueryResultsService.cs | 276 +++++++++++++ KoiCatalog.App/Util.cs | 58 +++ KoiCatalog.Gui/AboutControl.xaml | 52 +++ KoiCatalog.Gui/AboutControl.xaml.cs | 10 + KoiCatalog.Gui/App.config | 11 + KoiCatalog.Gui/App.xaml | 341 ++++++++++++++++ KoiCatalog.Gui/App.xaml.cs | 23 ++ KoiCatalog.Gui/AppStartup.cs | 24 ++ KoiCatalog.Gui/ColorControl.xaml | 73 ++++ KoiCatalog.Gui/ColorControl.xaml.cs | 21 + KoiCatalog.Gui/Colors.xaml | 9 + KoiCatalog.Gui/Commands.cs | 104 +++++ KoiCatalog.Gui/ConditionalStyleSelector.cs | 40 ++ KoiCatalog.Gui/CustomDialogManager.cs | 50 +++ KoiCatalog.Gui/CustomExpanderStyle.xaml | 73 ++++ KoiCatalog.Gui/CustomMessageDialog.xaml | 72 ++++ KoiCatalog.Gui/CustomMessageDialog.xaml.cs | 364 ++++++++++++++++++ KoiCatalog.Gui/CustomProgressBar.xaml | 62 +++ KoiCatalog.Gui/CustomProgressBar.xaml.cs | 44 +++ KoiCatalog.Gui/DataTableView.xaml | 143 +++++++ KoiCatalog.Gui/DataTableView.xaml.cs | 243 ++++++++++++ KoiCatalog.Gui/DatabaseStatusView.xaml | 112 ++++++ KoiCatalog.Gui/DatabaseStatusView.xaml.cs | 29 ++ KoiCatalog.Gui/Document.cs | 24 ++ KoiCatalog.Gui/EventViewer.xaml | 144 +++++++ KoiCatalog.Gui/EventViewer.xaml.cs | 56 +++ KoiCatalog.Gui/Icons.xaml | 90 +++++ KoiCatalog.Gui/KoiCatalog.Gui.csproj | 284 ++++++++++++++ KoiCatalog.Gui/MainWindow.xaml | 184 +++++++++ KoiCatalog.Gui/MainWindow.xaml.cs | 311 +++++++++++++++ KoiCatalog.Gui/PathTrimmingTextBlock.cs | 153 ++++++++ KoiCatalog.Gui/Properties/AssemblyInfo.cs | 53 +++ .../Properties/Resources.Designer.cs | 71 ++++ KoiCatalog.Gui/Properties/Resources.resx | 117 ++++++ .../Properties/Settings.Designer.cs | 30 ++ KoiCatalog.Gui/Properties/Settings.settings | 7 + KoiCatalog.Gui/QueryEditorView.xaml | 222 +++++++++++ KoiCatalog.Gui/QueryEditorView.xaml.cs | 46 +++ KoiCatalog.Gui/ResultsDocument.xaml | 52 +++ KoiCatalog.Gui/ResultsDocument.xaml.cs | 131 +++++++ KoiCatalog.Gui/StartPageDocument.xaml | 114 ++++++ KoiCatalog.Gui/StartPageDocument.xaml.cs | 48 +++ KoiCatalog.Gui/StatsView.xaml | 70 ++++ KoiCatalog.Gui/StatsView.xaml.cs | 21 + KoiCatalog.Gui/TipsControl.xaml | 40 ++ KoiCatalog.Gui/TipsControl.xaml.cs | 10 + .../BitmapImageValueConverter.cs | 51 +++ .../BooleanToCollapsedValueConverter.cs | 29 ++ .../ColorMultiplyValueConverter.cs | 35 ++ .../ColorToBrushValueConverter.cs | 28 ++ .../ValueConverters/ColorValueConverter.cs | 32 ++ .../ValueConverters/CompoundValueConverter.cs | 34 ++ .../ValueConverters/DisplayValueConverter.cs | 42 ++ .../FloatToSliderValueValueConverter.cs | 29 ++ .../IsNotNullOrEmptyValueConverter.cs | 32 ++ .../ValueConverters/IsNullValueConverter.cs | 24 ++ .../ValueConverters/RatioValueConverter.cs | 34 ++ .../SexToStringValueConverter.cs | 45 +++ .../StringJoinValueConverter.cs | 31 ++ .../TaskbarItemProgressStateValueConverter.cs | 39 ++ .../TypeToGridColumnCountValueConverter.cs | 42 ++ .../ValueConverters/TypeValueConverter.cs | 24 ++ KoiCatalog.Gui/icon.ico | Bin 0 -> 304215 bytes KoiCatalog.Gui/packages.config | 6 + KoiCatalog.sln | 67 ++++ KoiCatalog/Data/Component.cs | 23 ++ KoiCatalog/Data/ComponentTypeCode.cs | 48 +++ KoiCatalog/Data/CompoundQueryHandler.cs | 37 ++ KoiCatalog/Data/CompressionMethod.cs | 8 + KoiCatalog/Data/Database.cs | 229 +++++++++++ KoiCatalog/Data/DatabaseEvent.cs | 27 ++ KoiCatalog/Data/DatabaseEventEventArgs.cs | 14 + KoiCatalog/Data/DatabaseEventType.cs | 16 + KoiCatalog/Data/DatabaseLoadMethod.cs | 61 +++ KoiCatalog/Data/DirectDatabaseConnection.cs | 100 +++++ KoiCatalog/Data/DisplayAttribute.cs | 30 ++ KoiCatalog/Data/Entity.cs | 60 +++ KoiCatalog/Data/EventSeverity.cs | 9 + KoiCatalog/Data/FilteredEntity.cs | 28 ++ KoiCatalog/Data/FullAccessComponentFilter.cs | 13 + KoiCatalog/Data/IDatabaseConnection.cs | 34 ++ KoiCatalog/Data/IDatabaseLoadMethod.cs | 14 + KoiCatalog/Data/IDatabaseSaveMethod.cs | 10 + KoiCatalog/Data/ILogger.cs | 7 + KoiCatalog/Data/IReadOnlyComponentFilter.cs | 7 + KoiCatalog/Data/IReadOnlyEntity.cs | 9 + KoiCatalog/Data/Progress.cs | 14 + KoiCatalog/Data/Query.cs | 111 ++++++ KoiCatalog/Data/QueryFormat.cs | 157 ++++++++ KoiCatalog/Data/QueryFormatParameter.cs | 32 ++ KoiCatalog/Data/QueryHandler.cs | 8 + KoiCatalog/Data/QueryParameter.cs | 73 ++++ KoiCatalog/Data/QueryParameterTemplate.cs | 23 ++ .../Data/QueryParameterTemplateCategory.cs | 14 + KoiCatalog/Data/QueryResult.cs | 12 + KoiCatalog/Data/ReadOnlyComponentFilter.cs | 23 ++ KoiCatalog/Data/ReadOnlyEntity.cs | 24 ++ KoiCatalog/Data/ReadOnlyEntityExtension.cs | 20 + KoiCatalog/Data/SerializationConstants.cs | 10 + KoiCatalog/Data/SerializationFormat.cs | 7 + .../Data/SerializedDatabaseLoadMethod.cs | 96 +++++ .../Data/SerializedDatabaseSaveMethod.cs | 57 +++ KoiCatalog/Data/Stat.cs | 57 +++ KoiCatalog/Data/Stats.cs | 34 ++ KoiCatalog/Data/StatsCategory.cs | 34 ++ KoiCatalog/Data/StatsHandler.cs | 7 + KoiCatalog/Data/StatsLoader.cs | 8 + KoiCatalog/Data/Visibility.cs | 9 + .../Drawing/ConcurrentCachingPalette.cs | 35 ++ KoiCatalog/Drawing/Palettes.cs | 22 ++ KoiCatalog/IO/BinaryReaderExtension.cs | 15 + KoiCatalog/IO/IOUtil.cs | 29 ++ KoiCatalog/IO/PngFile.cs | 45 +++ .../KoiCatalog.Resources/Palettes/Hair.pal | 17 + .../KoiCatalog.Resources/Palettes/Skin.pal | 2 + KoiCatalog/KoiCatalog.csproj | 114 ++++++ KoiCatalog/Plugins/OverallStatsHandler.cs | 24 ++ KoiCatalog/Plugins/PluginManager.cs | 96 +++++ KoiCatalog/Plugins/QueryUtil.cs | 28 ++ KoiCatalog/Properties/AssemblyInfo.cs | 35 ++ KoiCatalog/Resources.cs | 87 +++++ KoiCatalog/Util/AutoSizingList.cs | 46 +++ KoiCatalog/Util/ConcurrentList.cs | 123 ++++++ KoiCatalog/Util/Disposable.cs | 31 ++ KoiCatalog/Util/EnumeratorExtension.cs | 17 + KoiCatalog/Util/ICloneable.cs | 9 + KoiCatalog/Util/StringUtil.cs | 154 ++++++++ License.txt | 77 ++++ PalettePal/Drawing/Adjective.cs | 107 +++++ PalettePal/Drawing/Color.cs | 209 ++++++++++ PalettePal/Drawing/ColorConversion.cs | 160 ++++++++ PalettePal/Drawing/ColorFilter.cs | 18 + PalettePal/Drawing/ColorGradingColorFilter.cs | 13 + PalettePal/Drawing/ColorSample.cs | 52 +++ PalettePal/Drawing/ColorSampleCollection.cs | 39 ++ PalettePal/Drawing/Colors.cs | 8 + PalettePal/Drawing/IColorFilter.cs | 7 + PalettePal/Drawing/NullColorFilter.cs | 10 + PalettePal/Drawing/Palette.cs | 67 ++++ PalettePal/Drawing/Size.cs | 14 + PalettePal/Drawing/Texture3D.cs | 134 +++++++ PalettePal/Math/BinaryPoint.cs | 14 + PalettePal/Math/MathEx.cs | 21 + PalettePal/Math/PointCloudBinaryMatrix.cs | 30 ++ PalettePal/Math/Vector3.cs | 175 +++++++++ PalettePal/Math/Vector3i.cs | 190 +++++++++ PalettePal/PalettePal.csproj | 61 +++ PalettePal/PalettePal.csproj.DotSettings | 4 + PalettePal/Properties/AssemblyInfo.cs | 35 ++ PalettePal/XmlUtil.cs | 88 +++++ .../FileIO/CompoundDefaultDirectoryHandler.cs | 31 ++ Plugins/FileIO/CompoundFileHandler.cs | 67 ++++ .../CreateFromDirectoryDatabaseLoadMethod.cs | 154 ++++++++ Plugins/FileIO/DefaultDirectory.cs | 21 + Plugins/FileIO/DefaultDirectoryHandler.cs | 11 + Plugins/FileIO/FileHandler.cs | 8 + .../FileIO/FileHandlerDependencyAttribute.cs | 20 + Plugins/FileIO/FileIO.csproj | 59 +++ Plugins/FileIO/FileIOUtil.cs | 12 + Plugins/FileIO/FileInfo.cs | 59 +++ Plugins/FileIO/FileInfoFileHandler.cs | 11 + Plugins/FileIO/FileInfoQueryHandler.cs | 48 +++ Plugins/FileIO/FileInfoStatsHandler.cs | 24 ++ Plugins/FileIO/FileLoader.cs | 25 ++ Plugins/FileIO/Properties/AssemblyInfo.cs | 35 ++ Plugins/Koikatu/BlockHeader.cs | 27 ++ Plugins/Koikatu/BloodType.cs | 10 + Plugins/Koikatu/BustSizeType.cs | 9 + Plugins/Koikatu/ChaFile.cs | 91 +++++ Plugins/Koikatu/ChaFileAccessory.cs | 26 ++ Plugins/Koikatu/ChaFileBody.cs | 36 ++ Plugins/Koikatu/ChaFileClothes.cs | 33 ++ Plugins/Koikatu/ChaFileCoordinate.cs | 43 +++ Plugins/Koikatu/ChaFileCustom.cs | 36 ++ Plugins/Koikatu/ChaFileDefine.cs | 167 ++++++++ Plugins/Koikatu/ChaFileFace.cs | 61 +++ Plugins/Koikatu/ChaFileHair.cs | 30 ++ Plugins/Koikatu/ChaFileMakeup.cs | 21 + Plugins/Koikatu/ChaFileParameter.cs | 81 ++++ Plugins/Koikatu/ChaFileStatus.cs | 66 ++++ Plugins/Koikatu/ClubActivity.cs | 12 + Plugins/Koikatu/ColorFilters.cs | 20 + Plugins/Koikatu/HairStyle.cs | 12 + Plugins/Koikatu/HeightType.cs | 9 + .../Koikatu.Resources/ColorFilters/Normal.png | Bin 0 -> 7641 bytes Plugins/Koikatu/Koikatu.csproj | 104 +++++ Plugins/Koikatu/KoikatuCharacterCard.cs | 117 ++++++ .../KoikatuCharacterCardQueryHandler.cs | 160 ++++++++ .../KoikatuCharacterCardStatsHandler.cs | 38 ++ Plugins/Koikatu/KoikatuColorConversion.cs | 29 ++ Plugins/Koikatu/KoikatuConstants.cs | 25 ++ .../Koikatu/KoikatuDefaultDirectoryHandler.cs | 72 ++++ Plugins/Koikatu/KoikatuFileHandler.cs | 38 ++ Plugins/Koikatu/Personality.cs | 42 ++ Plugins/Koikatu/Properties/AssemblyInfo.cs | 35 ++ Plugins/Koikatu/Sex.cs | 8 + Plugins/Koikatu/SkinType.cs | 11 + Plugins/Koikatu/TeethType.cs | 8 + Plugins/Koikatu/packages.config | 7 + Readme.html | 74 ++++ Readme.md | 37 ++ Resources/Media/Logo.png | Bin 0 -> 13289 bytes Resources/Media/Screenshots/1.png | Bin 0 -> 51900 bytes Resources/Media/Screenshots/2.png | Bin 0 -> 124956 bytes Resources/Media/Style.css | 76 ++++ SimpleErrorReporter/ErrorReporter.cs | 106 +++++ SimpleErrorReporter/MessageEventArgs.cs | 15 + .../Properties/AssemblyInfo.cs | 35 ++ .../SimpleErrorReporter.csproj | 42 ++ Where is the program.html | 32 ++ 236 files changed, 13262 insertions(+) create mode 100644 .gitignore create mode 100644 KoiCatalog.App/ActionLockTarget.cs create mode 100644 KoiCatalog.App/CancellableTask.cs create mode 100644 KoiCatalog.App/CancellableTaskGroup.cs create mode 100644 KoiCatalog.App/Data/DataColumn.cs create mode 100644 KoiCatalog.App/Data/DataRow.cs create mode 100644 KoiCatalog.App/Data/DataTable.cs create mode 100644 KoiCatalog.App/DatabaseLoadMode.cs create mode 100644 KoiCatalog.App/DatabaseLoadingState.cs create mode 100644 KoiCatalog.App/DatabaseStatus.cs create mode 100644 KoiCatalog.App/DatabaseStatusState.cs create mode 100644 KoiCatalog.App/DatabaseToDatabaseStatusService.cs create mode 100644 KoiCatalog.App/DatabaseToQueryFormatService.cs create mode 100644 KoiCatalog.App/DatabaseToStatsService.cs create mode 100644 KoiCatalog.App/DatabaseUtil.cs create mode 100644 KoiCatalog.App/GlobalOptions.cs create mode 100644 KoiCatalog.App/IOUtil.cs create mode 100644 KoiCatalog.App/KoiCatalog.App.csproj create mode 100644 KoiCatalog.App/KoiCatalogApp.cs create mode 100644 KoiCatalog.App/ProgramInfo.cs create mode 100644 KoiCatalog.App/Properties/AssemblyInfo.cs create mode 100644 KoiCatalog.App/QueryCleanupService.cs create mode 100644 KoiCatalog.App/QueryEditor.cs create mode 100644 KoiCatalog.App/QueryEditorParameter.cs create mode 100644 KoiCatalog.App/QueryEditorParameterSelectableValue.cs create mode 100644 KoiCatalog.App/QueryFormatToQueryEditorService.cs create mode 100644 KoiCatalog.App/QueryToQueryResultsService.cs create mode 100644 KoiCatalog.App/Util.cs create mode 100644 KoiCatalog.Gui/AboutControl.xaml create mode 100644 KoiCatalog.Gui/AboutControl.xaml.cs create mode 100644 KoiCatalog.Gui/App.config create mode 100644 KoiCatalog.Gui/App.xaml create mode 100644 KoiCatalog.Gui/App.xaml.cs create mode 100644 KoiCatalog.Gui/AppStartup.cs create mode 100644 KoiCatalog.Gui/ColorControl.xaml create mode 100644 KoiCatalog.Gui/ColorControl.xaml.cs create mode 100644 KoiCatalog.Gui/Colors.xaml create mode 100644 KoiCatalog.Gui/Commands.cs create mode 100644 KoiCatalog.Gui/ConditionalStyleSelector.cs create mode 100644 KoiCatalog.Gui/CustomDialogManager.cs create mode 100644 KoiCatalog.Gui/CustomExpanderStyle.xaml create mode 100644 KoiCatalog.Gui/CustomMessageDialog.xaml create mode 100644 KoiCatalog.Gui/CustomMessageDialog.xaml.cs create mode 100644 KoiCatalog.Gui/CustomProgressBar.xaml create mode 100644 KoiCatalog.Gui/CustomProgressBar.xaml.cs create mode 100644 KoiCatalog.Gui/DataTableView.xaml create mode 100644 KoiCatalog.Gui/DataTableView.xaml.cs create mode 100644 KoiCatalog.Gui/DatabaseStatusView.xaml create mode 100644 KoiCatalog.Gui/DatabaseStatusView.xaml.cs create mode 100644 KoiCatalog.Gui/Document.cs create mode 100644 KoiCatalog.Gui/EventViewer.xaml create mode 100644 KoiCatalog.Gui/EventViewer.xaml.cs create mode 100644 KoiCatalog.Gui/Icons.xaml create mode 100644 KoiCatalog.Gui/KoiCatalog.Gui.csproj create mode 100644 KoiCatalog.Gui/MainWindow.xaml create mode 100644 KoiCatalog.Gui/MainWindow.xaml.cs create mode 100644 KoiCatalog.Gui/PathTrimmingTextBlock.cs create mode 100644 KoiCatalog.Gui/Properties/AssemblyInfo.cs create mode 100644 KoiCatalog.Gui/Properties/Resources.Designer.cs create mode 100644 KoiCatalog.Gui/Properties/Resources.resx create mode 100644 KoiCatalog.Gui/Properties/Settings.Designer.cs create mode 100644 KoiCatalog.Gui/Properties/Settings.settings create mode 100644 KoiCatalog.Gui/QueryEditorView.xaml create mode 100644 KoiCatalog.Gui/QueryEditorView.xaml.cs create mode 100644 KoiCatalog.Gui/ResultsDocument.xaml create mode 100644 KoiCatalog.Gui/ResultsDocument.xaml.cs create mode 100644 KoiCatalog.Gui/StartPageDocument.xaml create mode 100644 KoiCatalog.Gui/StartPageDocument.xaml.cs create mode 100644 KoiCatalog.Gui/StatsView.xaml create mode 100644 KoiCatalog.Gui/StatsView.xaml.cs create mode 100644 KoiCatalog.Gui/TipsControl.xaml create mode 100644 KoiCatalog.Gui/TipsControl.xaml.cs create mode 100644 KoiCatalog.Gui/ValueConverters/BitmapImageValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/BooleanToCollapsedValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/ColorMultiplyValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/ColorToBrushValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/ColorValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/CompoundValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/DisplayValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/FloatToSliderValueValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/IsNotNullOrEmptyValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/IsNullValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/RatioValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/SexToStringValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/StringJoinValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/TaskbarItemProgressStateValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/TypeToGridColumnCountValueConverter.cs create mode 100644 KoiCatalog.Gui/ValueConverters/TypeValueConverter.cs create mode 100644 KoiCatalog.Gui/icon.ico create mode 100644 KoiCatalog.Gui/packages.config create mode 100644 KoiCatalog.sln create mode 100644 KoiCatalog/Data/Component.cs create mode 100644 KoiCatalog/Data/ComponentTypeCode.cs create mode 100644 KoiCatalog/Data/CompoundQueryHandler.cs create mode 100644 KoiCatalog/Data/CompressionMethod.cs create mode 100644 KoiCatalog/Data/Database.cs create mode 100644 KoiCatalog/Data/DatabaseEvent.cs create mode 100644 KoiCatalog/Data/DatabaseEventEventArgs.cs create mode 100644 KoiCatalog/Data/DatabaseEventType.cs create mode 100644 KoiCatalog/Data/DatabaseLoadMethod.cs create mode 100644 KoiCatalog/Data/DirectDatabaseConnection.cs create mode 100644 KoiCatalog/Data/DisplayAttribute.cs create mode 100644 KoiCatalog/Data/Entity.cs create mode 100644 KoiCatalog/Data/EventSeverity.cs create mode 100644 KoiCatalog/Data/FilteredEntity.cs create mode 100644 KoiCatalog/Data/FullAccessComponentFilter.cs create mode 100644 KoiCatalog/Data/IDatabaseConnection.cs create mode 100644 KoiCatalog/Data/IDatabaseLoadMethod.cs create mode 100644 KoiCatalog/Data/IDatabaseSaveMethod.cs create mode 100644 KoiCatalog/Data/ILogger.cs create mode 100644 KoiCatalog/Data/IReadOnlyComponentFilter.cs create mode 100644 KoiCatalog/Data/IReadOnlyEntity.cs create mode 100644 KoiCatalog/Data/Progress.cs create mode 100644 KoiCatalog/Data/Query.cs create mode 100644 KoiCatalog/Data/QueryFormat.cs create mode 100644 KoiCatalog/Data/QueryFormatParameter.cs create mode 100644 KoiCatalog/Data/QueryHandler.cs create mode 100644 KoiCatalog/Data/QueryParameter.cs create mode 100644 KoiCatalog/Data/QueryParameterTemplate.cs create mode 100644 KoiCatalog/Data/QueryParameterTemplateCategory.cs create mode 100644 KoiCatalog/Data/QueryResult.cs create mode 100644 KoiCatalog/Data/ReadOnlyComponentFilter.cs create mode 100644 KoiCatalog/Data/ReadOnlyEntity.cs create mode 100644 KoiCatalog/Data/ReadOnlyEntityExtension.cs create mode 100644 KoiCatalog/Data/SerializationConstants.cs create mode 100644 KoiCatalog/Data/SerializationFormat.cs create mode 100644 KoiCatalog/Data/SerializedDatabaseLoadMethod.cs create mode 100644 KoiCatalog/Data/SerializedDatabaseSaveMethod.cs create mode 100644 KoiCatalog/Data/Stat.cs create mode 100644 KoiCatalog/Data/Stats.cs create mode 100644 KoiCatalog/Data/StatsCategory.cs create mode 100644 KoiCatalog/Data/StatsHandler.cs create mode 100644 KoiCatalog/Data/StatsLoader.cs create mode 100644 KoiCatalog/Data/Visibility.cs create mode 100644 KoiCatalog/Drawing/ConcurrentCachingPalette.cs create mode 100644 KoiCatalog/Drawing/Palettes.cs create mode 100644 KoiCatalog/IO/BinaryReaderExtension.cs create mode 100644 KoiCatalog/IO/IOUtil.cs create mode 100644 KoiCatalog/IO/PngFile.cs create mode 100644 KoiCatalog/KoiCatalog.Resources/Palettes/Hair.pal create mode 100644 KoiCatalog/KoiCatalog.Resources/Palettes/Skin.pal create mode 100644 KoiCatalog/KoiCatalog.csproj create mode 100644 KoiCatalog/Plugins/OverallStatsHandler.cs create mode 100644 KoiCatalog/Plugins/PluginManager.cs create mode 100644 KoiCatalog/Plugins/QueryUtil.cs create mode 100644 KoiCatalog/Properties/AssemblyInfo.cs create mode 100644 KoiCatalog/Resources.cs create mode 100644 KoiCatalog/Util/AutoSizingList.cs create mode 100644 KoiCatalog/Util/ConcurrentList.cs create mode 100644 KoiCatalog/Util/Disposable.cs create mode 100644 KoiCatalog/Util/EnumeratorExtension.cs create mode 100644 KoiCatalog/Util/ICloneable.cs create mode 100644 KoiCatalog/Util/StringUtil.cs create mode 100644 License.txt create mode 100644 PalettePal/Drawing/Adjective.cs create mode 100644 PalettePal/Drawing/Color.cs create mode 100644 PalettePal/Drawing/ColorConversion.cs create mode 100644 PalettePal/Drawing/ColorFilter.cs create mode 100644 PalettePal/Drawing/ColorGradingColorFilter.cs create mode 100644 PalettePal/Drawing/ColorSample.cs create mode 100644 PalettePal/Drawing/ColorSampleCollection.cs create mode 100644 PalettePal/Drawing/Colors.cs create mode 100644 PalettePal/Drawing/IColorFilter.cs create mode 100644 PalettePal/Drawing/NullColorFilter.cs create mode 100644 PalettePal/Drawing/Palette.cs create mode 100644 PalettePal/Drawing/Size.cs create mode 100644 PalettePal/Drawing/Texture3D.cs create mode 100644 PalettePal/Math/BinaryPoint.cs create mode 100644 PalettePal/Math/MathEx.cs create mode 100644 PalettePal/Math/PointCloudBinaryMatrix.cs create mode 100644 PalettePal/Math/Vector3.cs create mode 100644 PalettePal/Math/Vector3i.cs create mode 100644 PalettePal/PalettePal.csproj create mode 100644 PalettePal/PalettePal.csproj.DotSettings create mode 100644 PalettePal/Properties/AssemblyInfo.cs create mode 100644 PalettePal/XmlUtil.cs create mode 100644 Plugins/FileIO/CompoundDefaultDirectoryHandler.cs create mode 100644 Plugins/FileIO/CompoundFileHandler.cs create mode 100644 Plugins/FileIO/CreateFromDirectoryDatabaseLoadMethod.cs create mode 100644 Plugins/FileIO/DefaultDirectory.cs create mode 100644 Plugins/FileIO/DefaultDirectoryHandler.cs create mode 100644 Plugins/FileIO/FileHandler.cs create mode 100644 Plugins/FileIO/FileHandlerDependencyAttribute.cs create mode 100644 Plugins/FileIO/FileIO.csproj create mode 100644 Plugins/FileIO/FileIOUtil.cs create mode 100644 Plugins/FileIO/FileInfo.cs create mode 100644 Plugins/FileIO/FileInfoFileHandler.cs create mode 100644 Plugins/FileIO/FileInfoQueryHandler.cs create mode 100644 Plugins/FileIO/FileInfoStatsHandler.cs create mode 100644 Plugins/FileIO/FileLoader.cs create mode 100644 Plugins/FileIO/Properties/AssemblyInfo.cs create mode 100644 Plugins/Koikatu/BlockHeader.cs create mode 100644 Plugins/Koikatu/BloodType.cs create mode 100644 Plugins/Koikatu/BustSizeType.cs create mode 100644 Plugins/Koikatu/ChaFile.cs create mode 100644 Plugins/Koikatu/ChaFileAccessory.cs create mode 100644 Plugins/Koikatu/ChaFileBody.cs create mode 100644 Plugins/Koikatu/ChaFileClothes.cs create mode 100644 Plugins/Koikatu/ChaFileCoordinate.cs create mode 100644 Plugins/Koikatu/ChaFileCustom.cs create mode 100644 Plugins/Koikatu/ChaFileDefine.cs create mode 100644 Plugins/Koikatu/ChaFileFace.cs create mode 100644 Plugins/Koikatu/ChaFileHair.cs create mode 100644 Plugins/Koikatu/ChaFileMakeup.cs create mode 100644 Plugins/Koikatu/ChaFileParameter.cs create mode 100644 Plugins/Koikatu/ChaFileStatus.cs create mode 100644 Plugins/Koikatu/ClubActivity.cs create mode 100644 Plugins/Koikatu/ColorFilters.cs create mode 100644 Plugins/Koikatu/HairStyle.cs create mode 100644 Plugins/Koikatu/HeightType.cs create mode 100644 Plugins/Koikatu/Koikatu.Resources/ColorFilters/Normal.png create mode 100644 Plugins/Koikatu/Koikatu.csproj create mode 100644 Plugins/Koikatu/KoikatuCharacterCard.cs create mode 100644 Plugins/Koikatu/KoikatuCharacterCardQueryHandler.cs create mode 100644 Plugins/Koikatu/KoikatuCharacterCardStatsHandler.cs create mode 100644 Plugins/Koikatu/KoikatuColorConversion.cs create mode 100644 Plugins/Koikatu/KoikatuConstants.cs create mode 100644 Plugins/Koikatu/KoikatuDefaultDirectoryHandler.cs create mode 100644 Plugins/Koikatu/KoikatuFileHandler.cs create mode 100644 Plugins/Koikatu/Personality.cs create mode 100644 Plugins/Koikatu/Properties/AssemblyInfo.cs create mode 100644 Plugins/Koikatu/Sex.cs create mode 100644 Plugins/Koikatu/SkinType.cs create mode 100644 Plugins/Koikatu/TeethType.cs create mode 100644 Plugins/Koikatu/packages.config create mode 100644 Readme.html create mode 100644 Readme.md create mode 100644 Resources/Media/Logo.png create mode 100644 Resources/Media/Screenshots/1.png create mode 100644 Resources/Media/Screenshots/2.png create mode 100644 Resources/Media/Style.css create mode 100644 SimpleErrorReporter/ErrorReporter.cs create mode 100644 SimpleErrorReporter/MessageEventArgs.cs create mode 100644 SimpleErrorReporter/Properties/AssemblyInfo.cs create mode 100644 SimpleErrorReporter/SimpleErrorReporter.csproj create mode 100644 Where is the program.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ff3a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/.vs/ +/packages/ +bin/ +obj/ +*.user diff --git a/KoiCatalog.App/ActionLockTarget.cs b/KoiCatalog.App/ActionLockTarget.cs new file mode 100644 index 0000000..265b9a3 --- /dev/null +++ b/KoiCatalog.App/ActionLockTarget.cs @@ -0,0 +1,56 @@ +using System; +using KoiCatalog.Util; + +namespace KoiCatalog.App +{ + public sealed class ActionLockTarget + { + private int LockDepth + { + get => _lockDepth; + set + { + if (value < 0) + throw new InvalidOperationException(); + _lockDepth = value; + } + } + private int _lockDepth; + + public bool IsLocked => LockDepth != 0; + + public ActionLockHandle AcquireLock() + { + return new ActionLockHandle(this); + } + + public sealed class ActionLockHandle : Disposable + { + private ActionLockTarget Owner { get; } + + internal ActionLockHandle(ActionLockTarget owner) + { + if (owner == null) throw new ArgumentNullException(nameof(owner)); + Owner = owner; + Owner.PushLock(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Owner.PopLock(); + } + else + { + throw new InvalidOperationException("Undisposed object detected."); + } + + base.Dispose(disposing); + } + } + + private void PushLock() => LockDepth++; + private void PopLock() => LockDepth--; + } +} diff --git a/KoiCatalog.App/CancellableTask.cs b/KoiCatalog.App/CancellableTask.cs new file mode 100644 index 0000000..110fe6d --- /dev/null +++ b/KoiCatalog.App/CancellableTask.cs @@ -0,0 +1,19 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace KoiCatalog.App +{ + public sealed class CancellableTask + { + public Task Task { get; } + public CancellationTokenSource CancellationTokenSource { get; } + + public CancellableTask(Task task, CancellationTokenSource cancellationTokenSource) + { + if (task == null) throw new ArgumentNullException(nameof(task)); + Task = task; + CancellationTokenSource = cancellationTokenSource; + } + } +} diff --git a/KoiCatalog.App/CancellableTaskGroup.cs b/KoiCatalog.App/CancellableTaskGroup.cs new file mode 100644 index 0000000..aeed882 --- /dev/null +++ b/KoiCatalog.App/CancellableTaskGroup.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace KoiCatalog.App +{ + public sealed class CancellableTaskGroup + { + private List Tasks { get; } = new List(); + + private void FlushCompletedTasks() + { + Tasks.RemoveAll(i => i.Task.IsCompleted); + } + + public void Add(CancellableTask task) + { + if (task == null) throw new ArgumentNullException(nameof(task)); + Tasks.Add(task); + FlushCompletedTasks(); + } + + public bool IsAnyTaskRunning + { + get { return Tasks.Any(i => !i.Task.IsCompleted); } + } + + public void WaitAll() + { + Task.WaitAll(Tasks.Select(i => i.Task).ToArray()); + } + + public void CancelAll() + { + foreach (var task in Tasks) + { + task.CancellationTokenSource.Cancel(); + } + } + } +} diff --git a/KoiCatalog.App/Data/DataColumn.cs b/KoiCatalog.App/Data/DataColumn.cs new file mode 100644 index 0000000..7601052 --- /dev/null +++ b/KoiCatalog.App/Data/DataColumn.cs @@ -0,0 +1,16 @@ +using System; +using System.Reflection; + +namespace KoiCatalog.App.Data +{ + public sealed class DataColumn + { + public PropertyInfo Property { get; } + + public DataColumn(PropertyInfo property) + { + if (property == null) throw new ArgumentNullException(nameof(property)); + Property = property; + } + } +} diff --git a/KoiCatalog.App/Data/DataRow.cs b/KoiCatalog.App/Data/DataRow.cs new file mode 100644 index 0000000..9f23ef6 --- /dev/null +++ b/KoiCatalog.App/Data/DataRow.cs @@ -0,0 +1,23 @@ +using System; + +namespace KoiCatalog.App.Data +{ + public sealed class DataRow + { + private DataTable DataTable { get; } + private object[] Values { get; } + + public object this[int index] + { + get => Values[index]; + set => Values[index] = value; + } + + internal DataRow(DataTable dataTable) + { + if (dataTable == null) throw new ArgumentNullException(nameof(dataTable)); + DataTable = dataTable; + Values = new object[dataTable.Columns.Count]; + } + } +} diff --git a/KoiCatalog.App/Data/DataTable.cs b/KoiCatalog.App/Data/DataTable.cs new file mode 100644 index 0000000..9dca8bd --- /dev/null +++ b/KoiCatalog.App/Data/DataTable.cs @@ -0,0 +1,23 @@ +using System.Collections.ObjectModel; + +namespace KoiCatalog.App.Data +{ + public sealed class DataTable + { + public ObservableCollection Columns { get; } = + new ObservableCollection(); + + public ObservableCollection Rows { get; } = + new ObservableCollection(); + + public void Clear() + { + Rows.Clear(); + } + + public DataRow NewRow() + { + return new DataRow(this); + } + } +} diff --git a/KoiCatalog.App/DatabaseLoadMode.cs b/KoiCatalog.App/DatabaseLoadMode.cs new file mode 100644 index 0000000..fec5391 --- /dev/null +++ b/KoiCatalog.App/DatabaseLoadMode.cs @@ -0,0 +1,10 @@ +namespace KoiCatalog.App +{ + public enum DatabaseLoadMode + { + Auto, + LoadCache, + Rebuild, + Refresh, + } +} diff --git a/KoiCatalog.App/DatabaseLoadingState.cs b/KoiCatalog.App/DatabaseLoadingState.cs new file mode 100644 index 0000000..d97107f --- /dev/null +++ b/KoiCatalog.App/DatabaseLoadingState.cs @@ -0,0 +1,9 @@ +namespace KoiCatalog.App +{ + public enum DatabaseLoadingState + { + None, + Normal, + Indeterminate, + } +} diff --git a/KoiCatalog.App/DatabaseStatus.cs b/KoiCatalog.App/DatabaseStatus.cs new file mode 100644 index 0000000..bfb05ec --- /dev/null +++ b/KoiCatalog.App/DatabaseStatus.cs @@ -0,0 +1,87 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using KoiCatalog.Data; + +namespace KoiCatalog.App +{ + public sealed class DatabaseStatus : INotifyPropertyChanged + { + public ObservableCollection Events { get; } = + new ObservableCollection(); + + public Progress Progress + { + get => _progress; + set + { + _progress = value; + NotifyPropertyChanged(); + NotifyPropertyChanged(nameof(LoadingState)); + } + } + private Progress _progress; + + public DatabaseStatusState State + { + get => _state; + set + { + _state = value; + NotifyPropertyChanged(); + NotifyPropertyChanged(nameof(LoadingState)); + } + } + private DatabaseStatusState _state = DatabaseStatusState.Ready; + + public DatabaseLoadingState LoadingState + { + get + { + if (State == DatabaseStatusState.Ready) + return DatabaseLoadingState.None; + if (Progress == null) + return DatabaseLoadingState.Indeterminate; + return DatabaseLoadingState.Normal; + } + } + + public int TotalDatabaseItemCount + { + get => _totalDatabaseItemCount; + set + { + if (value == _totalDatabaseItemCount) return; + _totalDatabaseItemCount = value; + NotifyPropertyChanged(); + } + } + private int _totalDatabaseItemCount; + + public event PropertyChangedEventHandler PropertyChanged; + private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + public static DatabaseStatusState? DatabaseEventTypeToStatusStatus(DatabaseEventType eventType) + { + switch (eventType) + { + case DatabaseEventType.SaveStart: + return DatabaseStatusState.Saving; + case DatabaseEventType.ScanStart: + return DatabaseStatusState.Scanning; + case DatabaseEventType.LoadStart: + case DatabaseEventType.LoadProgress: + return DatabaseStatusState.Loading; + case DatabaseEventType.SaveEnd: + case DatabaseEventType.ScanEnd: + case DatabaseEventType.LoadEnd: + return DatabaseStatusState.Ready; + default: + return null; + } + } + } +} diff --git a/KoiCatalog.App/DatabaseStatusState.cs b/KoiCatalog.App/DatabaseStatusState.cs new file mode 100644 index 0000000..177c265 --- /dev/null +++ b/KoiCatalog.App/DatabaseStatusState.cs @@ -0,0 +1,10 @@ +namespace KoiCatalog.App +{ + public enum DatabaseStatusState + { + Ready, + Scanning, + Loading, + Saving, + } +} diff --git a/KoiCatalog.App/DatabaseToDatabaseStatusService.cs b/KoiCatalog.App/DatabaseToDatabaseStatusService.cs new file mode 100644 index 0000000..d47075f --- /dev/null +++ b/KoiCatalog.App/DatabaseToDatabaseStatusService.cs @@ -0,0 +1,152 @@ +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Windows.Threading; +using KoiCatalog.Data; + +namespace KoiCatalog.App +{ + public sealed class DatabaseToDatabaseStatusService : INotifyPropertyChanged + { + public IDatabaseConnection DatabaseConnection + { + get => _databaseConnection; + set + { + if (value == _databaseConnection) return; + + if (_databaseConnection != null) + { + _databaseConnection.Connected -= DatabaseConnectionOnConnected; + _databaseConnection.EventOccurred -= DatabaseConnectionOnEventOccurred; + } + + _databaseConnection = value; + + if (_databaseConnection != null) + { + _databaseConnection.Connected += DatabaseConnectionOnConnected; + _databaseConnection.EventOccurred += DatabaseConnectionOnEventOccurred; + } + + Reset(); + BeginRefresh(); + NotifyPropertyChanged(); + } + } + private IDatabaseConnection _databaseConnection; + + public DatabaseStatus DatabaseStatus + { + get => _databaseStatus; + set + { + if (value == _databaseStatus) return; + _databaseStatus = value; + Reset(); + BeginRefresh(); + NotifyPropertyChanged(); + } + } + private DatabaseStatus _databaseStatus = new DatabaseStatus(); + + private void Reset() + { + Cancel(); + if (DatabaseStatus != null) + { + DatabaseStatus.TotalDatabaseItemCount = 0; + DatabaseStatus.State = DatabaseStatusState.Ready; + DatabaseStatus.Progress = null; + } + } + + private void DatabaseConnectionOnConnected(object sender, EventArgs e) + { + KoiCatalogApp.Current.Dispatcher.BeginInvoke(new Action(() => + { + Reset(); + BeginRefresh(); + })); + } + + private void DatabaseConnectionOnEventOccurred(object sender, DatabaseEventEventArgs e) + { + KoiCatalogApp.Current.Dispatcher.BeginInvoke(new Action(() => + { + if (DatabaseStatus == null) return; + + DatabaseStatus.State = DatabaseStatus.DatabaseEventTypeToStatusStatus(e.Event.EventType) ?? DatabaseStatus.State; + + if (e.Event.EventType == DatabaseEventType.LoadStart) + { + DatabaseStatus.Events.Clear(); + BeginRefresh(); + } + if (e.Event.EventType == DatabaseEventType.LoadProgress) + { + DatabaseStatus.Progress = e.Event.Progress; + } + if (e.Event.EventType == DatabaseEventType.LoadEnd) + { + DatabaseStatus.Progress = null; + } + + DatabaseStatus.Events.Add(e.Event); + })); + } + + public void BeginRefresh() + { + Cancel(); + if (DatabaseStatus == null) return; + + DatabaseStatus.TotalDatabaseItemCount = 0; + + if (DatabaseConnection == null) return; + if (!DatabaseConnection.IsConnected) return; + + RefreshCancellationToken = new CancellationTokenSource(); + var cancellationToken = RefreshCancellationToken.Token; + + var newTotalDatabaseItems = 0; + var task = DatabaseConnection.SubmitQueryAsync(new Query(), + result => Interlocked.Increment(ref newTotalDatabaseItems), cancellationToken); + + const int updateInterval = 500; + + var timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromMilliseconds(updateInterval); + timer.Tick += (sender, e) => + { + if (cancellationToken.IsCancellationRequested) + { + timer.Stop(); + return; + } + + if (task.IsCompleted) + timer.Stop(); + else + timer.Start(); + + DatabaseStatus.TotalDatabaseItemCount = newTotalDatabaseItems; + }; + timer.Start(); + } + + public void Cancel() + { + RefreshCancellationToken?.Cancel(); + } + + private CancellationTokenSource RefreshCancellationToken { get; set; } + + public event PropertyChangedEventHandler PropertyChanged; + private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/KoiCatalog.App/DatabaseToQueryFormatService.cs b/KoiCatalog.App/DatabaseToQueryFormatService.cs new file mode 100644 index 0000000..deb7c5f --- /dev/null +++ b/KoiCatalog.App/DatabaseToQueryFormatService.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Windows.Threading; +using KoiCatalog.Data; + +namespace KoiCatalog.App +{ + public sealed class DatabaseToQueryFormatService : INotifyPropertyChanged + { + public IDatabaseConnection DatabaseConnection + { + get => _databaseConnection; + set + { + if (_databaseConnection == value) return; + + if (_databaseConnection != null) + { + _databaseConnection.Connected -= DatabaseConnectionOnConnected; + _databaseConnection.EventOccurred -= DatabaseConnectionOnEventOccurred; + } + + _databaseConnection = value; + + if (_databaseConnection != null) + { + _databaseConnection.Connected += DatabaseConnectionOnConnected; + _databaseConnection.EventOccurred += DatabaseConnectionOnEventOccurred; + } + + BeginRefreshQueryFormat(); + OnPropertyChanged(); + } + } + private IDatabaseConnection _databaseConnection; + + public ObservableCollection ComponentFilter + { + get => _componentFilter; + set + { + if (value == _componentFilter) return; + + if (_componentFilter != null) + { + ComponentFilter.CollectionChanged -= ComponentsOnCollectionChanged; + } + + _componentFilter = value; + + if (_componentFilter != null) + { + ComponentFilter.CollectionChanged += ComponentsOnCollectionChanged; + } + + BeginRefreshQueryFormat(); + OnPropertyChanged(); + } + } + private ObservableCollection _componentFilter = + new ObservableCollection(); + + public QueryFormat QueryFormat + { + get => _queryFormat; + set + { + if (value == _queryFormat) return; + _queryFormat = value; + BeginRefreshQueryFormat(); + OnPropertyChanged(); + } + } + private QueryFormat _queryFormat = new QueryFormat(); + + public DatabaseToQueryFormatService() + { + ComponentFilter = new ObservableCollection(); + } + + private void ComponentsOnCollectionChanged(object o, NotifyCollectionChangedEventArgs e) + { + BeginRefreshQueryFormat(); + } + + private void DatabaseConnectionOnEventOccurred(object sender, DatabaseEventEventArgs e) + { + if (e.Event.EventType == DatabaseEventType.LoadStart) + { + KoiCatalogApp.Current.Dispatcher.BeginInvoke(new Action(BeginRefreshQueryFormat)); + } + } + + private void DatabaseConnectionOnConnected(object sender, EventArgs eventArgs) + { + KoiCatalogApp.Current.Dispatcher.BeginInvoke(new Action(BeginRefreshQueryFormat)); + } + + public void Clear() + { + QueryFormat?.Clear(); + } + + public void Cancel() + { + QueryFormatRequestCancellationToken?.Cancel(); + } + + public void ClearAndCancel() + { + Clear(); + Cancel(); + } + + private void BeginRefreshQueryFormat() + { + ClearAndCancel(); + + if (DatabaseConnection == null) return; + if (!DatabaseConnection.IsConnected) return; + if (ComponentFilter == null) return; + + QueryFormatRequestCancellationToken = new CancellationTokenSource(); + var cancellationToken = QueryFormatRequestCancellationToken.Token; + + var results = new BlockingCollection(); + var task = DatabaseConnection.RequestQueryFormatAsync( + ComponentFilter, + result => results.Add(result, cancellationToken), cancellationToken) + .ContinueWith(t => results.CompleteAdding(), cancellationToken); + + const int updateInterval = 100; + const int maximumResultsPerUpdate = 5; + + var timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromMilliseconds(updateInterval); + timer.Tick += (sender, e) => + { + if (cancellationToken.IsCancellationRequested) + { + timer.Stop(); + return; + } + + for (var i = 0; i < maximumResultsPerUpdate; i++) + { + if (results.TryTake(out var result)) + QueryFormat?.PerformAction(result); + else + break; + } + + if (!task.IsCompleted || results.Count > 0 || !results.IsAddingCompleted) + { + timer.Start(); + } + else + { + timer.Stop(); + } + }; + timer.Start(); + } + + private CancellationTokenSource QueryFormatRequestCancellationToken { get; set; } + + public event PropertyChangedEventHandler PropertyChanged; + + private void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/KoiCatalog.App/DatabaseToStatsService.cs b/KoiCatalog.App/DatabaseToStatsService.cs new file mode 100644 index 0000000..00f02e2 --- /dev/null +++ b/KoiCatalog.App/DatabaseToStatsService.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Concurrent; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Windows.Threading; +using KoiCatalog.Data; +using KoiCatalog.Plugins; + +namespace KoiCatalog.App +{ + public sealed class DatabaseToStatsService : INotifyPropertyChanged + { + public IDatabaseConnection DatabaseConnection + { + get => _databaseConnection; + set + { + if (value == _databaseConnection) return; + + if (_databaseConnection != null) + { + _databaseConnection.EventOccurred -= DatabaseOnEventOccurred; + _databaseConnection.Connected -= DatabaseConnectionOnConnected; + } + + _databaseConnection = value; + + if (_databaseConnection != null) + { + _databaseConnection.EventOccurred += DatabaseOnEventOccurred; + _databaseConnection.Connected += DatabaseConnectionOnConnected; + } + + BeginRefresh(); + OnPropertyChanged(); + } + } + private IDatabaseConnection _databaseConnection; + + public Stats Stats + { + get => _stats; + set + { + if (value == _stats) return; + _stats = value; + BeginRefresh(); + OnPropertyChanged(); + } + } + private Stats _stats = new Stats(); + + private void DatabaseConnectionOnConnected(object sender, EventArgs eventArgs) + { + KoiCatalogApp.Current.Dispatcher.BeginInvoke(new Action(BeginRefresh)); + } + + private void DatabaseOnEventOccurred(object sender, DatabaseEventEventArgs e) + { + if (e.Event.EventType == DatabaseEventType.LoadStart) + { + KoiCatalogApp.Current.Dispatcher.BeginInvoke(new Action(BeginRefresh)); + } + } + + private StatsLoader StatsLoader { get; } = new StatsLoader(); + + private StatsHandler[] StatsHandlers { get; } = + PluginManager.GetNewTypes() + .Select(Activator.CreateInstance) + .Cast() + .ToArray(); + + private void AddStatisticsForEntity(IReadOnlyEntity entity) + { + if (Stats == null) return; + + // Todo: Generate stats server-side. + // Todo: Make entity read-only. + StatsLoader.Entity = entity; + StatsLoader.Stats = Stats; + + foreach (var statsHandler in StatsHandlers) + { + try + { + statsHandler.GetStats(StatsLoader); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + } + + public void BeginRefresh() + { + ClearAndCancel(); + + if (Stats == null) return; + if (DatabaseConnection == null) return; + if (!DatabaseConnection.IsConnected) return; + + RefreshCancellationToken = new CancellationTokenSource(); + var cancellationToken = RefreshCancellationToken.Token; + + var results = new BlockingCollection(); + var task = DatabaseConnection.SubmitQueryAsync(new Query(), result => + results.Add(result, cancellationToken), cancellationToken) + .ContinueWith(t => results.CompleteAdding(), cancellationToken); + + const int updateInterval = 100; + const int maximumResultsPerUpdate = 453; + + var timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromMilliseconds(updateInterval); + timer.Tick += (sender, e) => + { + if (cancellationToken.IsCancellationRequested) + { + timer.Stop(); + return; + } + + for (var i = 0; i < maximumResultsPerUpdate; i++) + { + if (results.TryTake(out var result)) + AddStatisticsForEntity(result.Data); + else + break; + } + + if (!task.IsCompleted || results.Count > 0 || !results.IsAddingCompleted) + { + timer.Start(); + } + else + { + timer.Stop(); + } + }; + timer.Start(); + } + + public void Clear() + { + Stats?.Clear(); + } + + public void Cancel() + { + RefreshCancellationToken?.Cancel(); + } + + public void ClearAndCancel() + { + Clear(); + Cancel(); + } + + private CancellationTokenSource RefreshCancellationToken { get; set; } + public event PropertyChangedEventHandler PropertyChanged; + + private void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/KoiCatalog.App/DatabaseUtil.cs b/KoiCatalog.App/DatabaseUtil.cs new file mode 100644 index 0000000..4c4d9d3 --- /dev/null +++ b/KoiCatalog.App/DatabaseUtil.cs @@ -0,0 +1,81 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using KoiCatalog.Data; +using KoiCatalog.Plugins.FileIO; + +namespace KoiCatalog.App +{ + public static class DatabaseUtil + { + /// + /// A high-level database save/load method that handles caching automatically. + /// + /// + /// + /// + /// + /// + /// + public static Task LoadAsync( + this IDatabaseConnection connection, + string directory, + string cacheDirectory, + DatabaseLoadMode mode = DatabaseLoadMode.Auto, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (connection == null) throw new ArgumentNullException(nameof(connection)); + if (directory == null) throw new ArgumentNullException(nameof(directory)); + if (cacheDirectory == null) throw new ArgumentNullException(nameof(cacheDirectory)); + + return Task.Run(async () => + { + var cacheFilePath = Path.Combine(cacheDirectory, IO.IOUtil.PathToHash(directory)); + + IDatabaseLoadMethod loadMethod = null; + IDatabaseSaveMethod saveMethod = null; + + try + { + switch (mode) + { + case DatabaseLoadMode.Auto: + if (File.Exists(cacheFilePath)) + goto case DatabaseLoadMode.LoadCache; + else + goto case DatabaseLoadMode.Rebuild; + case DatabaseLoadMode.LoadCache: + loadMethod = new SerializedDatabaseLoadMethod(cacheFilePath); + break; + case DatabaseLoadMode.Rebuild: + loadMethod = new CreateFromDirectoryDatabaseLoadMethod(directory, FileIOUtil.OmniFileHandler); + saveMethod = new SerializedDatabaseSaveMethod(cacheFilePath); + break; + case DatabaseLoadMode.Refresh: + loadMethod = new CreateFromDirectoryDatabaseLoadMethod(directory, FileIOUtil.OmniFileHandler, update: true); + saveMethod = new SerializedDatabaseSaveMethod(cacheFilePath); + break; + default: + throw new ArgumentOutOfRangeException(nameof(mode), mode, null); + } + + await connection.LoadAsync(loadMethod, cancellationToken); + + if (saveMethod != null) + { + await connection.SaveAsync(saveMethod, cancellationToken); + } + } + catch (TaskCanceledException) + { + } + finally + { + loadMethod?.Dispose(); + saveMethod?.Dispose(); + } + }, cancellationToken); + } + } +} diff --git a/KoiCatalog.App/GlobalOptions.cs b/KoiCatalog.App/GlobalOptions.cs new file mode 100644 index 0000000..ee04d38 --- /dev/null +++ b/KoiCatalog.App/GlobalOptions.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace KoiCatalog.App +{ + public static class GlobalOptions + { + static GlobalOptions() + { + var args = Environment.GetCommandLineArgs().Skip(1); + + foreach (var option in SplitOptions(args)) + { + switch (option.Name) + { + case null: + case "Directory": + StartupDirectories.AddRange(option.Arguments); + break; + case "NoReport": + ErrorReportingEnabled = false; + break; + default: + Console.WriteLine($"Unknown command-line option '{option.Name}'"); + break; + } + } + } + + private static List