This commit is contained in:
Mike Phares 2022-05-08 12:28:50 -07:00
commit 4a3e24236f
313 changed files with 22395 additions and 0 deletions

243
.editorconfig Normal file
View File

@ -0,0 +1,243 @@
[*.cs]
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
csharp_prefer_braces = false
csharp_prefer_qualified_reference = true:error
csharp_prefer_simple_default_expression = true:warning
csharp_prefer_simple_using_statement = true:warning
csharp_prefer_static_local_function = true:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true
csharp_style_conditional_delegate_call = true
csharp_style_deconstructed_variable_declaration = false
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_constructors = when_on_single_line:warning
csharp_style_expression_bodied_indexers = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:warning
csharp_style_expression_bodied_local_functions = when_on_single_line:warning
csharp_style_expression_bodied_methods = when_on_single_line:warning
csharp_style_expression_bodied_operators = when_on_single_line:warning
csharp_style_expression_bodied_properties = when_on_single_line:warning
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
csharp_style_inlined_variable_declaration = false
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_pattern_local_over_anonymous_function = true:warning
csharp_style_pattern_matching_over_as_with_null_check = true:warning
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_prefer_index_operator = true:warning
csharp_style_prefer_not_pattern = true:warning
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_pattern_matching = true:warning
csharp_style_prefer_range_operator = true:warning
csharp_style_prefer_switch_expression = true:warning
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable:warning
csharp_style_unused_value_expression_statement_preference = discard_variable:warning
csharp_style_var_elsewhere = false:warning
csharp_style_var_for_built_in_types = false:warning
csharp_style_var_when_type_is_apparent = false:warning
csharp_using_directive_placement = outside_namespace
dotnet_code_quality_unused_parameters = all
dotnet_code_quality_unused_parameters = non_public # IDE0060: Remove unused parameter
dotnet_code_quality.CAXXXX.api_surface = private, internal
dotnet_diagnostic.CA1825.severity = warning # CA1823: Avoid zero-length array allocations
dotnet_diagnostic.CA1829.severity = warning # CA1829: Use Length/Count property instead of Count() when available
dotnet_diagnostic.CA1834.severity = warning # CA1834: Consider using 'StringBuilder.Append(char)' when applicable
dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name
dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) System.Version.Equals("1", "2"); Version.Equals("1", "2");
dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary using System.Text;
dotnet_diagnostic.IDE0060.severity = warning # IDE0060: Remove unused parameter
dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.abstract_method_should_be_pascal_case.symbols = abstract_method
dotnet_naming_rule.class_should_be_pascal_case.severity = warning
dotnet_naming_rule.class_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.class_should_be_pascal_case.symbols = class
dotnet_naming_rule.delegate_should_be_pascal_case.severity = warning
dotnet_naming_rule.delegate_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.delegate_should_be_pascal_case.symbols = delegate
dotnet_naming_rule.enum_should_be_pascal_case.severity = warning
dotnet_naming_rule.enum_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.enum_should_be_pascal_case.symbols = enum
dotnet_naming_rule.event_should_be_pascal_case.severity = warning
dotnet_naming_rule.event_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.event_should_be_pascal_case.symbols = event
dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.method_should_be_pascal_case.severity = warning
dotnet_naming_rule.method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.method_should_be_pascal_case.symbols = method
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.private_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.private_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.private_method_should_be_pascal_case.symbols = private_method
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.symbols = private_or_internal_field
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.symbols = private_or_internal_static_field
dotnet_naming_rule.property_should_be_pascal_case.severity = warning
dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.property_should_be_pascal_case.symbols = property
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.symbols = public_or_protected_field
dotnet_naming_rule.static_field_should_be_pascal_case.severity = warning
dotnet_naming_rule.static_field_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.static_field_should_be_pascal_case.symbols = static_field
dotnet_naming_rule.static_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.static_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.static_method_should_be_pascal_case.symbols = static_method
dotnet_naming_rule.struct_should_be_pascal_case.severity = warning
dotnet_naming_rule.struct_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.struct_should_be_pascal_case.symbols = struct
dotnet_naming_rule.types_should_be_pascal_case.severity = warning
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.private_of_internal_field.capitalization = pascal_case
dotnet_naming_style.private_of_internal_field.required_prefix = _
dotnet_naming_style.private_of_internal_field.required_suffix =
dotnet_naming_style.private_of_internal_field.word_separator =
dotnet_naming_symbols.abstract_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.abstract_method.applicable_kinds = method
dotnet_naming_symbols.abstract_method.required_modifiers = abstract
dotnet_naming_symbols.class.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.class.applicable_kinds = class
dotnet_naming_symbols.class.required_modifiers =
dotnet_naming_symbols.delegate.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.delegate.applicable_kinds = delegate
dotnet_naming_symbols.delegate.required_modifiers =
dotnet_naming_symbols.enum.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.enum.applicable_kinds = enum
dotnet_naming_symbols.enum.required_modifiers =
dotnet_naming_symbols.event.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.event.applicable_kinds = event
dotnet_naming_symbols.event.required_modifiers =
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.method.applicable_accessibilities = public
dotnet_naming_symbols.method.applicable_kinds = method
dotnet_naming_symbols.method.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.private_method.applicable_accessibilities = private
dotnet_naming_symbols.private_method.applicable_kinds = method
dotnet_naming_symbols.private_method.required_modifiers =
dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_field.required_modifiers =
dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = static
dotnet_naming_symbols.property.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.property.applicable_kinds = property
dotnet_naming_symbols.property.required_modifiers =
dotnet_naming_symbols.public_or_protected_field.applicable_accessibilities = public, protected
dotnet_naming_symbols.public_or_protected_field.applicable_kinds = field
dotnet_naming_symbols.public_or_protected_field.required_modifiers =
dotnet_naming_symbols.static_field.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.static_field.applicable_kinds = field
dotnet_naming_symbols.static_field.required_modifiers = static
dotnet_naming_symbols.static_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.static_method.applicable_kinds = method
dotnet_naming_symbols.static_method.required_modifiers = static
dotnet_naming_symbols.struct.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.struct.applicable_kinds = struct
dotnet_naming_symbols.struct.required_modifiers =
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.required_modifiers =
dotnet_remove_unnecessary_suppression_exclusions = 0
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
dotnet_style_allow_multiple_blank_lines_experimental = false:warning
dotnet_style_allow_statement_immediately_after_block_experimental = true
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true:warning
dotnet_style_object_initializer = true:warning
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = false
dotnet_style_prefer_conditional_expression_over_return = false
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_simplified_boolean_expressions = true:warning
dotnet_style_prefer_simplified_interpolation = true
dotnet_style_qualification_for_event = false:error
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false:error
dotnet_style_qualification_for_property = false:error
dotnet_style_readonly_field = true:warning
dotnet_style_require_accessibility_modifiers = for_non_interface_members
end_of_line = crlf
file_header_template = unset
indent_size = 4
indent_style = space
insert_final_newline = false
root = true
tab_width = 4
# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1822
# https://github.com/dotnet/aspnetcore/blob/main/.editorconfig
# https://github.com/dotnet/project-system/blob/main/.editorconfig

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

461
.gitignore vendored Normal file
View File

@ -0,0 +1,461 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# JetBrains Rider
.idea/
*.sln.iml
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
#VSCode Settings => mklink /J "VSCode Settings" "C:\Users\phares\AppData\Roaming\Code\User"
globalStorage/
*workspaceStorage/
#Auto Gen Code from Code-Generator
*.gen

10
.txt Normal file
View File

@ -0,0 +1,10 @@
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Compare" "L:\Git\View-by-Distance\Compare"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Date-Group" "L:\Git\View-by-Distance\Date-Group"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Instance" "L:\Git\View-by-Distance\Instance"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Metadata" "L:\Git\View-by-Distance\Metadata"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Not-Copy-Copy" "L:\Git\View-by-Distance\Not-Copy-Copy"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\PrepareForOld" "L:\Git\View-by-Distance\PrepareForOld"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Property" "L:\Git\View-by-Distance\Property"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Property-Compare" "L:\Git\View-by-Distance\Property-Compare"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Resize" "L:\Git\View-by-Distance\Resize"
mklink /J "L:\Git\View-by-Distance-MKLink-Console\Shared" "L:\Git\View-by-Distance\Shared"

28
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,28 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"programC": "${workspaceFolder}/Compare/bin/Debug/net6.0/win-x64/Compare.dll",
"program": "${workspaceFolder}/Date-Group/bin/Debug/net6.0/win-x64/Date-Group.dll",
"programI": "${workspaceFolder}/Instance/bin/Debug/net6.0/win-x64/Instance.dll",
"programN": "${workspaceFolder}/Not-Copy-Copy/bin/Debug/net6.0/win-x64/Not-Copy-Copy.dll",
"programP": "${workspaceFolder}/PrepareForOld/bin/Debug/net6.0/win-x64/PrepareForOld.dll",
"args": [],
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "externalTerminal",
"stopAtEntry": false
}
]
}

11
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"cSpell.words": [
"Barrick",
"Beichler",
"Bohdi",
"Dlib",
"Phares",
"Serilog",
"Vericruz"
]
}

17
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Console.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

1
Compare/.vscode/format-report.json vendored Normal file
View File

@ -0,0 +1 @@
[]

32
Compare/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net6.0/win-x64/Compare.dll",
"args": [
"s"
],
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "externalTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processName": "Compare"
}
]
}

14
Compare/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"cSpell.words": [
"Barrick",
"bcdfghjklmnpqrstvwxyz",
"Beichler",
"Bohdi",
"Dlib",
"exif",
"nosj",
"Phares",
"Serilog",
"Vericruz"
]
}

42
Compare/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Compare.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Compare.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/Compare.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

906
Compare/Compare.cs Normal file
View File

@ -0,0 +1,906 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Globalization;
using System.Text.Json;
using View_by_Distance.Compare.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods;
using WindowsShortcutFactory;
namespace View_by_Distance.Compare;
public class Compare
{
private readonly Serilog.ILogger? _Log;
private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions;
private readonly string[] _VerifyToSeason;
private readonly IsEnvironment _IsEnvironment;
private readonly Models.Configuration _Configuration;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly List<(string Find, string Replace)> _RenameFindReplace;
private readonly List<(string Find, string Replace)> _RenameBFindReplace;
private readonly List<(string Find, string Replace)> _RenameCFindReplace;
private readonly List<(string Find, string Replace)> _SpellingFindReplace;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs;
public Compare(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{
if (isSilent)
{ }
if (console is null)
{ }
string renameFrom;
string renameTo;
string[] segments;
_AppSettings = appSettings;
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!");
_RenameFindReplace = new();
_RenameBFindReplace = new();
_RenameCFindReplace = new();
_SpellingFindReplace = new();
_IsEnvironment = isEnvironment;
_Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<Compare>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>();
string message;
string searchPattern = "*";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory);
Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration);
if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!");
if (propertyConfiguration.PopulatePropertyId is null)
throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!");
foreach (string spelling in configuration.Spelling)
{
segments = spelling.Split('|');
if (segments.Length != 2)
throw new Exception("Change configuration");
if (segments[1].Contains(segments[0]))
throw new Exception($"Change configuration {segments[1]}.Contains({segments[0]})!");
_SpellingFindReplace.Add(new(segments[0], segments[1]));
}
foreach (string rename in configuration.Rename)
{
segments = rename.Split('|');
if (segments.Length is not 2 and not 4)
throw new Exception("Change configuration");
renameFrom = Path.Combine(propertyConfiguration.RootDirectory, segments[0]);
renameTo = Path.Combine(propertyConfiguration.RootDirectory, segments[1]);
if (renameTo.Contains(renameFrom))
throw new Exception($"Change configuration {renameTo}.Contains({renameFrom})!");
_RenameFindReplace.Add(new(renameFrom, renameTo));
if (segments.Length == 4)
{
renameFrom = Path.Combine(propertyConfiguration.RootDirectory, segments[2]);
renameTo = Path.Combine(propertyConfiguration.RootDirectory, segments[3]);
if (renameTo.Contains(renameFrom))
throw new Exception($"Change configuration {renameTo}.Contains({renameFrom})!");
_RenameFindReplace.Add(new(renameFrom, renameTo));
}
}
foreach (string rename in configuration.RenameB)
{
segments = rename.Split('|');
if (segments.Length is not 2)
throw new Exception("Change configuration");
renameFrom = Path.GetFullPath(string.Concat(propertyConfiguration.RootDirectory, segments[0]));
renameTo = Path.GetFullPath(string.Concat(propertyConfiguration.RootDirectory, segments[1]));
if (renameTo.Contains(renameFrom))
throw new Exception($"Change configuration {renameTo}.Contains({renameFrom})!");
_RenameBFindReplace.Add(new(renameFrom, renameTo));
}
for (int i = 0; i < configuration.RenameC.Length; i++)
{
renameFrom = Path.GetFullPath(string.Concat(propertyConfiguration.RootDirectory, configuration.RenameC[i]));
renameTo = Path.Combine(propertyConfiguration.RootDirectory, GetRename(configuration.RenameC[i]));
if (renameTo.Contains(renameFrom))
throw new Exception("Change configuration!");
_RenameCFindReplace.Add(new(renameFrom, renameTo));
}
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
_Log.Information($"{nameof(Property.Models.Stateless.A_Property.GetGroupCollection)} has finished");
_VerifyToSeason = propertyConfiguration.VerifyToSeason.Select(l => Path.Combine(propertyConfiguration.RootDirectory, l)).ToArray();
List<string> missingVerifyToSeasonCollection = GetMissingVerifyToSeasonCollection(topDirectories, groupCollection);
if (missingVerifyToSeasonCollection.Any())
throw new Exception($"Update configuration with the following {Environment.NewLine} {string.Join(Environment.NewLine, missingVerifyToSeasonCollection)}");
if (PossiblyRename(topDirectories, groupCollection))
{
topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
}
_Log.Information($"{nameof(PossiblyRename)} has finished");
if (PossiblyRenameB(topDirectories, groupCollection))
{
topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
}
_Log.Information($"{nameof(PossiblyRenameB)} has finished");
if (PossiblyRenameC(topDirectories, groupCollection))
{
topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
}
_Log.Information($"{nameof(PossiblyRenameC)} has finished");
if (PossiblyCorrect(topDirectories, groupCollection))
{
topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
}
_Log.Information($"{nameof(PossiblyCorrect)} has finished");
string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories);
foreach (string dbFile in dbFiles)
File.Delete(dbFile);
_Log.Information("deleting *.db files has finished");
if (dbFiles.Any())
{
topDirectories.Clear();
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
}
PropertyLogic propertyLogic = GetPropertyLogic();
if (_IsEnvironment.Development && propertyConfiguration.PopulatePropertyId.Value && !propertyLogic.IndicesFromOld.Any())
throw new Exception("Copy keyValuePairs-####.json file");
_Exceptions.AddRange(propertyLogic.DoWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true));
message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message);
if (_Exceptions.Count != 0)
throw new Exception(message);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.DoWork));
if (!isSilent)
{
_Log.Information("First pass completed");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to continue or close console if compare not needed");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "{}");
string aPropertyContentCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "[()]");
if (!isSilent)
{
if (Directory.Exists(aPropertySingletonDirectory))
{
ConsoleKey? consoleKey = null;
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Execute {nameof(ChangeExtensionFromDeleteToJson)} \"Y(es)\" or \"N(o)\"?");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
break;
}
_Log.Information(". . .");
if (consoleKey == ConsoleKey.Y)
ChangeExtensionFromDeleteToJson(aPropertySingletonDirectory);
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Execute {nameof(Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull)} \"Y(es)\" or \"N(o)\"?");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
break;
}
_Log.Information(". . .");
if (consoleKey == ConsoleKey.Y)
{
Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull(propertyConfiguration.RootDirectory, aPropertySingletonDirectory, onlyJson: false);
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Execute {nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories)} \"Y(es)\" or \"N(o)\"?");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
break;
}
_Log.Information(". . .");
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(aPropertySingletonDirectory);
}
}
}
topDirectories.Clear();
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
_Exceptions.AddRange(propertyLogic.DoWork(propertyConfiguration, topDirectories, groupCollection, firstPass: false));
message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message);
if (_Exceptions.Count != 0)
throw new Exception(message);
if (!isSilent)
{
_Log.Information("Second pass completed");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to continue or close console if compare not needed");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
ThirdPassToMove(propertyLogic, propertyConfiguration, aPropertyContentCollectionDirectory, topDirectories, groupCollection);
if (!isSilent)
{
_Log.Information("Third pass completed");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to continue or close console if compare not needed");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
FourthPassCreateWindowsShortcuts(propertyLogic, propertyConfiguration, topDirectories, groupCollection, saveToCollection: false, keepAll: false);
if (!isSilent)
{
_Log.Information("Fourth pass completed");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to continue or close console if compare not needed");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
SaveDiffFilesOrSaveLogAndMoveFiles(propertyConfiguration);
string currentYearDirectory = Path.Combine(propertyConfiguration.RootDirectory, $". {DateTime.Now:yyyy}");
if (!Directory.Exists(currentYearDirectory))
_ = Directory.CreateDirectory(currentYearDirectory);
_Configuration = configuration;
}
private string GetRename(string renameA)
{
string result;
int season;
DateTime dateTime;
string seasonName;
string[] pathSegments;
string[] directorySegments;
string corrected = renameA[1..];
if ((from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any())
{
foreach ((string find, string replace) in _SpellingFindReplace)
corrected = corrected.Replace(find, replace);
}
corrected = corrected.Replace("Back to the hospital", "September 2007").Replace("Birthday", "September 2007").Replace("Aug Sept 09", "Sept 09");
pathSegments = corrected.Split('/');
directorySegments = pathSegments[0].Split(' ');
bool hasZzz = directorySegments.Contains("zzz");
if (hasZzz)
{
corrected = corrected.Replace("zzz ", string.Empty);
pathSegments = corrected.Split('/');
directorySegments = pathSegments[0].Split(' ');
}
if (pathSegments[^1].Contains('-'))
{
directorySegments = pathSegments[^1].Split(' ');
if (!DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
throw new Exception("l");
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else if (pathSegments.Length == 1)
{
directorySegments = pathSegments[^1].Split(' ');
if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else
throw new Exception("1");
}
else if (pathSegments.Length == 2)
{
directorySegments = pathSegments[^1].Split(' ');
if (directorySegments.Length == 1)
{
directorySegments = pathSegments[0].Split(' ');
if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else
throw new Exception("2,1");
}
else if (directorySegments.Length == 4)
{
directorySegments = pathSegments[0].Split(' ');
if (DateTime.TryParseExact(directorySegments[^1], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else
throw new Exception("2,4");
}
else if (directorySegments.Length == 2)
{
if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else if (DateTime.TryParseExact(string.Concat(directorySegments[0][..3], ' ', directorySegments[1]), "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(2)), "MMMM yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else
throw new Exception("2,2");
}
else if (directorySegments.Length == 3)
{
if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM dd yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM d yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else
throw new Exception("2,3");
}
else
throw new Exception("2");
}
else if (pathSegments.Length == 3)
{
directorySegments = pathSegments[^1].Split(' ');
if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM dd yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else if (DateTime.TryParseExact(string.Join(' ', directorySegments.Take(3)), "MMMM d yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(dateTime.DayOfYear);
result = string.Concat($"={dateTime:yyyy}.{season} {seasonName} ", string.Join(' ', pathSegments[0].Split(' ').Take(2)));
}
else
throw new Exception("3");
}
else
throw new Exception("e");
if (hasZzz)
result = string.Concat("zzz ", result);
return result;
}
private static void Verify(Models.Configuration configuration)
{
if (configuration.Spelling is null || !configuration.Spelling.Any())
throw new Exception($"{nameof(configuration.Spelling)} should have at least one!");
}
private long LogDelta(long ticks, string methodName)
{
long result;
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds;
_Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)");
result = DateTime.Now.Ticks;
return result;
}
private PropertyLogic GetPropertyLogic()
{
PropertyLogic result;
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _VerifyToSeason);
string fromPerpareForOld = "34720-637858334555170379.tsv";
string fromPerpareForOldFile = Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, fromPerpareForOld);
if (File.Exists(fromPerpareForOldFile))
{
string[] lines;
string[] columns;
List<string> debug = new();
long ticks = DateTime.Now.Ticks;
lines = File.ReadAllLines(fromPerpareForOldFile);
string resultsDirectory = $"{_Configuration.PropertyConfiguration.RootDirectory} - Results";
int[]? zeros = (from l in result.IndicesFromNew where l.Value.Any() select l.Value[0]).ToArray();
lines = (from l in result.IndicesFromNew select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray();
if (!Directory.Exists(resultsDirectory))
_ = Directory.CreateDirectory(resultsDirectory);
File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}.tsv"), lines);
string json = JsonSerializer.Serialize(result.IndicesFromNew, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Combine(resultsDirectory, $"{ticks}.json"), json);
foreach (string line in lines)
{
columns = line.Split('\t');
// select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}"
if (columns.Length != 7)
continue;
if (!int.TryParse(columns[1], out int propertyId))
continue;
if (!zeros.Contains(propertyId))
debug.Add(line);
else
debug.Add(propertyId.ToString());
}
File.WriteAllLines(Path.Combine(resultsDirectory, $"{ticks}-{fromPerpareForOld}"), debug);
}
return result;
}
private void SaveDiffFilesOrSaveLogAndMoveFiles(Property.Models.Configuration configuration)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
_Log.Information(aPropertySingletonDirectory);
_Log.Information("to");
_Log.Information(_Configuration.DiffPropertyDirectory);
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to continue or close console if compare not needed");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
int loadLessThan = 7;
string diffRootDirectory;
ConsoleKey? consoleKey = null;
List<PropertyCompare.Models.PropertyCompare>? duplicates = null;
PropertyCompare.Models.PropertyCompare[] diffPropertyCompareCollection;
if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory))
diffRootDirectory = string.Empty;
else
{
if (!_Configuration.DiffPropertyDirectory.EndsWith("{}"))
throw new Exception("Invalid directory should end with {}!");
diffRootDirectory = Property.Models.Stateless.A_Property.GetDiffRootDirectory(_Configuration.DiffPropertyDirectory);
}
PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory);
if (string.IsNullOrEmpty(_Configuration.DiffPropertyDirectory) || !Directory.Exists(_Configuration.DiffPropertyDirectory))
diffPropertyCompareCollection = Array.Empty<PropertyCompare.Models.PropertyCompare>();
else
{
diffPropertyCompareCollection = propertyCompareLogic.Get(_Configuration.DiffPropertyDirectory, loadLessThan, duplicates, deleteExtension: false);
if (!diffPropertyCompareCollection.Any())
throw new Exception("Invalid directory!");
}
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "[{}]");
PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan, duplicates, deleteExtension: false);
{
long ticks = DateTime.Now.Ticks;
string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray();
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);
}
for (int x = 0; x < int.MaxValue; x++)
{
_Log.Information($"Press \"D\" key to {nameof(PropertyCompare.Models.PropertyCompareLogic.SaveDiffFiles)}");
_Log.Information($"Press \"M\" key to {nameof(PropertyCompare.Models.PropertyCompareLogic.SaveLogAndMoveFiles)}");
_Log.Information("Press \"End\" key when ready to skip");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.D or ConsoleKey.M or ConsoleKey.End)
break;
}
_Log.Information(". . .");
if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.D)
propertyCompareLogic.SaveDiffFiles(aPropertyCollectionDirectory, loadLessThan, propertyCompareCollection, diffPropertyCompareCollection);
else if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.M)
{
for (int x = 0; x < int.MaxValue; x++)
{
_Log.Information($"Press \"0 - {loadLessThan}\" key when ready to continue");
_Log.Information("Press \"End\" key when ready to skip");
consoleKey = Console.ReadKey().Key;
if (consoleKey.Value is ConsoleKey.D0 or ConsoleKey.D1 or ConsoleKey.D2 or ConsoleKey.D3 or ConsoleKey.D4 or ConsoleKey.D5 or ConsoleKey.D6 or ConsoleKey.End)
break;
}
_Log.Information(". . .");
int i = int.Parse(consoleKey.Value.ToString()[1..]);
propertyCompareLogic.SaveLogAndMoveFiles(aPropertyCollectionDirectory, loadLessThan, propertyCompareCollection, diffPropertyCompareCollection, i);
}
}
private void ChangeExtensionFromDeleteToJson(string aPropertySingletonDirectory)
{
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
string searchPattern = "*.delete";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(aPropertySingletonDirectory, searchPattern, topDirectories);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection)
{
if (!topDirectories.Any())
continue;
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
File.Move(sourceDirectoryFile, Path.ChangeExtension(sourceDirectoryFile, ".json"));
}
}
private bool PossiblyRename(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection)
{
bool result = false;
string replaceFile;
string replaceDirectory;
int remainingDirectories = 0;
IEnumerable<(string Find, string Replace)>? found;
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection)
{
if (!topDirectories.Any())
continue;
found = from l in _RenameFindReplace where sourceDirectory == l.Find select l;
if (!found.Any())
continue;
if (!result)
result = true;
replaceDirectory = found.First().Replace;
if (!Directory.Exists(replaceDirectory))
Directory.Move(sourceDirectory, replaceDirectory);
else
{
if (Directory.EnumerateDirectories(sourceDirectory).Any())
remainingDirectories += 1;
else
{
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
{
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
if (File.Exists(replaceFile))
{
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
}
if (File.Exists(replaceFile))
continue;
File.Move(sourceDirectoryFile, replaceFile);
}
}
}
}
return result;
}
private bool PossiblyRenameB(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection)
{
bool result = false;
string replaceFile;
string replaceDirectory;
IEnumerable<(string Find, string Replace)>? found;
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection)
{
if (!topDirectories.Any())
continue;
found = from l in _RenameBFindReplace where sourceDirectory == l.Find select l;
if (!found.Any())
continue;
if (!result)
result = true;
replaceDirectory = found.First().Replace;
if (!Directory.Exists(replaceDirectory))
_ = Directory.CreateDirectory(replaceDirectory);
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
{
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
if (File.Exists(replaceFile))
{
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
}
if (File.Exists(replaceFile))
continue;
File.Move(sourceDirectoryFile, replaceFile);
}
}
return result;
}
private bool PossiblyRenameC(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection)
{
bool result = false;
string replaceFile;
string replaceDirectory;
IEnumerable<(string Find, string Replace)>? found;
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection)
{
if (!topDirectories.Any())
continue;
found = from l in _RenameCFindReplace where sourceDirectory == l.Find select l;
if (!found.Any())
continue;
if (!result)
result = true;
replaceDirectory = found.First().Replace;
if (!Directory.Exists(replaceDirectory))
_ = Directory.CreateDirectory(replaceDirectory);
foreach (string sourceDirectoryFile in sourceDirectoryFiles)
{
replaceFile = Path.Combine(replaceDirectory, Path.GetFileName(sourceDirectoryFile));
if (File.Exists(replaceFile))
{
if (replaceFile.EndsWith(".jpg", ignoreCase: true, CultureInfo.CurrentCulture))
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpeg"));
else if (replaceFile.EndsWith(".jpeg", ignoreCase: true, CultureInfo.CurrentCulture))
replaceFile = Path.Combine(replaceDirectory, Path.ChangeExtension(sourceDirectoryFile, ".jpg"));
}
if (File.Exists(replaceFile))
continue;
File.Move(sourceDirectoryFile, replaceFile);
}
}
return result;
}
private bool PossiblyCorrect(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection)
{
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
bool result = false;
string corrected;
string correctedMoveTo;
string? correctedDirectory;
string filteredSourceDirectoryFile;
string[] filteredSourceDirectoryFiles;
(string Find, string Replace) findReplace;
IEnumerable<(string Find, string Replace)>? found;
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection)
{
if (!topDirectories.Any())
continue;
filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where !_Configuration.PropertyConfiguration.IgnoreExtensions.Contains(Path.GetExtension(l)) select l).ToArray();
if (!filteredSourceDirectoryFiles.Any())
continue;
for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++)
{
found = null;
for (int z = 0; z < int.MaxValue; z++)
{
filteredSourceDirectoryFile = filteredSourceDirectoryFiles[i];
found = from l in _SpellingFindReplace where filteredSourceDirectoryFile.Contains(l.Find) select l;
if (!found.Any())
break;
findReplace = found.First();
corrected = filteredSourceDirectoryFile.Replace(findReplace.Find, findReplace.Replace);
correctedDirectory = Path.GetDirectoryName(corrected);
if (string.IsNullOrEmpty(correctedDirectory))
break;
correctedMoveTo = Path.Combine(correctedDirectory, Path.GetFileName(corrected));
if (File.Exists(correctedMoveTo))
break;
if (!Directory.Exists(correctedDirectory))
_ = Directory.CreateDirectory(correctedDirectory);
if (!result)
result = true;
File.Move(filteredSourceDirectoryFile, correctedMoveTo);
filteredSourceDirectoryFiles[i] = corrected;
}
}
}
return result;
}
private List<string> GetMissingVerifyToSeasonCollection(List<string> _, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection)
{
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
List<string> results = new();
string check;
foreach ((int _, string sourceDirectory, string[] _, int _) in groupCollection)
{
if (sourceDirectory == _Configuration.PropertyConfiguration.RootDirectory)
continue;
check = sourceDirectory[(_Configuration.PropertyConfiguration.RootDirectory.Length + 1)..];
if (check[0] is '=' || check.StartsWith("zzz ="))
{
if (!_Configuration.PropertyConfiguration.VerifyToSeason.Contains(check))
results.Add(check);
}
}
return results;
}
private void CreateWindowsShortcuts((long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] collection, bool keepAll)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
int z = 0;
string fileName;
WindowsShortcut windowsShortcut;
foreach ((long ticks, string filteredSourceDirectoryFile, string propertyDirectory, int propertyId) in collection)
{
z += 1;
if (z % 1000 == 0)
_Log.Debug($"{z}) Loop {propertyDirectory}");
if (!keepAll)
{
fileName = Path.Combine(propertyDirectory, $"{propertyId}.lnk");
if (File.Exists(fileName))
continue;
}
else
{
fileName = string.Empty;
for (short c = 65; c < short.MaxValue; c++)
{
if (c > 95)
break;
fileName = Path.Combine(propertyDirectory, $"{(char)c}", $"{propertyId}.lnk");
if (File.Exists(fileName))
continue;
}
}
if (string.IsNullOrEmpty(fileName))
continue;
windowsShortcut = new() { Path = filteredSourceDirectoryFile };
windowsShortcut.Save(fileName);
windowsShortcut.Dispose();
}
}
private void ThirdPassToMove(PropertyLogic propertyLogic, Property.Models.Configuration configuration, string aPropertyContentCollectionDirectory, List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
int stay = 0;
string fileName;
string id = " - Id";
A_Property? property;
string? directoryName;
ConsoleKey? consoleKey = null;
DateTime dateTime = DateTime.Now;
string filteredSourceDirectoryFile;
List<string> fileStayCollection = new();
List<string> fileMoveCollection = new();
List<string> distinctDirectories = new();
List<KeyValuePair<int, int[]>> valueCollection = new();
List<Group> groupResultsCollection = propertyLogic.GetParallelWork(configuration, topDirectories, groupCollection, firstPass: false, filterOnFirstPass: false);
foreach (Group group in groupResultsCollection)
{
for (int i = 0; i < group.PropertyCollection.Length; i++)
{
property = group.PropertyCollection[i];
if (property?.Id is null)
continue;
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
valueCollection.Add(new(property.Id.Value, property.Indices));
if (!propertyLogic.IndicesFromNew.ContainsKey(property.Id.Value))
stay += 1;
else if (!fileMoveCollection.Contains(filteredSourceDirectoryFile))
fileMoveCollection.Add(filteredSourceDirectoryFile);
}
}
string[] lines = (from l in valueCollection select string.Concat(l.Key, '\t', string.Join('\t', l.Value))).ToArray();
if (!Directory.Exists(aPropertyContentCollectionDirectory))
_ = Directory.CreateDirectory(aPropertyContentCollectionDirectory);
File.WriteAllLines(Path.Combine(aPropertyContentCollectionDirectory, $"{dateTime.Ticks}.tsv"), lines);
string json = JsonSerializer.Serialize(valueCollection, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Combine(aPropertyContentCollectionDirectory, $"{dateTime.Ticks}.json"), json);
foreach (string fileMove in fileMoveCollection)
{
directoryName = Path.GetDirectoryName(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, id, fileMove[_Configuration.PropertyConfiguration.RootDirectory.Length..]));
if (string.IsNullOrEmpty(directoryName))
continue;
if (!distinctDirectories.Contains(directoryName))
distinctDirectories.Add(directoryName);
}
foreach (string distinctDirectory in distinctDirectories)
{
if (!Directory.Exists(distinctDirectory))
_ = Directory.CreateDirectory(distinctDirectory);
}
_Log.Information($"{stay} file(s) are staying and {fileMoveCollection.Count} file(s) will be moved");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Press \"M\" key to {nameof(File.Move)}");
_Log.Information("Press \"End\" key when ready to skip or close console if compare not needed");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.M or ConsoleKey.End)
break;
}
_Log.Information(". . .");
if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.M)
{
foreach (string fileMove in fileMoveCollection)
{
fileName = string.Concat(_Configuration.PropertyConfiguration.RootDirectory, id, fileMove[_Configuration.PropertyConfiguration.RootDirectory.Length..]);
File.Move(fileMove, fileName);
}
for (int i = 1; i < 4; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory);
}
}
private void FourthPassCreateWindowsShortcuts(PropertyLogic propertyLogic, Property.Models.Configuration configuration, List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection, bool saveToCollection, bool keepAll)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
int stay = 0;
A_Property? property;
ConsoleKey? consoleKey = null;
string filteredSourceDirectoryFile;
List<string> fileMoveCollection = new();
List<KeyValuePair<int, int[]>> valueCollection = new();
(long Ticks, string FilteredSourceDirectoryFile, string PropertyDirectory, int PropertyId)[] collection;
List<Group> groupResultsCollection = propertyLogic.GetParallelWork(configuration, topDirectories, groupCollection, firstPass: false, filterOnFirstPass: false);
foreach (Group group in groupResultsCollection)
{
for (int i = 0; i < group.PropertyCollection.Length; i++)
{
property = group.PropertyCollection[i];
if (property?.Id is null)
continue;
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
valueCollection.Add(new(property.Id.Value, property.Indices));
if (!propertyLogic.IndicesFromNew.ContainsKey(property.Id.Value))
stay += 1;
else
fileMoveCollection.Add(filteredSourceDirectoryFile);
}
}
collection = propertyLogic.GetPropertyIds(configuration, groupResultsCollection, saveToCollection);
_Log.Information($"{stay} file(s) are staying and {fileMoveCollection.Count} file(s) will be moved");
for (int x = 0; x < int.MaxValue; x++)
{
_Log.Information($"Press \"S\" key to {nameof(CreateWindowsShortcuts)}");
_Log.Information("Press \"End\" key when ready to skip or close console if compare not needed");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.M or ConsoleKey.End)
break;
}
_Log.Information(". . .");
if (consoleKey.HasValue && consoleKey.Value == ConsoleKey.S)
CreateWindowsShortcuts(collection, keepAll);
}
}

67
Compare/Compare.csproj Normal file
View File

@ -0,0 +1,67 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Compare</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
<PackageReference Include="WindowsShortcutFactory" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,35 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Compare.Models;
public class AppSettings
{
protected string _Company;
protected string _WorkingDirectoryName;
protected int? _MaxDegreeOfParallelism;
public string Company => _Company;
public string WorkingDirectoryName => _WorkingDirectoryName;
public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism;
// public AppSettings()
// {
// }
[JsonConstructor]
public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism)
{
_Company = company;
_WorkingDirectoryName = workingDirectoryName;
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Compare.Models.Binder;
public class AppSettings
{
[Display(Name = "Company"), Required] public string Company { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
[Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; }
public AppSettings()
{
Company = string.Empty;
WorkingDirectoryName = string.Empty;
MaxDegreeOfParallelism = -1;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,30 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Compare.Models.Binder;
public class Configuration
{
[Display(Name = "Diff Property Directory"), Required] public string DiffPropertyDirectory { get; set; }
[Display(Name = "Property Configuration"), Required] public Property.Models.Configuration? PropertyConfiguration { get; set; }
[Display(Name = "Rename"), Required] public string[] Rename { get; set; }
[Display(Name = "Rename B"), Required] public string[] RenameB { get; set; }
[Display(Name = "Rename C"), Required] public string[] RenameC { get; set; }
[Display(Name = "Spelling"), Required] public string[] Spelling { get; set; }
public Configuration()
{
DiffPropertyDirectory = string.Empty;
Rename = Array.Empty<string>();
RenameB = Array.Empty<string>();
RenameC = Array.Empty<string>();
Spelling = Array.Empty<string>();
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,43 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Compare.Models;
public class Configuration
{
protected readonly string _DiffPropertyDirectory;
protected Property.Models.Configuration? _PropertyConfiguration;
protected readonly string[] _Rename;
protected readonly string[] _RenameB;
protected readonly string[] _RenameC;
protected readonly string[] _Spelling;
public string DiffPropertyDirectory => _DiffPropertyDirectory;
public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration;
public string[] Rename => _Rename;
public string[] RenameB => _RenameB;
public string[] RenameC => _RenameC;
public string[] Spelling => _Spelling;
[JsonConstructor]
public Configuration(string diffPropertyDirectory, Property.Models.Configuration? propertyConfiguration, string[] rename, string[] renameB, string[] renameC, string[] spelling)
{
_DiffPropertyDirectory = diffPropertyDirectory;
_PropertyConfiguration = propertyConfiguration;
_Rename = rename;
_RenameB = renameB;
_RenameC = renameC;
_Spelling = spelling;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration;
public void Update() => _PropertyConfiguration?.Update();
}

View File

@ -0,0 +1,40 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace View_by_Distance.Compare.Models.Stateless;
public abstract class AppSettings
{
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
namespace View_by_Distance.Compare.Models.Stateless;
public abstract class Configuration
{
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory, Property.Models.Configuration propertyConfiguration)
{
Models.Configuration? result;
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Binder.Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
Binder.Configuration configuration = configurationSection.Get<Binder.Configuration>();
string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.Configuration>(json);
if (result is null)
throw new Exception(json);
string jsonThis = result.ToString();
result.Set(propertyConfiguration);
result.Update();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Compare.Models.Stateless;
public static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

71
Compare/Program.cs Normal file
View File

@ -0,0 +1,71 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.Compare.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Compare;
public class Program
{
public static void Secondary(List<string> args)
{
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
IConfigurationRoot configurationRoot = configurationBuilder.Build();
AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot);
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception("MaxDegreeOfParallelism must be set!");
if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount)
throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!");
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>();
int silentIndex = args.IndexOf("s");
if (silentIndex > -1)
args.RemoveAt(silentIndex);
try
{
if (args is null)
throw new Exception("args is null!");
Shared.Models.Console console = new();
Compare _ = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console);
}
catch (Exception ex)
{
log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace));
}
finally
{
Log.CloseAndFlush();
}
if (silentIndex > -1)
log.Debug("Done. Bye");
else
{
log.Debug("Done. Press 'Enter' to end");
_ = Console.ReadLine();
}
}
public static void Main(string[] args)
{
if (args is not null)
Secondary(args.ToList());
else
Secondary(new List<string>());
}
}

File diff suppressed because it is too large Load Diff

1609
Compare/appsettings.json Normal file

File diff suppressed because it is too large Load Diff

1
Date-Group/.vscode/format-report.json vendored Normal file
View File

@ -0,0 +1 @@
[]

30
Date-Group/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net6.0/win-x64/Date-Group.dll",
"args": [],
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "externalTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processName": "Date-Group"
}
]
}

11
Date-Group/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"cSpell.words": [
"Barrick",
"Beichler",
"Bohdi",
"Dlib",
"Phares",
"Serilog",
"Vericruz"
]
}

42
Date-Group/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Date-Group.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Date-Group.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/Date-Group.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@ -0,0 +1,63 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Date.Group</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

426
Date-Group/DateGroup.cs Normal file
View File

@ -0,0 +1,426 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Globalization;
using System.Text;
using View_by_Distance.Date.Group.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Date.Group;
public class DateGroup
{
private readonly Serilog.ILogger? _Log;
private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment;
private readonly Models.Configuration _Configuration;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs;
public DateGroup(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{
if (isSilent)
{ }
if (args is null)
{ }
if (console is null)
{ }
_AppSettings = appSettings;
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!");
_IsEnvironment = isEnvironment;
_Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<DateGroup>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory);
Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration);
_Configuration = configuration;
if (configuration.ByHash is null)
throw new Exception($"{nameof(configuration.ByHash)} is null!");
if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!");
if (propertyConfiguration.PopulatePropertyId is null)
throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!");
if (!_IsEnvironment.Development)
throw new Exception("This program only allows development environments!");
string searchPattern = "*";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
PropertyLogic propertyLogic = GetPropertyLogic();
string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories);
foreach (string dbFile in dbFiles)
File.Delete(dbFile);
for (int i = 1; i < 10; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
List<Property.Models.Group> groupResultsCollection = new();
if (!propertyConfiguration.PopulatePropertyId.Value || !configuration.ByHash.Value)
groupResultsCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true);
else
{
_Exceptions.AddRange(propertyLogic.DoWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true));
string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message);
if (_Exceptions.Count != 0)
throw new Exception(message);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.DoWork));
topDirectories.Clear();
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
groupResultsCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: false, filterOnFirstPass: true);
}
MoveFiles(topDirectories, groupResultsCollection);
}
private static void Verify(Models.Configuration configuration)
{
if (configuration.ByDay is null)
throw new Exception($"{nameof(configuration.ByDay)} is null!");
if (configuration.ByHash is null)
throw new Exception($"{nameof(configuration.ByHash)} is null!");
if (configuration.BySeason is null)
throw new Exception($"{nameof(configuration.BySeason)} is null!");
if (configuration.ByWeek is null)
throw new Exception($"{nameof(configuration.ByWeek)} is null!");
if (!configuration.ByDay.Value && !configuration.ByWeek.Value && !configuration.BySeason.Value && !configuration.ByHash.Value)
throw new Exception("Change configuration!");
if (configuration.KeepFullPath is null)
throw new Exception($"{nameof(configuration.KeepFullPath)} is null!");
if (configuration?.PropertyConfiguration?.PopulatePropertyId is null)
throw new Exception($"{nameof(configuration.PropertyConfiguration.PopulatePropertyId)} must be set!");
if (configuration.PropertyConfiguration.PopulatePropertyId.Value && !configuration.ByHash.Value)
throw new Exception("Change configuration!");
if (!configuration.PropertyConfiguration.PopulatePropertyId.Value && configuration.ByHash.Value)
throw new Exception("Change configuration!");
if (configuration.ByDay.Value && configuration.ByWeek.Value && configuration.BySeason.Value && configuration.ByHash.Value)
throw new Exception("Change configuration!");
}
private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
{
bool result;
string text;
if (!compareBeforeWrite)
result = true;
else
{
if (!File.Exists(path))
text = string.Empty;
else
text = File.ReadAllText(path);
result = text != contents;
}
if (result)
{
if (path.Contains("()"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("[]") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
File.WriteAllText(path, contents);
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
File.WriteAllText(path, contents);
else
File.WriteAllText(path, contents);
}
return result;
}
private long LogDelta(long ticks, string methodName)
{
long result;
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds;
_Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)");
result = DateTime.Now.Ticks;
return result;
}
private List<(string Source, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Property.Models.Group group)
{
List<(string Source, string[] Destination)> results = new();
if (_Configuration.ByDay is null)
throw new Exception($"{nameof(_Configuration.ByDay)} is null!");
if (_Configuration.ByHash is null)
throw new Exception($"{nameof(_Configuration.ByHash)} is null!");
if (_Configuration.BySeason is null)
throw new Exception($"{nameof(_Configuration.BySeason)} is null!");
if (_Configuration.ByWeek is null)
throw new Exception($"{nameof(_Configuration.ByWeek)} is null!");
if (_Configuration.KeepFullPath is null)
throw new Exception($"{nameof(_Configuration.KeepFullPath)} is null!");
char flag;
string day;
int season;
string year;
string month;
string? check;
string fileName;
string? pathRoot;
string seasonName;
string weekOfYear;
string? directory;
string seasonValue;
A_Property? property;
string directoryName;
bool? propertyWrongYear;
string topDirectoryName;
string[]? matches = null;
string[] directorySegments;
DateTime? minimumDateTime = null;
List<string> destinationCollection;
string filteredSourceDirectoryFile;
List<string> directoryNames = new();
List<string> topDirectorySegments = new();
StringBuilder destinationDirectoryName = new();
Calendar calendar = new CultureInfo("en-US").Calendar;
for (int z = 1; z < 3; z++)
{
if (z == 1)
{
check = Path.Combine(destinationDirectory, ".");
pathRoot = Path.GetPathRoot(destinationDirectory);
}
else if (z == 2)
{
check = Path.Combine(topDirectory, ".");
pathRoot = Path.GetPathRoot(topDirectory);
}
else
throw new Exception();
if (string.IsNullOrEmpty(pathRoot))
continue;
for (int i = 0; i < int.MaxValue; i++)
{
check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot)
break;
directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' ');
topDirectorySegments.AddRange(directorySegments);
(_, matches) = Property.Models.Stateless.A_Property.IsWrongYear(directorySegments, string.Empty);
if (matches.Any())
break;
}
if (matches is not null && matches.Any())
break;
}
if (matches is null)
matches = Array.Empty<string>();
for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++)
{
destinationCollection = new();
directoryNames.Clear();
_ = destinationDirectoryName.Clear();
property = group.PropertyCollection[i];
if (property is null)
continue;
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(property);
directory = Path.GetDirectoryName(filteredSourceDirectoryFile);
if (string.IsNullOrEmpty(directory))
continue;
day = minimumDateTime.Value.ToString("MM-dd");
month = minimumDateTime.Value.ToString("MMMM");
(propertyWrongYear, _) = property.IsWrongYear(filteredSourceDirectoryFile, minimumDateTime);
if (propertyWrongYear is null)
flag = '#';
else
{
if (propertyWrongYear.Value)
flag = '~';
else
{
if (property.DateTimeOriginal.HasValue && minimumDateTime.Value.DayOfYear != property.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(minimumDateTime.Value.Ticks - property.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
flag = '^';
else
flag = '=';
}
}
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(minimumDateTime.Value.DayOfYear);
if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
seasonValue = string.Empty;
else
seasonValue = $".{season}";
if (propertyWrongYear is null || !propertyWrongYear.Value)
year = $"{flag}{minimumDateTime.Value:yyyy}{seasonValue}";
else
{
if (matches[0][0] != '~')
year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
else
year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
}
topDirectoryName = Path.GetFileName(topDirectory);
weekOfYear = calendar.GetWeekOfYear(minimumDateTime.Value, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
if (_Configuration.ByHash.Value)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.BySeason.Value && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
directoryNames.Add($"{year} {seasonName}");
else
{
if (!_Configuration.KeepFullPath.Value)
{
_ = destinationDirectoryName.Append(topDirectoryName);
if (_Configuration.BySeason.Value)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{year} {seasonName}" });
else if (_Configuration.ByDay.Value)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}" });
else if (_Configuration.ByWeek.Value)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}" });
else
throw new Exception();
}
else
{
foreach (string sourceDirectoryNameSegment in topDirectorySegments)
{
if (matches.Contains(sourceDirectoryNameSegment))
_ = destinationDirectoryName.Append(year);
else
_ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
}
if (_Configuration.BySeason.Value)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.ByDay.Value)
directoryNames.Add($"{weekOfYear}) {year} {day}");
else if (_Configuration.ByWeek.Value)
directoryNames.Add($"{weekOfYear}) {month} {year}");
else
throw new Exception();
}
}
if (!_Configuration.ByHash.Value || property.Id is null)
fileName = Path.GetFileName(filteredSourceDirectoryFile);
else
fileName = $"{property.Id.Value}{Path.GetExtension(filteredSourceDirectoryFile).ToLower()}";
destinationCollection.Add(destinationDirectory);
destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName);
results.Add(new(filteredSourceDirectoryFile, destinationCollection.ToArray()));
}
return results;
}
private PropertyLogic GetPropertyLogic()
{
PropertyLogic result;
string[] verifyToSeason = Array.Empty<string>();
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason);
return result;
}
private List<(string Source, string[] Destination)> GetFileMoveCollectionAll(List<string> topDirectories, List<Property.Models.Group> groupCollection)
{
List<(string Source, string[] Destination)> results = new();
if (_Configuration.KeepFullPath is null)
throw new Exception($"{nameof(_Configuration.KeepFullPath)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string? topDirectory;
string? checkDirectory;
string sourceDirectory;
string destinationDirectory;
string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, "Z) Moved");
List<(string Source, string[] Destination)> fileMoveCollectionDirectory;
foreach (Property.Models.Group group in groupCollection)
{
sourceDirectory = group.SourceDirectory;
if (!_Configuration.KeepFullPath.Value)
destinationDirectory = destinationRoot;
else
destinationDirectory = string.Concat(destinationRoot, sourceDirectory[_Configuration.PropertyConfiguration.RootDirectory.Length..]);
checkDirectory = Path.GetFullPath(sourceDirectory);
for (int z = 0; z < int.MaxValue; z++)
{
if (checkDirectory == _Configuration.PropertyConfiguration.RootDirectory || topDirectories.Contains(checkDirectory))
break;
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
break;
}
if (string.IsNullOrEmpty(checkDirectory))
continue;
topDirectory = checkDirectory;
fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, group);
results.AddRange(fileMoveCollectionDirectory);
}
return results;
}
private void MoveFiles(List<string> topDirectories, List<Property.Models.Group> groupCollection)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string directoryName;
List<string> distinct = new();
List<(string Source, string[] Destination)> fileMoveCollectionAll = GetFileMoveCollectionAll(topDirectories, groupCollection);
foreach ((string source, string[] destination) in fileMoveCollectionAll)
{
directoryName = Path.Combine(destination.Take(destination.Length - 1).ToArray());
if (distinct.Contains(directoryName))
continue;
distinct.Add(directoryName);
if (!Directory.Exists(directoryName))
_ = Directory.CreateDirectory(directoryName);
}
_Log.Information("Ready to move files?");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to move files back or close console to not move files");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
int moved = 0;
string fullFileName;
foreach ((string source, string[] destination) in fileMoveCollectionAll)
{
fullFileName = Path.Combine(destination);
if (File.Exists(fullFileName))
continue;
File.Move(source, fullFileName);
moved += 1;
}
_Log.Information($"{moved} file(s) moved");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to move files back or close console to leave them moved");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
foreach ((string source, string[] destination) in fileMoveCollectionAll)
{
fullFileName = Path.Combine(destination);
if (File.Exists(source))
continue;
File.Move(fullFileName, source);
moved += 1;
}
_Log.Information($"Done moving back {moved} file(s)");
for (int i = 1; i < 10; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory);
}
}

View File

@ -0,0 +1,35 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Date.Group.Models;
public class AppSettings
{
protected string _Company;
protected string _WorkingDirectoryName;
protected int? _MaxDegreeOfParallelism;
public string Company => _Company;
public string WorkingDirectoryName => _WorkingDirectoryName;
public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism;
// public AppSettings()
// {
// }
[JsonConstructor]
public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism)
{
_Company = company;
_WorkingDirectoryName = workingDirectoryName;
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Binder;
public class AppSettings
{
[Display(Name = "Company"), Required] public string Company { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
[Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; }
public AppSettings()
{
Company = string.Empty;
WorkingDirectoryName = string.Empty;
MaxDegreeOfParallelism = -1;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,30 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Binder;
public class Configuration
{
[Display(Name = "By Date"), Required] public bool? ByDay { get; set; }
[Display(Name = "By Hash"), Required] public bool? ByHash { get; set; }
[Display(Name = "By Season"), Required] public bool? BySeason { get; set; }
[Display(Name = "By Week"), Required] public bool? ByWeek { get; set; }
[Display(Name = "Ignore Subdirectories for Rename"), Required] public bool? KeepFullPath { get; set; }
[Display(Name = "Property Configuration"), Required] public Property.Models.Configuration? PropertyConfiguration { get; set; }
public Configuration()
{
ByDay = null;
ByHash = null;
BySeason = null;
ByWeek = null;
KeepFullPath = null;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,43 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Date.Group.Models;
public class Configuration
{
protected readonly bool? _ByDay;
protected readonly bool? _ByHash;
protected readonly bool? _BySeason;
protected readonly bool? _ByWeek;
protected readonly bool? _KeepFullPath;
protected Property.Models.Configuration? _PropertyConfiguration;
public bool? ByDay => _ByDay;
public bool? ByHash => _ByHash;
public bool? BySeason => _BySeason;
public bool? ByWeek => _ByWeek;
public bool? KeepFullPath => _KeepFullPath;
public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor]
public Configuration(bool? byDay, bool? byHash, bool? bySeason, bool? byWeek, bool? keepFullPath, Property.Models.Configuration? propertyConfiguration)
{
_ByDay = byDay;
_ByHash = byHash;
_BySeason = bySeason;
_ByWeek = byWeek;
_KeepFullPath = keepFullPath;
_PropertyConfiguration = propertyConfiguration;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration;
public void Update() => _PropertyConfiguration?.Update();
}

View File

@ -0,0 +1,40 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Stateless;
public abstract class AppSettings
{
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Stateless;
public abstract class Configuration
{
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory, Property.Models.Configuration propertyConfiguration)
{
Models.Configuration? result;
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Binder.Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
Binder.Configuration configuration = configurationSection.Get<Binder.Configuration>();
string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.Configuration>(json);
if (result is null)
throw new Exception(json);
string jsonThis = result.ToString();
result.Set(propertyConfiguration);
result.Update();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Date.Group.Models.Stateless;
public static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

109
Date-Group/Program.cs Normal file
View File

@ -0,0 +1,109 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.Date.Group.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Date.Group;
public class Program
{
public static void Secondary(List<string> args)
{
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
IConfigurationRoot configurationRoot = configurationBuilder.Build();
AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot);
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception("MaxDegreeOfParallelism must be set!");
if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount)
throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!");
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>();
int silentIndex = args.IndexOf("s");
if (silentIndex > -1)
args.RemoveAt(silentIndex);
try
{
if (args is null)
throw new Exception("args is null!");
#nullable disable
if (Property.Models.Stateless.A_Property.IsWrongYear("-".Split(' '), "2021").Item1.HasValue)
throw new Exception("-");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass".Split(' '), "2021").Item1.HasValue)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("England 2017".Split(' '), "2017").Item1.Value)
throw new Exception("England");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael".Split(' '), "2021").Item1.HasValue)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item2[0] != "~2021.4")
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Chelsea's 2nd Birthday =2014".Split(' '), "2014").Item1.Value)
throw new Exception("Chelsea");
#nullable restore
Shared.Models.Console console = new();
DateGroup _ = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console);
}
catch (Exception ex)
{
log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace));
}
finally
{
Log.CloseAndFlush();
}
if (silentIndex > -1)
log.Debug("Done. Bye");
else
{
log.Debug("Done. Press 'Enter' to end");
_ = Console.ReadLine();
}
}
public static void Main(string[] args)
{
if (args is not null)
Secondary(args.ToList());
else
Secondary(new List<string>());
}
}

View File

@ -0,0 +1,342 @@
{
"Company": "Mike Phares",
"Linux": {},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MaxDegreeOfParallelism": 1,
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"ByDay": false,
"ByHash": false,
"BySeason": true,
"ByWeek": false,
"DateGroup": "2022-04-07",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"KeepFullPath": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": false,
"PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/- Device Videos 2_0_0_3 - Current/_",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"PropertyContentCollectionFiles": [],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".amr",
".AMR",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"VerifyToSeason": [
". 2000",
". 2001",
". 2002",
". 2003",
". 2004",
". 2005",
". 2006",
". 2007",
". 2008",
". 2009",
". 2010",
". 2011",
". 2012",
". 2013",
". 2014",
". 2015",
". 2016",
". 2017",
". 2018",
". 2019",
". 2020",
". 2021",
". 2022",
". 2023",
". 2024",
". 2025",
". 2026",
". 2027",
". 2028",
". 2029",
"=2000.0 Winter",
"=2002.1 Spring",
"=2002.4 Winter",
"=2003.0 Winter",
"=2003.1 Spring",
"=2003.3 Fall",
"=2003.4 Winter",
"=2004.0 Winter",
"=2005.1 Spring",
"=2005.2 Summer",
"=2005.3 Fall",
"=2005.4 Winter",
"=2006.0 Winter",
"=2006.1 Spring",
"=2006.3 Fall",
"=2007.0 Winter",
"=2007.2 Summer Logan Michael",
"=2007.2 Summer",
"=2007.3 Fall Logan Michael",
"=2007.4 Winter Logan Michael",
"=2008.0 Winter Logan Michael",
"=2008.1 Spring Logan Michael",
"=2008.2 Summer Logan Michael",
"=2008.2 Summer",
"=2008.3 Fall Logan Michael",
"=2009.0 Winter Logan Michael",
"=2009.0 Winter",
"=2009.1 Spring Logan Michael",
"=2009.1 Spring",
"=2009.2 Summer Logan Michael",
"=2009.2 Summer",
"=2009.3 Fall Logan Michael",
"=2009.3 Fall",
"=2009.4 Winter Logan Michael",
"=2009.4 Winter",
"=2010.0 Winter Logan Michael",
"=2010.0 Winter",
"=2010.1 Spring Logan Michael",
"=2010.1 Spring",
"=2010.2 Summer",
"=2010.3 Fall Logan Michael",
"=2010.3 Fall",
"=2010.4 Winter",
"=2011.0 Winter",
"=2011.1 Spring",
"=2011.2 Summer",
"=2011.3 Fall",
"=2011.4 Winter",
"=2012.0 Winter Chelsea 2012",
"=2012.0 Winter Chelsea",
"=2012.0 Winter",
"=2012.1 Spring Chelsea",
"=2012.1 Spring",
"=2012.2 Summer Chelsea",
"=2012.2 Summer",
"=2012.3 Fall Chelsea",
"=2012.3 Fall",
"=2012.4 Winter Chelsea",
"=2012.4 Winter",
"=2013.0 Winter Chelsea 2013",
"=2013.0 Winter Chelsea",
"=2013.0 Winter",
"=2013.1 Spring",
"=2013.2 Summer Chelsea",
"=2013.2 Summer",
"=2013.3 Fall Chelsea",
"=2013.3 Fall",
"=2013.4 Winter",
"=2014.0 Winter",
"=2014.1 Spring",
"=2014.2 Summer",
"=2014.3 Fall",
"=2014.4 Winter",
"=2015.0 Winter",
"=2015.1 Spring",
"=2015.2 Summer",
"=2015.3 Fall",
"=2015.4 Winter",
"=2016.0 Winter",
"=2016.1 Spring",
"=2016.2 Summer",
"=2016.3 Fall",
"=2016.4 Winter",
"=2017.1 Spring",
"=2017.2 Summer",
"=2017.3 Fall",
"=2017.4 Winter",
"=2018.0 Winter",
"=2018.1 Spring",
"=2018.3 Fall",
"=2018.4 Winter",
"=2019.0 Winter",
"=2019.1 Spring",
"=2019.2 Summer",
"=2019.3 Fall",
"=2019.4 Winter",
"=2020.0 Winter",
"=2020.1 Spring",
"=2020.2 Summer",
"=2020.3 Fall",
"=2020.4 Winter",
"=2021.1 Spring",
"=2021.2 Summer",
"=2021.3 Fall",
"=2021.4 Winter",
"=2022.0 Winter",
"=2022.1 Spring",
"Anthem 2015",
"April 2010",
"April 2013",
"December 2006",
"December 2010",
"Fall 2005",
"Fall 2015",
"Fall 2016",
"Fall 2017",
"Fall 2018",
"Fall 2019",
"Fall 2020",
"Fall 2021",
"February 2010",
"January 2015",
"July 2010",
"June 2010",
"Kids 2005",
"March 2013",
"May 2010",
"May 2011",
"May 2013",
"October 2005",
"October 2014",
"Spring 2013",
"Spring 2014",
"Spring 2016",
"Spring 2018",
"Spring 2019",
"Spring 2020",
"Summer 2011",
"Summer 2012",
"Summer 2013",
"Summer 2014",
"Summer 2015",
"Summer 2016",
"Summer 2017",
"Summer 2018",
"Summer 2020",
"Summer 2021",
"Winter 2015",
"Winter 2016",
"Winter 2017",
"Winter 2018",
"Winter 2019-2020",
"Winter 2020",
"zzz =2005.0 Winter Tracy Pictures",
"zzz =2005.1 Spring Tracy Pictures",
"zzz =2005.2 Summer Tracy Pictures",
"zzz =2005.3 Fall Tracy Pictures",
"zzz =2005.4 Winter Tracy Pictures",
"zzz =2006.1 Spring Tracy Pictures",
"zzz =2007.0 Winter Tracy Pictures",
"zzz =2007.2 Summer Tracy Pictures",
"zzz =2008.0 Winter Tracy Pictures",
"zzz =2008.2 Summer Tracy Pictures",
"zzz =2009.0 Winter Tracy Pictures",
"zzz =2009.2 Summer Tracy Pictures",
"zzz =2009.3 Fall Tracy Pictures",
"zzz =2009.4 Winter Tracy Pictures",
"zzz =2010.0 Winter Tracy Pictures",
"zzz =2010.1 Spring Tracy Pictures",
"zzz =2010.2 Summer Tracy Pictures",
"zzz =2010.3 Fall Tracy Pictures",
"zzz =2011.0 Winter Tracy Pictures",
"zzz =2011.1 Spring Tracy Pictures",
"zzz =2011.2 Summer Tracy Pictures",
"zzz =2011.3 Fall Tracy Pictures",
"zzz =2011.4 Winter Tracy Pictures",
"zzz =2012.0 Winter Tracy Pictures",
"zzz =2012.1 Spring Tracy Pictures",
"zzz =2012.2 Summer Tracy Pictures",
"zzz =2012.3 Fall Tracy Pictures",
"zzz =2012.4 Winter Tracy Pictures",
"zzz =2013.0 Winter Tracy Pictures",
"zzz =2013.1 Spring Tracy Pictures",
"zzz =2013.2 Summer Tracy Pictures",
"zzz =2013.3 Fall Tracy Pictures",
"zzz =2013.4 Winter Tracy Pictures",
"zzz =2014.0 Winter Tracy Pictures",
"zzz =2014.1 Spring Tracy Pictures",
"zzz =2014.2 Summer Tracy Pictures",
"zzz =2014.3 Fall Tracy Pictures",
"zzz =2014.4 Winter Tracy Pictures",
"zzz =2015.0 Winter Tracy Pictures"
]
}
}
}

1
Instance/.vscode/format-report.json vendored Normal file
View File

@ -0,0 +1 @@
[]

32
Instance/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/x64/Debug/net6.0/win-x64/Instance.dll",
"args": [
"s"
],
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "externalTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processName": "Instance"
}
]
}

14
Instance/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"cSpell.words": [
"Bday",
"Blazor",
"Dlib",
"Exif",
"mmod",
"nameof",
"nosj",
"Phares",
"Serilog",
"Vericruz"
]
}

42
Instance/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Instance.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Instance.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/Instance.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

796
Instance/DlibDotNet.cs Normal file
View File

@ -0,0 +1,796 @@
using FaceRecognitionDotNet;
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using ShellProgressBar;
using System.Drawing.Imaging;
using System.Text.Json;
using View_by_Distance.Instance.Models;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Instance;
public class DlibDotNet
{
private readonly D_Face _Faces;
private readonly G_Index _Index;
private readonly C_Resize _Resize;
private readonly F_Random _Random;
private readonly A2_People _People;
private readonly E3_Rename _Rename;
private readonly B_Metadata _Metadata;
private readonly E_Distance _Distance;
private readonly Serilog.ILogger? _Log;
private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment;
private readonly D2_FaceLandmarks _FaceLandmarks;
private readonly Models.Configuration _Configuration;
private readonly bool _ArgZeroIsConfigurationRootDirectory;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs;
public DlibDotNet(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{
string argZero;
_AppSettings = appSettings;
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!");
_IsEnvironment = isEnvironment;
_Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<DlibDotNet>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory);
Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration);
(Model model, PredictorModel predictorModel) = GetTuple(args, propertyConfiguration, configuration);
if (configuration.SearchForAbandonedFilesFull is null)
throw new Exception($"{nameof(configuration.SearchForAbandonedFilesFull)} is null!");
_Configuration = configuration;
_Index = new G_Index(configuration);
_Random = new F_Random(configuration);
_People = new A2_People(configuration);
_Rename = new E3_Rename(configuration);
_Distance = new E_Distance(configuration);
_FaceLandmarks = new D2_FaceLandmarks(configuration);
if (configuration.ForceMetadataLastWriteTimeToCreationTime is null)
throw new Exception($"{nameof(configuration.ForceMetadataLastWriteTimeToCreationTime)} is null!");
if (configuration.ForceResizeLastWriteTimeToCreationTime is null)
throw new Exception($"{nameof(configuration.ForceResizeLastWriteTimeToCreationTime)} is null!");
if (configuration.IgnoreExtensions is null)
throw new Exception($"{nameof(configuration.IgnoreExtensions)} is null!");
if (configuration.OutputQuality is null)
throw new Exception($"{nameof(configuration.OutputQuality)} is null!");
if (configuration.OverrideForResizeImages is null)
throw new Exception($"{nameof(configuration.OverrideForResizeImages)} is null!");
if (configuration.PropertiesChangedForMetadata is null)
throw new Exception($"{nameof(configuration.PropertiesChangedForMetadata)} is null!");
if (configuration.PropertiesChangedForResize is null)
throw new Exception($"{nameof(configuration.PropertiesChangedForResize)} is null!");
_Metadata = new(configuration.ForceMetadataLastWriteTimeToCreationTime.Value, configuration.PropertiesChangedForMetadata.Value);
if (args.Count > 0)
argZero = Path.GetFullPath(args[0]);
else
argZero = Path.GetFullPath(propertyConfiguration.RootDirectory);
_ArgZeroIsConfigurationRootDirectory = propertyConfiguration.RootDirectory == argZero;
(ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) = C_Resize.GetTuple(configuration.OutputExtension, configuration.OutputQuality.Value);
_Resize = new C_Resize(configuration.ForceResizeLastWriteTimeToCreationTime.Value, configuration.OverrideForResizeImages.Value, configuration.PropertiesChangedForResize.Value, configuration.ValidResolutions, imageCodecInfo, encoderParameters);
ModelParameter modelParameter = new()
{
CnnFaceDetectorModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "mmod_human_face_detector.dat")),
FaceRecognitionModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "dlib_face_recognition_resnet_model_v1.dat")),
PosePredictor5FaceLandmarksModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "shape_predictor_5_face_landmarks.dat")),
PosePredictor68FaceLandmarksModel = File.ReadAllBytes(Path.Combine(configuration.ModelDirectory, "shape_predictor_68_face_landmarks.dat"))
};
_Faces = new D_Face(configuration, argZero, model, modelParameter, predictorModel);
if (configuration.SkipSearch is null)
throw new Exception($"{nameof(configuration.SkipSearch)} is null!");
if (_ArgZeroIsConfigurationRootDirectory)
_ = _People.GetPeople(propertyConfiguration);
if (!isSilent && configuration.TestDistanceResults.HasValue && configuration.TestDistanceResults.Value)
{
E2_Navigate e2Navigate = new(console, configuration, argZero);
e2Navigate.Navigate(propertyConfiguration, configuration.OutputResolutions[0]);
}
if (_ArgZeroIsConfigurationRootDirectory)
{
long ticks = DateTime.Now.Ticks;
string[] directories = Property.Models.Stateless.A_Property.GetDirectoryRenameCollection(propertyConfiguration, configuration.OutputResolutions[0], nameof(B_Metadata), nameof(C_Resize));
foreach (string directory in directories)
{
if (!Directory.Exists(directory))
continue;
Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull(argZero, directory, onlyJson: false);
}
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull));
}
if (!configuration.SkipSearch.Value)
Search(argZero);
if (_Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory)
{
long ticks = DateTime.Now.Ticks;
if (configuration.SearchForAbandonedFilesFull.Value)
{
string[] directories = _Rename.GetDirectoryRenameCollection(propertyConfiguration, relativePath: string.Empty, newDirectoryName: string.Empty, jsonFiles4InfoAny: false);
foreach (string directory in directories)
{
if (!Directory.Exists(directory))
continue;
Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull(argZero, directory, onlyJson: true);
}
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.SearchForAbandonedFilesFull));
}
List<string[]> directoryCollections = _Rename.GetDirectoryRenameCollections(propertyConfiguration, relativePath: string.Empty, newDirectoryName: string.Empty, jsonFiles4InfoAny: false);
foreach (string[] directoryCollection in directoryCollections)
{
_Log.Information(string.Concat("Cleaning <", directoryCollection[0], ">"));
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(directoryCollection[0]);
}
string d2FaceLandmarksRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(D2_FaceLandmarks));
_Log.Information(string.Concat("Cleaning <", d2FaceLandmarksRootDirectory, ">"));
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(d2FaceLandmarksRootDirectory);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.IPath.DeleteEmptyDirectories));
}
string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message);
if (_Exceptions.Count != 0)
throw new Exception(message);
if (configuration.LoadOrCreateThenSaveDirectoryDistanceResults is null)
throw new Exception($"{nameof(configuration.LoadOrCreateThenSaveDirectoryDistanceResults)} is null!");
if (configuration.LoadOrCreateThenSaveDirectoryDistanceResults.Value)
{
long ticks = DateTime.Now.Ticks;
foreach (string outputResolution in configuration.OutputResolutions)
_Distance.LoadOrCreateThenSaveDirectoryDistanceResults(propertyConfiguration, outputResolution);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(E_Distance.LoadOrCreateThenSaveDirectoryDistanceResults));
}
}
private long LogDelta(long ticks, string methodName)
{
long result;
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds;
_Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)");
result = DateTime.Now.Ticks;
return result;
}
#pragma warning disable CA1416
#pragma warning restore CA1416
private (Model Model, PredictorModel PredictorModel) GetTuple(List<string> args, Property.Models.Configuration propertyConfiguration, Models.Configuration configuration)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
(Model Model, PredictorModel PredictorModel) result;
Array array;
Model? model = null;
string[] sourceDirectoryNames;
PredictorModel? predictorModel = null;
if (!args.Any())
sourceDirectoryNames = Array.Empty<string>();
else
{
string argZero = Path.GetFullPath(args[0]);
sourceDirectoryNames = argZero.Split(Path.DirectorySeparatorChar);
if (!argZero.StartsWith(propertyConfiguration.RootDirectory))
throw new Exception($"Source directory must be inside root directory! <{argZero}> <{propertyConfiguration.RootDirectory}>");
if (_ArgZeroIsConfigurationRootDirectory && propertyConfiguration.RootDirectory != argZero)
{
if (!configuration.MixedYearRelativePaths.Contains(sourceDirectoryNames[0]))
{
string[] segments = sourceDirectoryNames[0].Split(' ');
if (segments.Length < 2 || segments[^1].Length != 4 || (segments[^1][..2] != "19" && segments[^1][..2] != "20"))
throw new Exception("root subdirectory must have a year at the end or directory name needs to be added to the exclude list!");
}
}
}
_Log.Information(configuration.ModelDirectory);
string[] resizeMatch = (from l in sourceDirectoryNames where configuration.ValidResolutions.Contains(l) select l).ToArray();
if (resizeMatch.Any())
throw new Exception("Input directory should be the source and not a resized directory!");
array = Enum.GetValues(typeof(Model));
foreach (Model check in array)
{
if (configuration.ModelName.Contains(check.ToString()))
{
model = check;
break;
}
}
if (model is null)
throw new Exception("Destination directory must have Model name!");
model = model.Value;
array = Enum.GetValues(typeof(PredictorModel));
foreach (PredictorModel check in array)
{
if (configuration.PredictorModelName.Contains(check.ToString()))
{
predictorModel = check;
break;
}
}
if (predictorModel is null)
throw new Exception("Destination directory must have Predictor Model name!");
predictorModel = predictorModel.Value;
result = new(model.Value, predictorModel.Value);
return result;
}
private void Verify(Models.Configuration configuration)
{
if (!configuration.OutputResolutions.Any() || string.IsNullOrEmpty(configuration.OutputResolutions[0]) || !configuration.ValidResolutions.Contains(configuration.OutputResolutions[0]))
throw new Exception($"{nameof(configuration.OutputResolutions)} must be a valid outputResolution!");
if ((from l in configuration.OutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
throw new Exception($"One or more {nameof(configuration.OutputResolutions)} are not in the ValidResolutions list!");
if ((from l in configuration.SaveFaceLandmarkForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any())
throw new Exception($"One or more {nameof(configuration.SaveFaceLandmarkForOutputResolutions)} are not in the ValidResolutions list!");
if (configuration.CheckJsonForDistanceResults is null)
throw new Exception($"{nameof(configuration.CheckJsonForDistanceResults)} must be set!");
if (configuration.CrossDirectoryMaxItemsInDistanceCollection is null)
throw new Exception($"{nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection)} must be set!");
if (configuration.DistanceFactor is null)
throw new Exception($"{nameof(configuration.DistanceFactor)} must be set!");
if (configuration.ForceMetadataLastWriteTimeToCreationTime is null)
throw new Exception($"{nameof(configuration.ForceMetadataLastWriteTimeToCreationTime)} must be set!");
if (configuration.ForceResizeLastWriteTimeToCreationTime is null)
throw new Exception($"{nameof(configuration.ForceResizeLastWriteTimeToCreationTime)} must be set!");
if (configuration.IgnoreExtensions is null)
throw new Exception($"{nameof(configuration.IgnoreExtensions)} must be set!");
if (configuration.IgnoreRelativePaths is null)
throw new Exception($"{nameof(configuration.IgnoreRelativePaths)} must be set!");
if (configuration.LoadOrCreateThenSaveDirectoryDistanceResults is null)
throw new Exception($"{nameof(configuration.LoadOrCreateThenSaveDirectoryDistanceResults)} must be set!");
if (configuration.LoadOrCreateThenSaveDistanceResults is null)
throw new Exception($"{nameof(configuration.LoadOrCreateThenSaveDistanceResults)} must be set!");
if (configuration.LoadOrCreateThenSaveImageFacesResults is null)
throw new Exception($"{nameof(configuration.LoadOrCreateThenSaveImageFacesResults)} must be set!");
if (configuration.LoadOrCreateThenSaveIndex is null)
throw new Exception($"{nameof(configuration.LoadOrCreateThenSaveIndex)} must be set!");
if (configuration.LocationConfidenceFactor is null)
throw new Exception($"{nameof(configuration.LocationConfidenceFactor)} must be set!");
if (configuration.MappedMaxIndex is null)
throw new Exception($"{nameof(configuration.MappedMaxIndex)} must be set!");
if (configuration.MappedMaxIndex.HasValue && configuration.LoadOrCreateThenSaveIndex.Value && !_IsEnvironment.DebuggerWasAttachedDuringConstructor)
throw new Exception($"{nameof(configuration.MappedMaxIndex)} only allowed when debugger is attached!");
if (configuration.MaxItemsInDistanceCollection is null)
throw new Exception($"{nameof(configuration.MaxItemsInDistanceCollection)} must be set!");
if (configuration.MixedYearRelativePaths is null)
throw new Exception($"{nameof(configuration.MixedYearRelativePaths)} must be set!");
if (configuration.NumJitters is null)
throw new Exception($"{nameof(configuration.NumJitters)} must be set!");
if (configuration.OutputQuality is null)
throw new Exception($"{nameof(configuration.OutputQuality)} must be set!");
if (configuration.OutputResolutions is null)
throw new Exception($"{nameof(configuration.OutputResolutions)} must be set!");
if (configuration.OverrideForFaceImages is null)
throw new Exception($"{nameof(configuration.OverrideForFaceImages)} must be set!");
if (configuration.OverrideForFaceLandmarkImages is null)
throw new Exception($"{nameof(configuration.OverrideForFaceLandmarkImages)} must be set!");
if (configuration.OverrideForResizeImages is null)
throw new Exception($"{nameof(configuration.OverrideForResizeImages)} must be set!");
if (configuration.PaddingLoops is null)
throw new Exception($"{nameof(configuration.PaddingLoops)} must be set!");
if (configuration.PropertiesChangedForDistance is null)
throw new Exception($"{nameof(configuration.PropertiesChangedForDistance)} must be set!");
if (configuration.PropertiesChangedForFaces is null)
throw new Exception($"{nameof(configuration.PropertiesChangedForFaces)} must be set!");
if (configuration.PropertiesChangedForIndex is null)
throw new Exception($"{nameof(configuration.PropertiesChangedForIndex)} must be set!");
if (configuration.PropertiesChangedForMetadata is null)
throw new Exception($"{nameof(configuration.PropertiesChangedForMetadata)} must be set!");
if (configuration.PropertiesChangedForResize is null)
throw new Exception($"{nameof(configuration.PropertiesChangedForResize)} must be set!");
if (configuration.Reverse is null)
throw new Exception($"{nameof(configuration.Reverse)} must be set!");
if (configuration.SaveFaceLandmarkForOutputResolutions is null)
throw new Exception($"{nameof(configuration.SaveFaceLandmarkForOutputResolutions)} must be set!");
if (configuration.SaveFullYearOfRandomFiles is null)
throw new Exception($"{nameof(configuration.SaveFullYearOfRandomFiles)} must be set!");
if (configuration.SaveResizedSubfiles is null)
throw new Exception($"{nameof(configuration.SaveResizedSubfiles)} must be set!");
if (configuration.SearchForAbandonedFilesFull is null)
throw new Exception($"{nameof(configuration.SearchForAbandonedFilesFull)} must be set!");
if (configuration.SkipSearch is null)
throw new Exception($"{nameof(configuration.SkipSearch)} must be set!");
if (configuration.TestDistanceResults is null)
throw new Exception($"{nameof(configuration.TestDistanceResults)} must be set!");
if (configuration.ValidResolutions is null)
throw new Exception($"{nameof(configuration.ValidResolutions)} must be set!");
if (string.IsNullOrEmpty(configuration.ModelDirectory) || !Directory.Exists(configuration.ModelDirectory))
throw new Exception($"{nameof(configuration.ModelDirectory)} must have a value and exits!");
if (string.IsNullOrEmpty(configuration.ModelName))
throw new Exception($"{nameof(configuration.ModelName)} must have a value!");
if (string.IsNullOrEmpty(configuration.OutputExtension))
throw new Exception($"{nameof(configuration.OutputExtension)} must have a value!");
if (string.IsNullOrEmpty(configuration.PredictorModelName))
throw new Exception($"{nameof(configuration.PredictorModelName)} must have a value!");
if (configuration.DistanceFactor.Value + configuration.LocationConfidenceFactor.Value != 10)
throw new Exception($"{nameof(configuration.DistanceFactor)} and {nameof(configuration.LocationConfidenceFactor)} must add up to 10!");
}
private int FullParallelWork(object @lock, long ticks, PropertyLogic propertyLogic, string outputResolution, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileInfo?> propertyFileInfoCollection, List<A_Property> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<D_Face>> faceCollections, int g, string sourceDirectory, int r, string[] filteredSourceDirectoryFiles, int count)
{
int result = 0;
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(AppSettings.MaxDegreeOfParallelism)} is null!");
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism.Value };
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
if (faceCollections.Count != filteredSourceDirectoryFiles.Length || metadataCollection.Count != filteredSourceDirectoryFiles.Length || resizeKeyValuePairs.Count != filteredSourceDirectoryFiles.Length || propertyCollection.Count != filteredSourceDirectoryFiles.Length)
{
for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++)
{
faceCollections.Add(new());
metadataCollection.Add(new());
resizeKeyValuePairs.Add(new());
propertyCollection.Add(new());
propertyFileInfoCollection.Add(null);
}
}
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
using (ProgressBar progressBar = new(filteredSourceDirectoryFiles.Length, $"{g}) {r + 1:000} / {count:000} - {outputResolution} - {sourceDirectory} - {filteredSourceDirectoryFiles.Length} file(s) - {totalSeconds} total second(s)", options))
{
_ = Parallel.For(0, filteredSourceDirectoryFiles.Length, parallelOptions, i =>
{
try
{
FullParallelForWork(propertyLogic, @lock, outputResolution, sourceDirectoryChanges, propertyFileInfoCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, sourceDirectory, index: i, filteredSourceDirectoryFiles[i]);
if (sourceDirectoryChanges.Any())
progressBar.Tick();
}
catch (Exception ex)
{
result += 1;
_Log.Error(string.Concat(sourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex);
if (result == filteredSourceDirectoryFiles.Length)
throw new Exception(string.Concat("All in [", sourceDirectory, "]failed!"));
}
});
}
return result;
}
private void FullParallelForWork(PropertyLogic propertyLogic, object @lock, string outputResolution, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileInfo?> propertyFileInfoCollection, List<A_Property> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<D_Face>> imageFaceCollections, string sourceDirectory, int index, string filteredSourceDirectoryFile)
{
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration.SaveResizedSubfiles is null)
throw new Exception($"{nameof(_Configuration.SaveResizedSubfiles)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.WriteBitmapDataBytes)} is null!");
List<D_Face> faceCollection;
string original = "Original";
long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now;
List<string> parseExceptions = new();
Dictionary<string, int[]> imageResizeKeyValuePairs;
List<Tuple<string, DateTime>> subFileTuples = new();
List<KeyValuePair<string, string>> metadataCollection;
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filteredSourceDirectoryFile);
string relativePath = Property.Models.Stateless.IPath.GetRelativePath(filteredSourceDirectoryFile, _Configuration.PropertyConfiguration.RootDirectory.Length);
FileInfo propertyFileInfo = new(Path.Combine(propertyLogic.AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(fileNameWithoutExtension, ".json")));
A_Property property = propertyLogic.GetProperty(propertyLogic.AngleBracketCollection[0], sourceDirectory, filteredSourceDirectoryFile, subFileTuples, parseExceptions, propertyFileInfo);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.GetProperty));
(int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(subFileTuples, parseExceptions, filteredSourceDirectoryFile, relativePath, fileNameWithoutExtension);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection));
FileInfo resizedFileInfo = new(Path.Combine(_Resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(filteredSourceDirectoryFile)));
imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, filteredSourceDirectoryFile, relativePath, fileNameWithoutExtension);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs));
if (_Configuration.SaveResizedSubfiles.Value)
{
_Resize.SaveResizedSubfile(outputResolution, subFileTuples, filteredSourceDirectoryFile, original, property, imageResizeKeyValuePairs, resizedFileInfo);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile));
resizedFileInfo.Refresh();
}
else if (outputResolution == _Configuration.OutputResolutions[0] && false)
{
byte[] bytes = _Resize.GetResizedBytes(outputResolution, subFileTuples, filteredSourceDirectoryFile, property, imageResizeKeyValuePairs);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(C_Resize.GetResizedBytes));
string path = Path.Combine(resizedFileInfo.DirectoryName, Path.GetFileNameWithoutExtension(resizedFileInfo.Name));
File.WriteAllBytes(path, bytes);
}
if (_Configuration.LoadOrCreateThenSaveImageFacesResults is null || !_Configuration.LoadOrCreateThenSaveImageFacesResults.Value)
faceCollection = new();
else
{
int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution];
int outputResolutionWidth = outputResolutionCollection[0];
int outputResolutionHeight = outputResolutionCollection[1];
int outputResolutionOrientation = outputResolutionCollection[2];
faceCollection = _Faces.GetFaces(_Configuration.PropertyConfiguration, outputResolution, subFileTuples, parseExceptions, relativePath, fileNameWithoutExtension, property, resizedFileInfo, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(D_Face.GetFaces));
_Faces.SaveFaces(_Configuration.PropertyConfiguration, subFileTuples, parseExceptions, relativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(D_Face.SaveFaces));
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
{
_FaceLandmarks.SaveFaceLandmarkImages(subFileTuples, parseExceptions, relativePath, fileNameWithoutExtension, resizedFileInfo, faceCollection);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(D2_FaceLandmarks.SaveFaceLandmarkImages));
}
}
lock (@lock)
{
propertyCollection[index] = property;
imageFaceCollections[index] = faceCollection;
metadataCollections[index] = metadataCollection;
propertyFileInfoCollection[index] = propertyFileInfo;
resizeKeyValuePairs[index] = imageResizeKeyValuePairs;
sourceDirectoryChanges.AddRange(from l in subFileTuples where l.Item2 > dateTime select l);
}
}
private static void WriteTab(string checkDirectory, List<(string Id, string Line)> metadataIdLines, string fileName)
{
string text;
FileInfo fileInfo;
List<string> duplicates = new();
List<string> metadataIds = new();
fileInfo = new(Path.Combine(checkDirectory, "[()]", Path.ChangeExtension(fileName, "tsv")));
if (fileInfo?.Directory is null)
throw new Exception();
if (!fileInfo.Directory.Exists)
fileInfo.Directory.Create();
foreach ((string Id, string Line) metadataIdLine in metadataIdLines)
{
if (metadataIds.Contains(metadataIdLine.Id))
duplicates.Add(metadataIdLine.Id);
else
metadataIds.Add(metadataIdLine.Id);
}
for (int i = metadataIdLines.Count - 1; i > -1; i--)
{
if (duplicates.Contains(metadataIdLines[i].Id))
metadataIdLines.RemoveAt(i);
}
if (metadataIdLines.Any())
{
text = string.Join(Environment.NewLine, from l in metadataIdLines orderby l.Id select l.Line);
_ = Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, text, compareBeforeWrite: true);
}
else
{
if (fileInfo.Exists)
File.Delete(fileInfo.FullName);
}
}
private void WriteGroup(PropertyLogic propertyLogic, List<A_Property> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<List<D_Face>> faceCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, string sourceDirectory, string[] filteredSourceDirectoryFiles)
{
if (_Configuration.PropertiesChangedForMetadata is null)
throw new Exception($"{nameof(_Configuration.PropertiesChangedForMetadata)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
if (_Configuration.PropertyConfiguration.PropertiesChangedForProperty is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PropertiesChangedForProperty)} is null!");
if (_Configuration.PropertiesChangedForResize is null)
throw new Exception($"{nameof(_Configuration.PropertiesChangedForResize)} is null!");
if (_Configuration.PropertiesChangedForFaces is null)
throw new Exception($"{nameof(_Configuration.PropertiesChangedForFaces)} is null!");
string key;
string json;
string checkFile;
int sourceDirectoryLength = sourceDirectory.Length;
int rootDirectoryLength = _Configuration.PropertyConfiguration.RootDirectory.Length;
JsonSerializerOptions writeIndentedJsonSerializerOptions = new() { WriteIndented = false };
if (!(from l in propertyCollection where l?.Width is null select true).Any())
{
string checkDirectory;
List<KeyValuePair<string, List<D_Face>>> faceCollectionsKeyValuePairs = new();
List<KeyValuePair<string, A_Property>> propertyCollectionKeyValuePairs = new();
List<KeyValuePair<string, Dictionary<string, int[]>>> resizeKeyValuePairsCollections = new();
List<KeyValuePair<string, List<KeyValuePair<string, string>>>> metadataCollectionKeyValuePairs = new();
(int level, List<string> directories) = Property.Models.Stateless.IPath.Get(_Configuration.PropertyConfiguration.RootDirectory, sourceDirectory);
string fileName = string.Concat(string.Join(_Configuration.PropertyConfiguration.FileNameDirectorySeparator, directories), ".json");
for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++)
{
key = Property.Models.Stateless.IPath.GetRelativePath(filteredSourceDirectoryFiles[i], sourceDirectoryLength);
faceCollectionsKeyValuePairs.Add(new KeyValuePair<string, List<D_Face>>(key, faceCollections[i]));
propertyCollectionKeyValuePairs.Add(new KeyValuePair<string, A_Property>(key, propertyCollection[i]));
resizeKeyValuePairsCollections.Add(new KeyValuePair<string, Dictionary<string, int[]>>(key, resizeKeyValuePairs[i]));
metadataCollectionKeyValuePairs.Add(new KeyValuePair<string, List<KeyValuePair<string, string>>>(key, metadataCollection[i]));
}
if (_Metadata.AngleBracketCollection.Any())
{
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(_Metadata.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(metadataCollectionKeyValuePairs, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, compareBeforeWrite: true);
}
if (propertyLogic.AngleBracketCollection.Any())
{
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(propertyLogic.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(propertyCollectionKeyValuePairs, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, compareBeforeWrite: true);
}
if (_Resize.AngleBracketCollection.Any())
{
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(_Resize.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(resizeKeyValuePairsCollections, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, compareBeforeWrite: true);
}
if (_Configuration.LoadOrCreateThenSaveImageFacesResults.HasValue && _Configuration.LoadOrCreateThenSaveImageFacesResults.Value && _Faces.AngleBracketCollection.Any())
{
checkDirectory = Property.Models.Stateless.IPath.GetDirectory(_Faces.AngleBracketCollection[0], level, "[{}]");
checkFile = Path.Combine(checkDirectory, fileName);
if (File.Exists(checkFile))
File.Move(checkFile, Path.Combine(checkDirectory, fileName));
checkFile = Path.Combine(checkDirectory, fileName);
json = JsonSerializer.Serialize(faceCollectionsKeyValuePairs, writeIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(checkFile, json, compareBeforeWrite: true);
}
}
}
private void FullDoWork(List<string> topDirectories, List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime)} is null!");
if (_Configuration.LoadOrCreateThenSaveImageFacesResults is null)
throw new Exception($"{nameof(_Configuration.LoadOrCreateThenSaveImageFacesResults)} is null!");
if (_Configuration.LoadOrCreateThenSaveDirectoryDistanceResults is null)
throw new Exception($"{nameof(_Configuration.LoadOrCreateThenSaveDirectoryDistanceResults)} is null!");
if (_Configuration.LoadOrCreateThenSaveDistanceResults is null)
throw new Exception($"{nameof(_Configuration.LoadOrCreateThenSaveDistanceResults)} is null!");
if (_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!");
if (_Configuration.PropertyConfiguration.PopulatePropertyId is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PopulatePropertyId)} is null!");
if (_Configuration.PropertyConfiguration.PropertiesChangedForProperty is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PropertiesChangedForProperty)} is null!");
if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.WriteBitmapDataBytes)} is null!");
int exceptionCount;
object @lock = new();
long ticks = DateTime.Now.Ticks;
string[] filteredSourceDirectoryFiles;
List<List<D_Face>> faceCollections = new();
List<A_Property> propertyCollection = new();
PropertyLogic propertyLogic = GetPropertyLogic();
List<FileInfo?> propertyFileInfoCollection = new();
List<Dictionary<string, int[]>> resizeKeyValuePairs = new();
List<Tuple<string, DateTime>> sourceDirectoryChanges = new();
string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property));
List<List<KeyValuePair<string, string>>> metadataCollection = new();
foreach (string outputResolution in _Configuration.OutputResolutions)
{
_FileKeyValuePairs.Clear();
_FilePropertiesKeyValuePairs.Clear();
foreach ((int g, string sourceDirectory, string[] sourceDirectoryFiles, int r) in groupCollection)
{
if (!topDirectories.Any())
continue;
_Faces.AngleBracketCollection.Clear();
_Resize.AngleBracketCollection.Clear();
_Metadata.AngleBracketCollection.Clear();
propertyLogic.AngleBracketCollection.Clear();
_FaceLandmarks.AngleBracketCollection.Clear();
filteredSourceDirectoryFiles = (from l in sourceDirectoryFiles where !_Configuration.IgnoreExtensions.Contains(Path.GetExtension(l)) select l).ToArray();
if (!filteredSourceDirectoryFiles.Any())
continue;
propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration,
sourceDirectory,
nameof(A_Property),
outputResolution,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false,
contentDescription: string.Empty,
singletonDescription: "Properties for each image",
collectionDescription: string.Empty));
_Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration,
sourceDirectory,
nameof(B_Metadata),
outputResolution,
includeResizeGroup: false,
includeModel: false,
includePredictorModel: false,
contentDescription: string.Empty,
singletonDescription: "Metadata as key value pairs",
collectionDescription: string.Empty));
_Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration,
sourceDirectory,
nameof(C_Resize),
outputResolution,
includeResizeGroup: true,
includeModel: false,
includePredictorModel: false,
contentDescription: "Resized image",
singletonDescription: "Resize deminsions for each resolution",
collectionDescription: string.Empty));
if (_Configuration.LoadOrCreateThenSaveImageFacesResults.HasValue && _Configuration.LoadOrCreateThenSaveImageFacesResults.Value)
_Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration,
sourceDirectory,
nameof(D_Face),
outputResolution,
includeResizeGroup: true,
includeModel: true,
includePredictorModel: true,
contentDescription: "n png file(s) for each face found",
singletonDescription: string.Empty,
collectionDescription: "For each image a json file with all faces found"));
if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
_FaceLandmarks.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_Configuration.PropertyConfiguration,
sourceDirectory,
nameof(D2_FaceLandmarks),
outputResolution,
includeResizeGroup: true,
includeModel: true,
includePredictorModel: true,
contentDescription: "n x 2 png file(s) for each face found",
singletonDescription: string.Empty,
collectionDescription: string.Empty));
exceptionCount = FullParallelWork(@lock, ticks, propertyLogic, outputResolution, sourceDirectoryChanges, propertyFileInfoCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, faceCollections, g, sourceDirectory, r, filteredSourceDirectoryFiles, groupCollection.Count);
if (metadataCollection.Count != filteredSourceDirectoryFiles.Length || propertyCollection.Count != filteredSourceDirectoryFiles.Length || resizeKeyValuePairs.Count != filteredSourceDirectoryFiles.Length || faceCollections.Count != filteredSourceDirectoryFiles.Length)
throw new Exception("Counts don't match!");
if (exceptionCount != 0)
_Exceptions.Add(sourceDirectory);
else
{
string key;
int rootDirectoryLength = _Configuration.PropertyConfiguration.RootDirectory.Length;
_FilePropertiesKeyValuePairs.Add(sourceDirectory, new List<Tuple<string, A_Property>>());
for (int i = 0; i < filteredSourceDirectoryFiles.Length; i++)
{
key = Property.Models.Stateless.IPath.GetRelativePath(filteredSourceDirectoryFiles[i], rootDirectoryLength);
_FileKeyValuePairs.Add(new KeyValuePair<string, string>(sourceDirectory, key));
_FilePropertiesKeyValuePairs[sourceDirectory].Add(new Tuple<string, A_Property>(key, propertyCollection[i]));
}
}
if (exceptionCount == 0 && _ArgZeroIsConfigurationRootDirectory)
WriteGroup(propertyLogic, propertyCollection, metadataCollection, faceCollections, resizeKeyValuePairs, sourceDirectory, filteredSourceDirectoryFiles);
if (exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResults.HasValue && _Configuration.LoadOrCreateThenSaveDistanceResults.Value)
_Distance.LoadOrCreateThenSaveDistanceResults(_Configuration.PropertyConfiguration, sourceDirectory, outputResolution, sourceDirectoryChanges, filteredSourceDirectoryFiles, faceCollections);
if (_Resize.AngleBracketCollection.Any())
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Resize.AngleBracketCollection[0].Replace("<>", "()"));
if (_Faces.AngleBracketCollection.Any())
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Faces.AngleBracketCollection[0].Replace("<>", "()"));
if (_FaceLandmarks.AngleBracketCollection.Any())
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_FaceLandmarks.AngleBracketCollection[0].Replace("<>", "()"));
if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any())
{
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key when ready to continue or close console");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
}
if (_ArgZeroIsConfigurationRootDirectory && outputResolution == _Configuration.OutputResolutions[0])
{
int loadLessThan = 7;
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration);
PropertyCompare.Models.PropertyCompare[] propertyCompares = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan);
{
string[] lines = (from l in propertyCompares select l.GetSelect()).ToArray();
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "[{}]");
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
string json = JsonSerializer.Serialize(propertyCompares, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);
}
if (!_Configuration.LoadOrCreateThenSaveImageFacesResults.Value && !_Configuration.LoadOrCreateThenSaveDirectoryDistanceResults.Value && !_Configuration.LoadOrCreateThenSaveDistanceResults.Value)
break;
if (_Exceptions.Count == 0)
{
if (_FileKeyValuePairs.Any())
_Random.Random(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], _FileKeyValuePairs);
if (_IsEnvironment.Development)
continue;
G2_Identify identify = new(_Configuration);
List<G2_Identify> identifiedCollection = identify.GetIdentifiedCollection(_Configuration.PropertyConfiguration, _IsEnvironment, _People);
_People.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection);
identify.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection);
if (_Configuration.LoadOrCreateThenSaveIndex.HasValue && _Configuration.LoadOrCreateThenSaveIndex.Value && _FilePropertiesKeyValuePairs.Any())
_Index.SetIndex(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs);
}
}
}
}
private PropertyLogic GetPropertyLogic()
{
PropertyLogic result;
string[] verifyToSeason = Array.Empty<string>();
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason);
return result;
}
private void Search(string argZero)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime)} is null!");
if (_Configuration.PropertyConfiguration.IgnoreExtensions is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.IgnoreExtensions)} is null!");
if (_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!");
if (_Configuration.PropertyConfiguration.PopulatePropertyId is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PopulatePropertyId)} is null!");
if (_Configuration.PropertyConfiguration.PropertiesChangedForProperty is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.PropertiesChangedForProperty)} is null!");
if (_Configuration.Reverse is null)
throw new Exception($"{nameof(_Configuration.Reverse)} is null!");
if (_Configuration.PropertyConfiguration.WriteBitmapDataBytes is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration.WriteBitmapDataBytes)} is null!");
string searchPattern = "*";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
PropertyLogic propertyLogic = GetPropertyLogic();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(argZero, searchPattern, topDirectories, _Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, _Configuration.Reverse.Value);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
_Exceptions.AddRange(propertyLogic.DoWork(_Configuration.PropertyConfiguration, topDirectories, groupCollection, firstPass: true));
string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message);
if (_Exceptions.Count != 0)
throw new Exception(message);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(argZero, searchPattern, topDirectories, _Configuration.PropertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, _Configuration.Reverse.Value);
if (_AppSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
FullDoWork(topDirectories, groupCollection);
}
internal void RenameQueue()
{
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
_Rename.RenameQueue(_Configuration.PropertyConfiguration);
}
}

92
Instance/Instance.csproj Normal file
View File

@ -0,0 +1,92 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Instance</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DlibDotNet" Version="19.21.0.20210302" />
<!--PackageReference Include="configuration.MKL" Version="19.21.0.20210302" /-->
<!--PackageReference Include="DlibDotNet-WithCUDA" Version="19.17.0.20190429" /-->
<!--PackageReference Include="configuration.CUDA92" Version="19.21.0.20210302" /-->
<!--PackageReference Include="configuration.CUDA102" Version="19.21.0.20210302" /-->
<!--PackageReference Include="configuration.CUDA110" Version="19.21.0.20210302" /-->
<!--PackageReference Include="configuration.CUDA111" Version="19.21.0.20210302" /-->
<!--PackageReference Include="configuration.CUDA112" Version="19.21.0.20210302" /-->
</ItemGroup>
<ItemGroup>
<PackageReference Include="FaceRecognitionDotNet" Version="1.3.0.4" />
<!--PackageReference Include="FaceRecognitionDotNet.MKL" Version="1.3.0.4" /-->
<!--PackageReference Include="FaceRecognitionDotNet-WithCUDA" Version="1.2.3.10" /-->
<!--PackageReference Include="FaceRecognitionDotNet.CUDA92" Version="1.3.0.4" /-->
<!--PackageReference Include="FaceRecognitionDotNet.CUDA102" Version="1.3.0.4" /-->
<!--PackageReference Include="FaceRecognitionDotNet.CUDA110" Version="1.3.0.4" /-->
<!--PackageReference Include="FaceRecognitionDotNet.CUDA111" Version="1.3.0.4" /-->
<!--PackageReference Include="FaceRecognitionDotNet.CUDA112" Version="1.3.0.4" /-->
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.Staging.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,35 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Instance.Models;
public class AppSettings
{
protected string _Company;
protected string _WorkingDirectoryName;
protected int? _MaxDegreeOfParallelism;
public string Company => _Company;
public string WorkingDirectoryName => _WorkingDirectoryName;
public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism;
// public AppSettings()
// {
// }
[JsonConstructor]
public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism)
{
_Company = company;
_WorkingDirectoryName = workingDirectoryName;
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Instance.Models.Binder;
public class AppSettings
{
[Display(Name = "Company"), Required] public string Company { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
[Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; }
public AppSettings()
{
Company = string.Empty;
WorkingDirectoryName = string.Empty;
MaxDegreeOfParallelism = -1;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,99 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Instance.Models.Binder;
public class Configuration
{
[Display(Name = "Check Json For Distance Results"), Required] public bool? CheckJsonForDistanceResults { get; set; }
[Display(Name = "CrossDirectory Max Items In Distance Collection"), Required] public int? CrossDirectoryMaxItemsInDistanceCollection { get; set; }
[Display(Name = "Distance Factor"), Required] public int? DistanceFactor { get; set; }
[Display(Name = "Force Metadata Last Write Time to Creation Time"), Required] public bool? ForceMetadataLastWriteTimeToCreationTime { get; set; }
[Display(Name = "Force Resize Last Write Time to Creation Time"), Required] public bool? ForceResizeLastWriteTimeToCreationTime { get; set; }
[Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; }
[Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; }
[Display(Name = "Load Or Create Then Save Directroy Distance Results"), Required] public bool? LoadOrCreateThenSaveDirectoryDistanceResults { get; set; }
[Display(Name = "Load Or Create Then Save Distance Results"), Required] public bool? LoadOrCreateThenSaveDistanceResults { get; set; }
[Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public bool? LoadOrCreateThenSaveImageFacesResults { get; set; }
[Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; }
[Display(Name = "Location Confidence Factor"), Required] public int? LocationConfidenceFactor { get; set; }
[Display(Name = "Mapped Max Index"), Required] public int? MappedMaxIndex { get; set; }
[Display(Name = "Max Items In Distance Collection"), Required] public int? MaxItemsInDistanceCollection { get; set; }
[Display(Name = "Mixed Year Relative Paths"), Required] public string[] MixedYearRelativePaths { get; set; }
[Display(Name = "Model Directory"), Required] public string ModelDirectory { get; set; }
[Display(Name = "Model Name"), Required] public string ModelName { get; set; }
[Display(Name = "Num Jitters"), Required] public int? NumJitters { get; set; }
[Display(Name = "Output Extension"), Required] public string OutputExtension { get; set; }
[Display(Name = "Output Quality"), Required] public int? OutputQuality { get; set; }
[Display(Name = "Output Resolutions"), Required] public string[] OutputResolutions { get; set; }
[Display(Name = "Override For Face Images"), Required] public bool? OverrideForFaceImages { get; set; }
[Display(Name = "Override For Face Landmark Images"), Required] public bool? OverrideForFaceLandmarkImages { get; set; }
[Display(Name = "Override For Resize Images"), Required] public bool? OverrideForResizeImages { get; set; }
[Display(Name = "Padding Loops"), Required] public int? PaddingLoops { get; set; }
[Display(Name = "Predictor Model Name"), Required] public string PredictorModelName { get; set; }
[Display(Name = "Properties Changed For Distance"), Required] public bool? PropertiesChangedForDistance { get; set; }
[Display(Name = "Properties Changed For Faces"), Required] public bool? PropertiesChangedForFaces { get; set; }
[Display(Name = "Properties Changed For Index"), Required] public bool? PropertiesChangedForIndex { get; set; }
[Display(Name = "Properties Changed For Metadata"), Required] public bool? PropertiesChangedForMetadata { get; set; }
[Display(Name = "Properties Changed For Resize"), Required] public bool? PropertiesChangedForResize { get; set; }
[Display(Name = "Property Configuration"), Required] public Property.Models.Configuration? PropertyConfiguration { get; set; }
[Display(Name = "Reverse"), Required] public bool? Reverse { get; set; }
[Display(Name = "Save Face Landmark For Output Resolutions"), Required] public string[] SaveFaceLandmarkForOutputResolutions { get; set; }
[Display(Name = "Save Full Year Of Random Files"), Required] public bool? SaveFullYearOfRandomFiles { get; set; }
[Display(Name = "Save Resized Subfiles"), Required] public bool? SaveResizedSubfiles { get; set; }
[Display(Name = "Search for Abandoned Files"), Required] public bool? SearchForAbandonedFilesFull { get; set; }
[Display(Name = "Skip Search"), Required] public bool? SkipSearch { get; set; }
[Display(Name = "Test Distance Results"), Required] public bool? TestDistanceResults { get; set; }
[Display(Name = "Valid Resolutions"), Required] public string[] ValidResolutions { get; set; }
public Configuration()
{
CheckJsonForDistanceResults = null;
CrossDirectoryMaxItemsInDistanceCollection = null;
DistanceFactor = null;
ForceMetadataLastWriteTimeToCreationTime = null;
ForceResizeLastWriteTimeToCreationTime = null;
IgnoreExtensions = Array.Empty<string>();
IgnoreRelativePaths = Array.Empty<string>();
LoadOrCreateThenSaveDirectoryDistanceResults = null;
LoadOrCreateThenSaveDistanceResults = null;
LoadOrCreateThenSaveImageFacesResults = null;
LoadOrCreateThenSaveIndex = null;
LocationConfidenceFactor = null;
MappedMaxIndex = null;
MaxItemsInDistanceCollection = null;
MixedYearRelativePaths = Array.Empty<string>();
ModelDirectory = string.Empty;
ModelName = string.Empty;
NumJitters = null;
OutputExtension = string.Empty;
OutputQuality = null;
OutputResolutions = Array.Empty<string>();
OverrideForFaceImages = null;
OverrideForFaceLandmarkImages = null;
OverrideForResizeImages = null;
PaddingLoops = null;
PredictorModelName = string.Empty;
PropertiesChangedForDistance = null;
PropertiesChangedForFaces = null;
PropertiesChangedForIndex = null;
PropertiesChangedForMetadata = null;
PropertiesChangedForResize = null;
Reverse = null;
SaveFaceLandmarkForOutputResolutions = Array.Empty<string>();
SaveFullYearOfRandomFiles = null;
SaveResizedSubfiles = null;
SearchForAbandonedFilesFull = null;
SkipSearch = null;
TestDistanceResults = null;
ValidResolutions = Array.Empty<string>();
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,145 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Instance.Models;
public class Configuration
{
protected readonly bool? _CheckJsonForDistanceResults;
protected readonly int? _CrossDirectoryMaxItemsInDistanceCollection;
protected readonly int? _DistanceFactor;
protected readonly bool? _ForceMetadataLastWriteTimeToCreationTime;
protected readonly bool? _ForceResizeLastWriteTimeToCreationTime;
protected readonly string[] _IgnoreExtensions;
protected readonly string[] _IgnoreRelativePaths;
protected readonly bool? _LoadOrCreateThenSaveDirectoryDistanceResults;
protected readonly bool? _LoadOrCreateThenSaveDistanceResults;
protected readonly bool? _LoadOrCreateThenSaveImageFacesResults;
protected readonly bool? _LoadOrCreateThenSaveIndex;
protected readonly int? _LocationConfidenceFactor;
protected readonly int? _MappedMaxIndex;
protected readonly int? _MaxItemsInDistanceCollection;
protected readonly string[] _MixedYearRelativePaths;
protected readonly string _ModelDirectory;
protected readonly string _ModelName;
protected readonly int? _NumJitters;
protected readonly string _OutputExtension;
protected readonly int? _OutputQuality;
protected readonly string[] _OutputResolutions;
protected readonly bool? _OverrideForFaceImages;
protected readonly bool? _OverrideForFaceLandmarkImages;
protected readonly bool? _OverrideForResizeImages;
protected readonly int? _PaddingLoops;
protected readonly string _PredictorModelName;
protected readonly bool? _PropertiesChangedForDistance;
protected readonly bool? _PropertiesChangedForFaces;
protected readonly bool? _PropertiesChangedForIndex;
protected readonly bool? _PropertiesChangedForMetadata;
protected readonly bool? _PropertiesChangedForResize;
protected Property.Models.Configuration? _PropertyConfiguration;
protected readonly bool? _Reverse;
protected readonly string[] _SaveFaceLandmarkForOutputResolutions;
protected readonly bool? _SaveFullYearOfRandomFiles;
protected readonly bool? _SaveResizedSubfiles;
protected readonly bool? _SearchForAbandonedFiles;
protected readonly bool? _SkipSearch;
protected readonly bool? _TestDistanceResults;
protected readonly string[] _ValidResolutions;
public bool? CheckJsonForDistanceResults => _CheckJsonForDistanceResults;
public int? CrossDirectoryMaxItemsInDistanceCollection => _CrossDirectoryMaxItemsInDistanceCollection;
public int? DistanceFactor => _DistanceFactor;
public bool? ForceMetadataLastWriteTimeToCreationTime => _ForceMetadataLastWriteTimeToCreationTime;
public bool? ForceResizeLastWriteTimeToCreationTime => _ForceResizeLastWriteTimeToCreationTime;
public string[] IgnoreExtensions => _IgnoreExtensions;
public string[] IgnoreRelativePaths => _IgnoreRelativePaths;
public bool? LoadOrCreateThenSaveDirectoryDistanceResults => _LoadOrCreateThenSaveDirectoryDistanceResults;
public bool? LoadOrCreateThenSaveDistanceResults => _LoadOrCreateThenSaveDistanceResults;
public bool? LoadOrCreateThenSaveImageFacesResults => _LoadOrCreateThenSaveImageFacesResults;
public bool? LoadOrCreateThenSaveIndex => _LoadOrCreateThenSaveIndex;
public int? LocationConfidenceFactor => _LocationConfidenceFactor;
public int? MappedMaxIndex => _MappedMaxIndex;
public int? MaxItemsInDistanceCollection => _MaxItemsInDistanceCollection;
public string[] MixedYearRelativePaths => _MixedYearRelativePaths;
public string ModelDirectory => _ModelDirectory;
public string ModelName => _ModelName;
public int? NumJitters => _NumJitters;
public string OutputExtension => _OutputExtension;
public int? OutputQuality => _OutputQuality;
public string[] OutputResolutions => _OutputResolutions;
public bool? OverrideForFaceImages => _OverrideForFaceImages;
public bool? OverrideForFaceLandmarkImages => _OverrideForFaceLandmarkImages;
public bool? OverrideForResizeImages => _OverrideForResizeImages;
public int? PaddingLoops => _PaddingLoops;
public string PredictorModelName => _PredictorModelName;
public bool? PropertiesChangedForDistance => _PropertiesChangedForDistance;
public bool? PropertiesChangedForFaces => _PropertiesChangedForFaces;
public bool? PropertiesChangedForIndex => _PropertiesChangedForIndex;
public bool? PropertiesChangedForMetadata => _PropertiesChangedForMetadata;
public bool? PropertiesChangedForResize => _PropertiesChangedForResize;
public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration;
public bool? Reverse => _Reverse;
public string[] SaveFaceLandmarkForOutputResolutions => _SaveFaceLandmarkForOutputResolutions;
public bool? SaveFullYearOfRandomFiles => _SaveFullYearOfRandomFiles;
public bool? SaveResizedSubfiles => _SaveResizedSubfiles;
public bool? SearchForAbandonedFilesFull => _SearchForAbandonedFiles;
public bool? SkipSearch => _SkipSearch;
public bool? TestDistanceResults => _TestDistanceResults;
public string[] ValidResolutions => _ValidResolutions;
[JsonConstructor]
public Configuration(bool? checkJsonForDistanceResults, int? crossDirectoryMaxItemsInDistanceCollection, int? distanceFactor, bool? forceMetadataLastWriteTimeToCreationTime, bool? forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, bool? loadOrCreateThenSaveDirectoryDistanceResults, bool? loadOrCreateThenSaveDistanceResults, bool? loadOrCreateThenSaveImageFacesResults, bool? loadOrCreateThenSaveIndex, int? locationConfidenceFactor, int? mappedMaxIndex, int? maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int? numJitters, string outputExtension, int? outputQuality, string[] outputResolutions, bool? overrideForFaceImages, bool? overrideForFaceLandmarkImages, bool? overrideForResizeImages, int? paddingLoops, string predictorModelName, bool? propertiesChangedForDistance, bool? propertiesChangedForFaces, bool? propertiesChangedForIndex, bool? propertiesChangedForMetadata, bool? propertiesChangedForResize, Property.Models.Configuration? propertyConfiguration, bool? reverse, string[] saveFaceLandmarkForOutputResolutions, bool? saveFullYearOfRandomFiles, bool? saveResizedSubfiles, bool? searchForAbandonedFilesFull, bool? skipSearch, bool? testDistanceResults, string[] validResolutions)
{
_CheckJsonForDistanceResults = checkJsonForDistanceResults;
_CrossDirectoryMaxItemsInDistanceCollection = crossDirectoryMaxItemsInDistanceCollection;
_DistanceFactor = distanceFactor;
_ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime;
_ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime;
_IgnoreExtensions = ignoreExtensions;
_IgnoreRelativePaths = ignoreRelativePaths;
_LoadOrCreateThenSaveDirectoryDistanceResults = loadOrCreateThenSaveDirectoryDistanceResults;
_LoadOrCreateThenSaveDistanceResults = loadOrCreateThenSaveDistanceResults;
_LoadOrCreateThenSaveImageFacesResults = loadOrCreateThenSaveImageFacesResults;
_LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex;
_LocationConfidenceFactor = locationConfidenceFactor;
_MappedMaxIndex = mappedMaxIndex;
_MaxItemsInDistanceCollection = maxItemsInDistanceCollection;
_MixedYearRelativePaths = mixedYearRelativePaths;
_ModelDirectory = modelDirectory;
_ModelName = modelName;
_NumJitters = numJitters;
_OutputExtension = outputExtension;
_OutputQuality = outputQuality;
_OutputResolutions = outputResolutions;
_OverrideForFaceImages = overrideForFaceImages;
_OverrideForFaceLandmarkImages = overrideForFaceLandmarkImages;
_OverrideForResizeImages = overrideForResizeImages;
_PaddingLoops = paddingLoops;
_PredictorModelName = predictorModelName;
_PropertiesChangedForDistance = propertiesChangedForDistance;
_PropertiesChangedForFaces = propertiesChangedForFaces;
_PropertiesChangedForIndex = propertiesChangedForIndex;
_PropertiesChangedForMetadata = propertiesChangedForMetadata;
_PropertiesChangedForResize = propertiesChangedForResize;
_PropertyConfiguration = propertyConfiguration;
_Reverse = reverse;
_SaveFaceLandmarkForOutputResolutions = saveFaceLandmarkForOutputResolutions;
_SaveFullYearOfRandomFiles = saveFullYearOfRandomFiles;
_SaveResizedSubfiles = saveResizedSubfiles;
_SearchForAbandonedFiles = searchForAbandonedFilesFull;
_SkipSearch = skipSearch;
_TestDistanceResults = testDistanceResults;
_ValidResolutions = validResolutions;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration;
public void Update() => _PropertyConfiguration?.Update();
}

View File

@ -0,0 +1,40 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace View_by_Distance.Instance.Models.Stateless;
public abstract class AppSettings
{
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
namespace View_by_Distance.Instance.Models.Stateless;
public abstract class Configuration
{
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory, Property.Models.Configuration propertyConfiguration)
{
Models.Configuration? result;
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Binder.Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
Binder.Configuration configuration = configurationSection.Get<Binder.Configuration>();
string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.Configuration>(json);
if (result is null)
throw new Exception(json);
string jsonThis = result.ToString();
result.Set(propertyConfiguration);
result.Update();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Instance.Models.Stateless;
public static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -0,0 +1,79 @@
using System.Text.Json;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Instance.Models;
/// <summary>
// ?
/// </summary>
internal class A2_People
{
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
internal A2_People(Configuration configuration)
{
_Configuration = configuration;
_Log = Serilog.Log.ForContext<A2_People>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
internal void WriteAllText(Property.Models.Configuration configuration, string outputResolution, List<G2_Identify> identifiedCollection)
{
string key;
string json;
string jsonFile;
FileInfo fileInfo;
string[] segments;
string directoryFullName;
Dictionary<string, List<G2_Identify>> keyValuePairs = new();
string hPeopleCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People), "[]");
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
foreach (G2_Identify identified in identifiedCollection)
{
fileInfo = new FileInfo(string.Concat(aPropertySingletonDirectory, identified.RelativePath));
if (fileInfo?.Directory is null || !fileInfo.Directory.Exists || fileInfo.Exists)
continue;
key = string.Concat(identified.ParentDirectoryName, '|', identified.Person);
if (!keyValuePairs.ContainsKey(key))
keyValuePairs.Add(key, new List<G2_Identify>());
keyValuePairs[key].Add(identified);
}
foreach (KeyValuePair<string, List<G2_Identify>> keyValuePair in keyValuePairs)
{
segments = keyValuePair.Key.Split('|');
directoryFullName = Path.Combine(hPeopleCollectionDirectory, segments[0]);
if (!Directory.Exists(directoryFullName))
_ = Directory.CreateDirectory(directoryFullName);
jsonFile = Path.Combine(directoryFullName, $"{segments[1]}.json");
json = JsonSerializer.Serialize(keyValuePair.Value, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, compareBeforeWrite: true))
continue;
}
}
internal Person[] GetPeople(Property.Models.Configuration configuration)
{
Person[] results;
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string rootDirectory = _Configuration.PropertyConfiguration.RootDirectory;
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People));
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory));
if (rootResultsDirectory is null)
throw new Exception();
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
results = Shared.Models.Stateless.Methods.IPerson.GetPeople(storage);
return results.ToArray();
}
}

View File

@ -0,0 +1,161 @@
using FaceRecognitionDotNet;
using System.Drawing;
using System.Text.Json;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
namespace View_by_Distance.Instance.Models;
/// <summary>
// *.png
/// </summary>
internal class D2_FaceLandmarks
{
internal List<string> AngleBracketCollection { get; }
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
internal D2_FaceLandmarks(Configuration configuration)
{
_Configuration = configuration;
AngleBracketCollection = new List<string>();
_Log = Serilog.Log.ForContext<D2_FaceLandmarks>();
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
#pragma warning disable CA1416
private static Bitmap RotateBitmap(System.Drawing.Image image, float angle)
{
Bitmap result;
Bitmap bitmap = new(image);
result = D_Face.RotateBitmap(bitmap, angle);
if (bitmap is not null)
bitmap.Dispose();
return result;
}
private static void SaveFaceLandmarkImages(List<D_Face> faceCollections, List<string[]> imageFiles, int pointSize, FileInfo resizedFileInfo)
{
int x;
int y;
D_Face face;
int width;
int height;
string imageFileFullName;
Bitmap rotated;
string rotatedImageFileFullName;
Shared.Models.FacePoint[] facePoints;
for (int i = 0; i < faceCollections.Count; i++)
{
if (!faceCollections[i].Populated)
continue;
face = faceCollections[i];
imageFileFullName = imageFiles[i][0];
rotatedImageFileFullName = imageFiles[i][1];
try
{
using (System.Drawing.Image image = System.Drawing.Image.FromFile(resizedFileInfo.FullName))
{
using Graphics graphic = Graphics.FromImage(image);
if (face.FaceLandmarks is null || !face.FaceLandmarks.Any())
{
width = face.Location.Right - face.Location.Left;
height = face.Location.Bottom - face.Location.Top;
graphic.DrawEllipse(Pens.Red, face.Location.Left, face.Location.Top, width, height);
}
else
{
foreach (KeyValuePair<string, Shared.Models.FacePoint[]> keyValuePair in face.FaceLandmarks)
{
facePoints = keyValuePair.Value.ToArray();
foreach (Shared.Models.FacePoint facePoint in facePoints)
graphic.DrawEllipse(Pens.GreenYellow, face.Location.Left + facePoint.X - pointSize, face.Location.Top + facePoint.Y - pointSize, pointSize * 2, pointSize * 2);
if (keyValuePair.Key == FacePart.Chin.ToString())
continue;
if (facePoints.Length < 3)
continue;
x = (int)(from l in facePoints select l.X).Average();
y = (int)(from l in facePoints select l.Y).Average();
graphic.DrawEllipse(Pens.Purple, face.Location.Left + x - pointSize, face.Location.Top + y - pointSize, pointSize * 2, pointSize * 2);
}
}
image.Save(imageFileFullName, System.Drawing.Imaging.ImageFormat.Png);
}
if (face.α.HasValue)
{
using System.Drawing.Image image = System.Drawing.Image.FromFile(resizedFileInfo.FullName);
rotated = RotateBitmap(image, (float)face.α.Value);
if (rotated is not null)
{
rotated.Save(rotatedImageFileFullName, System.Drawing.Imaging.ImageFormat.Png);
rotated.Dispose();
}
}
}
catch (Exception) { }
}
}
#pragma warning restore CA1416
internal void SaveFaceLandmarkImages(List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string relativePath, string fileNameWithoutExtension, FileInfo resizedFileInfo, List<D_Face> faceCollections)
{
FileInfo fileInfo;
bool check = false;
string parentCheck;
const int pointSize = 2;
FileInfo rotatedFileInfo;
long ticks = DateTime.Now.Ticks;
List<string[]> imageFiles = new();
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), fileNameWithoutExtension);
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
if (!Directory.Exists(facesDirectory))
_ = Directory.CreateDirectory(facesDirectory);
for (int i = 0; i < faceCollections.Count; i++)
{
if (!faceCollections[i].Populated)
{
imageFiles.Add(Array.Empty<string>());
continue;
}
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{i} - {fileNameWithoutExtension}.png"));
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
File.Delete(parentCheck);
}
if (string.IsNullOrEmpty(fileInfo.DirectoryName))
continue;
rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, string.Concat(Path.GetFileNameWithoutExtension(fileInfo.FullName), " - ", i, " - R", Path.GetExtension(fileInfo.FullName))));
imageFiles.Add(new string[] { fileInfo.FullName, rotatedFileInfo.FullName });
if (check)
continue;
if (_Configuration.OverrideForFaceLandmarkImages is null)
check = false;
else if (_Configuration.OverrideForFaceLandmarkImages.Value)
check = true;
else if (!fileInfo.Exists)
check = true;
else if (!rotatedFileInfo.Exists)
check = true;
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
check = true;
}
if (check)
SaveFaceLandmarkImages(faceCollections, imageFiles, pointSize, resizedFileInfo);
}
}

498
Instance/Models/_D_Face.cs Normal file
View File

@ -0,0 +1,498 @@
using FaceRecognitionDotNet;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text.Json;
using System.Text.Json.Serialization;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Instance.Models;
/// <summary>
// List<D_Faces>
/// </summary>
public class D_Face : Shared.Models.Properties.IFace, IFace
{
internal List<string> AngleBracketCollection { get; }
private readonly Model _Model;
private readonly string _ArgZero;
private readonly Serilog.ILogger? _Log;
private readonly ModelParameter _ModelParameter;
private readonly PredictorModel _PredictorModel;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
protected double? _Α;
protected DateTime _DateTime;
protected Shared.Models.FaceEncoding _FaceEncoding;
protected Dictionary<string, Shared.Models.FacePoint[]> _FaceLandmarks;
protected Shared.Models.Location _Location;
protected int? _LocationIndex;
protected OutputResolution _OutputResolution;
protected bool _Populated;
protected string _RelativePath;
public double? α => _Α;
public DateTime DateTime => _DateTime;
public Shared.Models.FaceEncoding FaceEncoding => _FaceEncoding;
public Dictionary<string, Shared.Models.FacePoint[]> FaceLandmarks => _FaceLandmarks;
public OutputResolution OutputResolution => _OutputResolution;
public Shared.Models.Location Location => _Location;
public int? LocationIndex => _LocationIndex;
public bool Populated => _Populated;
public string RelativePath => _RelativePath;
#nullable disable
[JsonConstructor]
public D_Face(double? α, DateTime dateTime, Shared.Models.FaceEncoding faceEncoding, Dictionary<string, Shared.Models.FacePoint[]> faceLandmarks, Shared.Models.Location location, int? locationIndex, OutputResolution outputResolution, bool populated, string relativePath)
{
_Α = α;
_DateTime = dateTime;
_FaceEncoding = faceEncoding;
_FaceLandmarks = faceLandmarks;
_Location = location;
_LocationIndex = locationIndex;
_OutputResolution = outputResolution;
_Populated = populated;
_RelativePath = relativePath;
}
internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel)
{
_Model = model;
_ArgZero = argZero;
_Configuration = configuration;
_ModelParameter = modelParameter;
_PredictorModel = predictorModel;
AngleBracketCollection = new List<string>();
_Log = Serilog.Log.ForContext<D_Face>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
}
private D_Face(Shared.Models.Location location)
{
_Α = α;
_DateTime = DateTime.MinValue;
_FaceEncoding = null;
_FaceLandmarks = null;
_OutputResolution = null;
_Location = location;
_LocationIndex = null;
_Populated = false;
_RelativePath = string.Empty;
}
private D_Face()
{
_Α = α;
_DateTime = DateTime.MinValue;
_FaceEncoding = null;
_FaceLandmarks = null;
_OutputResolution = null;
_Location = null;
_LocationIndex = null;
_Populated = false;
_RelativePath = string.Empty;
}
private D_Face(A_Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string relativePath, int? i, Shared.Models.Location location)
{
DateTime?[] dateTimes;
dateTimes = new DateTime?[] { property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp };
_DateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
_FaceLandmarks = new Dictionary<string, Shared.Models.FacePoint[]>();
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
_Location = location;
_LocationIndex = i;
_Populated = false;
_RelativePath = relativePath;
}
private D_Face(int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, Shared.Models.Properties.IFace face)
{
_Α = face.α;
_DateTime = face.DateTime;
_FaceEncoding = face.FaceEncoding;
_FaceLandmarks = face.FaceLandmarks;
_OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
_Location = face.Location;
_LocationIndex = face.LocationIndex;
_Populated = face.Populated;
_RelativePath = face.RelativePath;
}
private static void GetPointBounds(PointF[] points, out float xmin, out float xmax, out float ymin, out float ymax)
{
xmin = points[0].X;
xmax = xmin;
ymin = points[0].Y;
ymax = ymin;
foreach (PointF point in points)
{
if (xmin > point.X)
xmin = point.X;
if (xmax < point.X)
xmax = point.X;
if (ymin > point.Y)
ymin = point.Y;
if (ymax < point.Y)
ymax = point.Y;
}
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
#pragma warning disable CA1416
internal static Bitmap RotateBitmap(Bitmap bitmap, float angle)
{
Bitmap result;
#if Linux
throw new Exception("Built on Linux!");
#elif OSX
throw new Exception("Built on macOS!");
#elif Windows
// Make a Matrix to represent rotation
// by this angle.
Matrix rotate_at_origin = new();
rotate_at_origin.Rotate(angle);
// Rotate the image's corners to see how big
// it will be after rotation.
PointF[] points =
{
new PointF(0, 0),
new PointF(bitmap.Width, 0),
new PointF(bitmap.Width, bitmap.Height),
new PointF(0, bitmap.Height),
};
rotate_at_origin.TransformPoints(points);
float xmin, xmax, ymin, ymax;
GetPointBounds(points, out xmin, out xmax, out ymin, out ymax);
// Make a bitmap to hold the rotated result.
int wid = (int)Math.Round(xmax - xmin);
int hgt = (int)Math.Round(ymax - ymin);
result = new Bitmap(wid, hgt);
// Create the real rotation transformation.
Matrix rotate_at_center = new();
rotate_at_center.RotateAt(angle,
new PointF(wid / 2f, hgt / 2f));
// Draw the image onto the new bitmap rotated.
using (Graphics gr = Graphics.FromImage(result))
{
// Use smooth image interpolation.
gr.InterpolationMode = InterpolationMode.High;
// Clear with the color in the image's upper left corner.
gr.Clear(bitmap.GetPixel(0, 0));
// For debugging. (It's easier to see the background.)
// gr.Clear(Color.LightBlue);
// Set up the transformation to rotate.
gr.Transform = rotate_at_center;
// Draw the image centered on the bitmap.
int x = (wid - bitmap.Width) / 2;
int y = (hgt - bitmap.Height) / 2;
gr.DrawImage(bitmap, x, y);
}
#endif
// Return the result bitmap.
return result;
}
private static void SaveFaces(List<D_Face> faceCollection, FileInfo resizedFileInfo, List<string> imageFiles)
{
int width;
int height;
Graphics graphics;
Rectangle rectangle;
Bitmap preRotated;
Shared.Models.Location location;
using Bitmap source = new(resizedFileInfo.FullName);
for (int i = 0; i < faceCollection.Count; i++)
{
if (!faceCollection[i].Populated || faceCollection[i]?.Location is null)
continue;
location = new Shared.Models.Location(faceCollection[i].Location.Confidence,
faceCollection[i].Location.Bottom,
faceCollection[i].Location.Left,
faceCollection[i].Location.Right,
faceCollection[i].Location.Top);
width = location.Right - location.Left;
height = location.Bottom - location.Top;
rectangle = new Rectangle(location.Left, location.Top, width, height);
using (preRotated = new(width, height))
{
using (graphics = Graphics.FromImage(preRotated))
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
preRotated.Save(imageFiles[i], System.Drawing.Imaging.ImageFormat.Png);
}
}
}
private List<D_Face> GetFaces(FileInfo resizedFileInfo, string relativePath, string fileNameWithoutExtension, A_Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string facesDirectory)
{
List<D_Face> results = new();
if (_Configuration.PaddingLoops is null)
throw new Exception();
if (_Configuration.NumJitters is null)
throw new Exception();
FaceRecognitionDotNet.Location[] locations;
FaceRecognitionDotNet.Image unknownImage = null;
if (resizedFileInfo.Exists)
{
try
{ unknownImage = FaceRecognition.LoadImageFile(resizedFileInfo.FullName); }
catch (Exception) { }
}
if (unknownImage is null)
results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i: null, location: null));
else
{
FaceRecognition faceRecognition = FaceRecognition.Create(_ModelParameter);
locations = faceRecognition.FaceLocations(unknownImage, numberOfTimesToUpsample: 1, _Model).ToArray();
if (!locations.Any())
results.Add(new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i: null, location: null));
else
{
double? α;
int width;
int height;
int padding;
int leftEyeX;
int leftEyeY;
int rightEyeX;
int rightEyeY;
string faceFile;
Graphics graphics;
D_Face face = null;
Rectangle rectangle;
double[] rawEncoding;
Bitmap rotated;
Bitmap preRotated;
FaceRecognitionDotNet.Image knownImage;
FaceRecognitionDotNet.Image rotatedImage;
Shared.Models.Location location;
FaceRecognitionDotNet.FaceEncoding[] faceEncodings;
IEnumerable<FaceRecognitionDotNet.FacePoint> facePoints;
Shared.Models.FaceEncoding faceEncoding;
IDictionary<FacePart, IEnumerable<FaceRecognitionDotNet.FacePoint>>[] faceLandmarks;
using Bitmap source = unknownImage.ToBitmap();
padding = (int)((source.Width + source.Height) / 2 * .01);
for (int i = 0; i < locations.Length; i++)
{
for (int p = 0; p <= _Configuration.PaddingLoops.Value; p++)
{
//Location(double confidence, int bottom, int left, int right, int top)
location = new(locations[i].Confidence,
locations[i].Bottom + (padding * p),
locations[i].Left - (padding * p),
locations[i].Right + (padding * p),
locations[i].Top - (padding * p));
face = new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i, location);
width = location.Right - location.Left;
height = location.Bottom - location.Top;
rectangle = new Rectangle(location.Left, location.Top, width, height);
using (preRotated = new Bitmap(width, height))
{
using (graphics = Graphics.FromImage(preRotated))
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
// source.Save(Path.Combine(_Configuration.RootDirectory, "source.jpg"));
// preRotated.Save(Path.Combine(_Configuration.RootDirectory, $"{p} - preRotated.jpg"));
using (knownImage = FaceRecognition.LoadImage(preRotated))
faceLandmarks = faceRecognition.FaceLandmark(knownImage, faceLocations: null, _PredictorModel, _Model).ToArray();
if (faceLandmarks.Length == 0 && p < _Configuration.PaddingLoops.Value)
continue;
else if (faceLandmarks.Length != 1)
continue;
foreach (KeyValuePair<FacePart, IEnumerable<FaceRecognitionDotNet.FacePoint>> keyValuePair in faceLandmarks[0])
face.FaceLandmarks.Add(keyValuePair.Key.ToString(), (from l in keyValuePair.Value select new Shared.Models.FacePoint(l.Index, l.Point.X, l.Point.Y)).ToArray());
if (!faceLandmarks[0].ContainsKey(FacePart.LeftEye) || !faceLandmarks[0].ContainsKey(FacePart.RightEye))
continue;
facePoints = faceLandmarks[0][FacePart.LeftEye];
leftEyeX = (int)(from l in facePoints select l.Point.X).Average();
leftEyeY = (int)(from l in facePoints select l.Point.Y).Average();
facePoints = faceLandmarks[0][FacePart.RightEye];
rightEyeX = (int)(from l in facePoints select l.Point.X).Average();
rightEyeY = (int)(from l in facePoints select l.Point.Y).Average();
α = Shared.Models.Stateless.Methods.IFace.Getα(rightEyeX, leftEyeX, rightEyeY, leftEyeY);
using (rotated = RotateBitmap(preRotated, (float)α.Value))
{
// rotated.Save(Path.Combine(_Configuration.RootDirectory, $"{p} - rotated.jpg"));
using (rotatedImage = FaceRecognition.LoadImage(rotated))
faceEncodings = faceRecognition.FaceEncodings(rotatedImage, knownFaceLocation: null, _Configuration.NumJitters.Value, _PredictorModel, _Model).ToArray();
if (faceEncodings.Length == 0 && p < _Configuration.PaddingLoops.Value)
continue;
else if (faceEncodings.Length != 1)
continue;
rawEncoding = faceEncodings[0].GetRawEncoding();
faceEncoding = new(rawEncoding, faceEncodings[0].Size);
face.Update(α, faceEncoding, populated: true);
}
faceFile = Path.Combine(facesDirectory, $"{i} - {fileNameWithoutExtension}.png");
preRotated.Save(faceFile, System.Drawing.Imaging.ImageFormat.Png);
results.Add(face);
}
if (face.Populated)
break;
}
if (face is null || !face.Populated)
{
location = new(locations[i].Confidence,
locations[i].Bottom,
locations[i].Left,
locations[i].Right,
locations[i].Top);
face = new D_Face(property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, relativePath, i, location);
results.Add(face);
}
}
}
unknownImage.Dispose();
faceRecognition.Dispose();
}
if (!results.Any())
throw new Exception();
return results;
}
#pragma warning restore CA1416
private void Update(double? α, Shared.Models.FaceEncoding faceEncoding, bool populated)
{
_Α = α;
_FaceEncoding = faceEncoding;
_Populated = populated;
}
internal List<D_Face> GetFaces(Property.Models.Configuration configuration, string outputResolution, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string relativePath, string fileNameWithoutExtension, A_Property property, FileInfo resizedFileInfo, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation)
{
List<D_Face> results;
if (_Configuration.PropertiesChangedForFaces is null)
throw new Exception();
string json;
D_Face face;
bool checkForOutputResolutionChange = false;
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) };
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), fileNameWithoutExtension);
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "[]"), $"{fileNameWithoutExtension}.json"));
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
File.Delete(parentCheck);
}
if (!Directory.Exists(facesDirectory))
_ = Directory.CreateDirectory(facesDirectory);
if (_Configuration.PropertiesChangedForFaces.Value)
results = null;
else if (!fileInfo.Exists)
results = null;
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
results = null;
else
{
json = Shared.Models.Stateless.Methods.IFace.GetJson(fileInfo.FullName);
try
{
results = JsonSerializer.Deserialize<List<D_Face>>(json);
for (int i = 0; i < results.Count; i++)
{
face = results[i];
if (face.OutputResolution is not null)
continue;
if (!checkForOutputResolutionChange)
checkForOutputResolutionChange = true;
results[i] = new(outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, face);
}
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), fileInfo.LastWriteTime));
}
catch (Exception)
{
results = null;
parseExceptions.Add(nameof(D_Face));
}
}
if (results is not null && checkForOutputResolutionChange)
{
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions);
if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true))
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
}
else if (results is null)
{
results = GetFaces(resizedFileInfo, relativePath, fileNameWithoutExtension, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, facesDirectory);
json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions);
if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(D_Face), DateTime.Now));
}
return results;
}
internal void SaveFaces(Property.Models.Configuration configuration, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string relativePath, string fileNameWithoutExtension, FileInfo resizedFileInfo, List<D_Face> faceCollection)
{
if (_Configuration.OverrideForFaceImages is null)
throw new Exception();
FileInfo fileInfo;
bool check = false;
string parentCheck;
List<string> imageFiles = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) };
string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), fileNameWithoutExtension);
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
bool facesDirectoryExisted = Directory.Exists(facesDirectory);
if (!facesDirectoryExisted)
_ = Directory.CreateDirectory(facesDirectory);
for (int i = 0; i < faceCollection.Count; i++)
{
if (!faceCollection[i].Populated || faceCollection[i]?.Location is null)
{
imageFiles.Add(string.Empty);
continue;
}
fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{i} - {fileNameWithoutExtension}.png"));
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
File.Delete(parentCheck);
}
imageFiles.Add(fileInfo.FullName);
if (_Configuration.OverrideForFaceImages.Value)
check = true;
else if (!fileInfo.Exists)
check = true;
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
check = true;
}
if (check)
SaveFaces(faceCollection, resizedFileInfo, imageFiles);
}
double Shared.Models.Stateless.Methods.IFace.TestStatic_Getα(int x1, int x2, int y1, int y2) => throw new NotImplementedException();
string Shared.Models.Stateless.Methods.IFace.TestStatic_GetJson(string jsonFileFullName) => throw new NotImplementedException();
Face Shared.Models.Stateless.Methods.IFace.TestStatic_GetFace(string jsonFileFullName) => throw new NotImplementedException();
Face[] Shared.Models.Stateless.Methods.IFace.TestStatic_GetFaces(string jsonFileFullName) => throw new NotImplementedException();
}

View File

@ -0,0 +1,230 @@
using System.Text.Json;
using View_by_Distance.Instance.Models.Stateless;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Instance.Models;
/// <summary>
// N/A
/// </summary>
internal class E2_Navigate
{
private readonly string _ArgZero;
private readonly E3_Rename _Rename;
private readonly IConsole _Console;
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
internal E2_Navigate(IConsole console, Configuration configuration, string argZero)
{
_Console = console;
_ArgZero = argZero;
_Configuration = configuration;
_Rename = new E3_Rename(configuration);
_Log = Serilog.Log.ForContext<E2_Navigate>();
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private void DisplayTags(Property.Models.Configuration configuration, string outputResolution, string[] directories, Dictionary<ConsoleKey, int> directoryKeyValuePairs, string[] files, Dictionary<ConsoleKey, int> fileKeyValuePairs)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
bool all = false;
FileSystem fileSystem;
string requestPath = "/RootResultsDirectory";
string? rootResultsDirectory = Path.GetDirectoryName(Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, nameof(B_Metadata)));
if (string.IsNullOrEmpty(rootResultsDirectory))
throw new Exception();
string rootResultsDirectoryAbsoluteUri = new Uri(rootResultsDirectory).AbsoluteUri;
string dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
string cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()");
string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
(string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple = new(rootResultsDirectoryAbsoluteUri, cResizeContentDirectory, dFacesContentDirectory, eDistanceCollectionDirectory);
List<FileSystem> fileSystemCollection = Shared.Models.Stateless.Methods.IFileSystem.GetFileSystemCollection(requestPath, tuple, directories, files, all);
Queue<FileSystem> queue = new(fileSystemCollection);
foreach (KeyValuePair<ConsoleKey, int> element in directoryKeyValuePairs)
{
fileSystem = queue.Dequeue();
_Log.Warn(string.Concat(element.Key, " - D) ", " <", fileSystem.Display, ">"));
// _Log.Info(string.Join(Environment.NewLine, from l in fileSystem where !string.IsNullOrEmpty(l) select l));
_Log.Info(string.Empty);
}
foreach (KeyValuePair<ConsoleKey, int> element in fileKeyValuePairs)
{
fileSystem = queue.Dequeue();
_Log.Warn(string.Concat(element.Key, " - F) [", fileSystem.Display, '}'));
// _Log.Info(string.Join(Environment.NewLine, from l in fileSystem where !string.IsNullOrEmpty(l) select l));
_Log.Info(string.Empty);
}
}
private void DisplayFaces(Property.Models.Configuration configuration, string outputResolution, string selectedFileFullName)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
string requestPath = "/RootResultsDirectory";
string? rootResultsDirectory = Path.GetDirectoryName(Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, nameof(B_Metadata)));
if (string.IsNullOrEmpty(rootResultsDirectory))
throw new Exception();
string rootResultsDirectoryAbsoluteUri = new Uri(rootResultsDirectory).AbsoluteUri;
string dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
string cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()");
string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
(string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple = new(rootResultsDirectoryAbsoluteUri, cResizeContentDirectory, dFacesContentDirectory, eDistanceCollectionDirectory);
FaceFileSystem[] faceFileSystemCollection = Shared.Models.Stateless.Methods.IFaceFileSystem.GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName);
for (int i = 0; i < faceFileSystemCollection.Length; i++)
{
_Log.Warn(string.Concat(i, " - F) [", faceFileSystemCollection[i].Display, '}'));
// _Log.Info(string.Join(Environment.NewLine, from l in fileSystemCollection[i] where !string.IsNullOrEmpty(l) select l));
_Log.Info(string.Empty);
}
// }
}
private string Rename(Property.Models.Configuration configuration, string subSourceDirectory)
{
string result;
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
_Log.Warn(string.Concat("What is the new name for [", Path.GetFileName(subSourceDirectory), "]<", subSourceDirectory, ">?"));
string? newDirectoryName = _Console.ReadLine();
_Log.Warn("Are you sure y[es] || n[o]?");
if (string.IsNullOrEmpty(newDirectoryName) || _Console.ReadKey() != ConsoleKey.Y)
{
_Log.Warn(string.Empty);
_Log.Warn("No changes made.");
result = subSourceDirectory;
}
else
{
_Log.Warn(string.Empty);
string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
string relativePath = Property.Models.Stateless.IPath.GetRelativePath(subSourceDirectory, eDistanceCollectionDirectory.Length);
if (relativePath.Length == 1)
throw new Exception();
if (Directory.Exists(Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName)))
{
_Log.Warn("\"To\" directory already exits!");
result = subSourceDirectory;
}
else
{
_Rename.DirectoryRename(configuration, relativePath, newDirectoryName);
_Log.Warn("Renamed...");
string? directoryName = Path.GetDirectoryName(subSourceDirectory);
if (string.IsNullOrEmpty(directoryName))
throw new Exception();
result = Path.Combine(directoryName, newDirectoryName);
}
}
return result;
}
internal void Navigate(Property.Models.Configuration configuration, string outputResolution)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
string[] subFiles;
ConsoleKey consoleKey;
string[] subDirectories;
string selectedFileFullName;
string rootDirectory = string.Empty;
string? subSourceDirectory = string.Empty;
Dictionary<ConsoleKey, int> fileKeyValuePairs = new();
Dictionary<ConsoleKey, int> directoryKeyValuePairs = new();
string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), _Configuration.OutputResolutions[0], includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
if (!Directory.Exists(eDistanceCollectionDirectory))
_ = Directory.CreateDirectory(eDistanceCollectionDirectory);
for (int z = 0; z < int.MaxValue; z++)
{
if (string.IsNullOrEmpty(subSourceDirectory))
{
rootDirectory = eDistanceCollectionDirectory;
subSourceDirectory = rootDirectory;
}
subFiles = Directory.GetFiles(subSourceDirectory, "*.json", SearchOption.TopDirectoryOnly);
subDirectories = Directory.GetDirectories(subSourceDirectory, "*", SearchOption.TopDirectoryOnly);
directoryKeyValuePairs.Clear();
for (int i = (int)ConsoleKey.A; i < (subDirectories.Length + (int)ConsoleKey.A) && i <= (int)ConsoleKey.RightWindows; i++)
directoryKeyValuePairs.Add((ConsoleKey)i, i - (int)ConsoleKey.A);
fileKeyValuePairs.Clear();
for (int i = (int)ConsoleKey.A + subDirectories.Length; i < (subFiles.Length + (int)ConsoleKey.A + subDirectories.Length) && i <= (int)ConsoleKey.RightWindows; i++)
fileKeyValuePairs.Add((ConsoleKey)i, i - (int)ConsoleKey.A);
_Log.Warn("");
DisplayTags(configuration, outputResolution, subDirectories, directoryKeyValuePairs, subFiles, fileKeyValuePairs);
_Log.Warn(string.Empty);
_Log.Warn(string.Empty);
_Log.Warn(string.Empty);
_Log.Warn("Select a file system object. Enter \"Backspace\" to go up a directory, \"F2\" to rename and \"Esc\" to end navigation.");
consoleKey = _Console.ReadKey();
_Log.Warn(string.Empty);
if (consoleKey == ConsoleKey.Escape)
break;
if (consoleKey == ConsoleKey.F2)
{
if (subSourceDirectory == rootDirectory)
{
_Log.Warn("Root directory can not be renamed! Try again.");
continue;
}
else
{
subSourceDirectory = Rename(configuration, subSourceDirectory);
continue;
}
}
else if (consoleKey is ConsoleKey.Backspace or ConsoleKey.LeftArrow)
{
if (subSourceDirectory != rootDirectory)
subSourceDirectory = Path.GetDirectoryName(subSourceDirectory);
else
{
_Log.Warn("At root directory. Try again.");
continue;
}
}
else if (directoryKeyValuePairs.ContainsKey(consoleKey))
{
subSourceDirectory = subDirectories[directoryKeyValuePairs[consoleKey]];
_Log.Warn(string.Concat(">>> [", Path.GetFileName(subSourceDirectory), "]<", subSourceDirectory, ">?"));
continue;
}
else
{
if (!fileKeyValuePairs.ContainsKey(consoleKey))
{
subSourceDirectory = _ArgZero;
_Log.Warn("Invalid selection. Try again.");
continue;
}
else
{
selectedFileFullName = subFiles[fileKeyValuePairs[consoleKey]];
_Log.Warn(string.Concat(">>> [", Path.GetFileName(selectedFileFullName), "]<", selectedFileFullName, ">?"));
DisplayFaces(configuration, outputResolution, selectedFileFullName);
_Log.Warn(string.Empty);
_Log.Warn(string.Empty);
_Log.Warn(string.Empty);
_Log.Warn("Go up a directory? Enter escape end.");
consoleKey = _Console.ReadKey();
if (consoleKey == ConsoleKey.Escape)
break;
subSourceDirectory = Path.GetDirectoryName(subSourceDirectory);
continue;
}
}
}
}
}

View File

@ -0,0 +1,338 @@
using System.Text.Json;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
namespace View_by_Distance.Instance.Models;
/// <summary>
// N/A
/// </summary>
internal class E3_Rename
{
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
internal E3_Rename(Configuration configuration)
{
_Configuration = configuration;
_Log = Serilog.Log.ForContext<G2_Identify>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
internal string[] GetDirectoryRenameCollection(Property.Models.Configuration configuration, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny)
{
List<string> results = new();
bool add;
string to;
string dFacesContentDirectory;
string cResizeContentDirectory;
string dFacesCollectionDirectory;
string cResizeSingletonDirectory;
string eDistanceContentDirectory;
string aPropertySingletonDirectory;
string bMetadataSingletonDirectory;
string eDistanceCollectionDirectory;
string g2IdentifyCollectionDirectory;
string d2FaceLandmarksContentDirectory;
add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath));
bMetadataSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(B_Metadata), "{}");
if (Directory.Exists(bMetadataSingletonDirectory))
{
to = Path.Combine(string.Concat(bMetadataSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
if (Directory.Exists(aPropertySingletonDirectory))
{
to = Path.Combine(string.Concat(aPropertySingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), _Configuration.ValidResolutions[0], includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()");
if (Directory.Exists(cResizeContentDirectory))
{
to = Path.Combine(string.Concat(cResizeContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
foreach (string outputResolution in _Configuration.ValidResolutions)
{
cResizeSingletonDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}");
if (Directory.Exists(cResizeSingletonDirectory))
{
to = Path.Combine(string.Concat(cResizeSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
if (Directory.Exists(dFacesContentDirectory))
{
to = Path.Combine(string.Concat(dFacesContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
if (Directory.Exists(dFacesCollectionDirectory))
{
to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
if (add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution) && Directory.Exists(d2FaceLandmarksContentDirectory))
{
to = Path.Combine(string.Concat(d2FaceLandmarksContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
if (Directory.Exists(eDistanceContentDirectory))
{
to = Path.Combine(string.Concat(eDistanceContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
if (Directory.Exists(eDistanceCollectionDirectory))
{
to = Path.Combine(string.Concat(eDistanceCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
g2IdentifyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]");
if (add && jsonFiles4InfoAny && Directory.Exists(g2IdentifyCollectionDirectory))
{
to = Path.Combine(string.Concat(g2IdentifyCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(to);
}
}
return results.ToArray();
}
internal List<string[]> GetDirectoryRenameCollections(Property.Models.Configuration configuration, string relativePath, string newDirectoryName, bool jsonFiles4InfoAny)
{
List<string[]> results = new();
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
bool add;
string to;
bool exists;
string from;
string dFacesContentDirectory;
string cResizeContentDirectory;
string dFacesCollectionDirectory;
string cResizeSingletonDirectory;
string eDistanceContentDirectory;
string bMetadataSingletonDirectory;
string aPropertySingletonDirectory;
string eDistanceCollectionDirectory;
string g2IdentifyCollectionDirectory;
string d2FaceLandmarksContentDirectory;
if (!string.IsNullOrEmpty(relativePath))
{
from = string.Concat(_Configuration.PropertyConfiguration.RootDirectory, relativePath);
to = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
foreach (string outputResolution in _Configuration.ValidResolutions)
{
add = Directory.Exists(string.Concat(Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()"), relativePath));
bMetadataSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(B_Metadata), "{}");
from = string.Concat(bMetadataSingletonDirectory, relativePath);
exists = Directory.Exists(bMetadataSingletonDirectory);
if (exists)
{
to = Path.Combine(string.Concat(bMetadataSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
from = string.Concat(aPropertySingletonDirectory, relativePath);
exists = Directory.Exists(aPropertySingletonDirectory);
if (exists)
{
to = Path.Combine(string.Concat(aPropertySingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
cResizeContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "()");
from = string.Concat(cResizeContentDirectory, relativePath);
exists = Directory.Exists(cResizeContentDirectory);
if (exists)
{
to = Path.Combine(string.Concat(cResizeContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
cResizeSingletonDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(C_Resize), outputResolution, includeResizeGroup: true, includeModel: false, includePredictorModel: false), "{}");
from = string.Concat(cResizeSingletonDirectory, relativePath);
exists = Directory.Exists(cResizeSingletonDirectory);
if (exists)
{
to = Path.Combine(string.Concat(cResizeSingletonDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
dFacesContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
from = string.Concat(dFacesContentDirectory, relativePath);
exists = Directory.Exists(dFacesContentDirectory);
if (exists)
{
to = Path.Combine(string.Concat(dFacesContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
from = string.Concat(dFacesCollectionDirectory, relativePath);
exists = Directory.Exists(dFacesCollectionDirectory);
if (exists)
{
to = Path.Combine(string.Concat(dFacesCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
d2FaceLandmarksContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D2_FaceLandmarks), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
from = string.Concat(d2FaceLandmarksContentDirectory, relativePath);
exists = Directory.Exists(d2FaceLandmarksContentDirectory);
if (!exists && add && _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution))
results.Add(new string[] { from });
else if (exists)
{
to = Path.Combine(string.Concat(d2FaceLandmarksContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
eDistanceContentDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "()");
from = string.Concat(eDistanceContentDirectory, relativePath);
exists = Directory.Exists(eDistanceContentDirectory);
if (exists)
{
to = Path.Combine(string.Concat(eDistanceContentDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
from = string.Concat(eDistanceCollectionDirectory, relativePath);
exists = Directory.Exists(eDistanceCollectionDirectory);
if (exists)
{
to = Path.Combine(string.Concat(eDistanceCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
g2IdentifyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]");
from = string.Concat(g2IdentifyCollectionDirectory, relativePath);
exists = Directory.Exists(g2IdentifyCollectionDirectory);
if (!exists && add && jsonFiles4InfoAny)
results.Add(new string[] { from });
else if (exists)
{
to = Path.Combine(string.Concat(g2IdentifyCollectionDirectory, Path.GetDirectoryName(relativePath)), newDirectoryName);
results.Add(new string[] { from, to });
}
}
return results;
}
internal void DirectoryRename(Property.Models.Configuration configuration, string relativePath, string newDirectoryName)
{
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string json;
FileInfo current;
FileInfo fileInfo;
string error = "Error";
string target = "Target";
string pending = "Pending";
DirectoryInfo directoryInfo;
IEnumerator<FileInfo> fileInfoCollection;
string oldValue = string.Concat("\"", relativePath);
string oldDirectoryName = Path.GetFileName(relativePath);
string traceFileName = string.Concat(DateTime.Now.Ticks, ".tsv");
string directoryName = Path.GetFileName(_Configuration.PropertyConfiguration.RootDirectory);
string? relativePathParent = Path.GetDirectoryName(relativePath);
if (string.IsNullOrEmpty(relativePathParent))
throw new Exception();
string newValue = string.Concat("\"", Path.Combine(relativePathParent, newDirectoryName));
string e3RenameContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(E3_Rename), "()");
string jsonRootDirectory = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, " - Copied"), string.Concat(directoryName, " - 4) Info"), _Configuration.PropertyConfiguration.DateGroup, "[]");
directoryInfo = new DirectoryInfo(jsonRootDirectory);
if (!directoryInfo.Exists)
directoryInfo.Create();
IEnumerator<FileInfo> fileInfoCollection4 = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator();
bool fileInfoCollection4MoveNext = fileInfoCollection4.MoveNext();
if (!fileInfoCollection4MoveNext)
current = new(string.Empty);
else
current = fileInfoCollection4.Current;
List<string[]> directoryCollections = GetDirectoryRenameCollections(configuration, relativePath, newDirectoryName, fileInfoCollection4MoveNext);
if ((from l in directoryCollections where l.Length != 2 select true).Any())
throw new Exception();
if (!Directory.Exists(e3RenameContentDirectory))
{
_ = Directory.CreateDirectory(e3RenameContentDirectory);
_ = Directory.CreateDirectory(Path.Combine(e3RenameContentDirectory, error));
_ = Directory.CreateDirectory(Path.Combine(e3RenameContentDirectory, target));
_ = Directory.CreateDirectory(Path.Combine(e3RenameContentDirectory, "Test"));
_ = Directory.CreateDirectory(Path.Combine(e3RenameContentDirectory, pending));
}
string fRandomSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(F_Random), "{}");
string[] files = Directory.GetFiles(fRandomSingletonDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
File.Delete(file);
File.WriteAllText(Path.Combine(e3RenameContentDirectory, pending, traceFileName), string.Concat(relativePath, newDirectoryName, Environment.NewLine));
try
{
foreach (string[] directoryCollection in directoryCollections)
{
directoryInfo = new DirectoryInfo(directoryCollection[0]);
if (!directoryInfo.Exists)
continue;
fileInfoCollection = directoryInfo.EnumerateFiles("*.json", SearchOption.AllDirectories).GetEnumerator();
for (int i = 0; i < int.MaxValue; i++)
{
if (fileInfoCollection.MoveNext())
fileInfo = fileInfoCollection.Current;
else if (fileInfoCollection4MoveNext && fileInfoCollection4.MoveNext())
fileInfo = fileInfoCollection4.Current;
else if (fileInfoCollection4MoveNext && current is not null)
{
fileInfo = current;
current = new(string.Empty);
}
else
break;
json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfo.FullName, fileInfo);
if (json.Contains(oldValue))
{
json = json.Replace(oldValue, newValue);
if (!Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true))
continue;
File.SetLastWriteTime(fileInfo.FullName, fileInfo.LastWriteTime);
}
}
Directory.Move(directoryCollection[0], directoryCollection[1]);
}
File.Move(Path.Combine(e3RenameContentDirectory, pending, traceFileName), Path.Combine(e3RenameContentDirectory, target, traceFileName));
}
catch (Exception)
{
File.Move(Path.Combine(e3RenameContentDirectory, pending, traceFileName), Path.Combine(e3RenameContentDirectory, error, traceFileName));
throw;
}
}
internal void RenameQueue(Property.Models.Configuration configuration)
{
string[] lines;
string[] segments;
string e3RenameContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(E3_Rename), "()");
string[] files = Directory.GetFiles(e3RenameContentDirectory, "*.tsv", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
lines = File.ReadAllLines(file);
foreach (string line in lines)
{
if (string.IsNullOrEmpty(line) || !line.Contains('\t'))
continue;
segments = line.Split('\t');
if (segments.Length != 2)
throw new Exception();
DirectoryRename(configuration, segments[0], segments[1]);
}
}
}
}

View File

@ -0,0 +1,390 @@
using FaceRecognitionDotNet;
using System.Text;
using System.Text.Json;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
namespace View_by_Distance.Instance.Models;
/// <summary>
// List<D_Faces>
/// </summary>
internal class E_Distance
{
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
internal E_Distance(Configuration configuration)
{
_Configuration = configuration;
_Log = Serilog.Log.ForContext<E_Distance>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private static void LoadFaceEncodingCollections(string[] subFiles, List<List<D_Face>> faceCollections, List<int[]> locationIndicesCollection, List<FaceEncoding> faceEncodingCollection, List<List<FaceEncoding>> faceEncodingCollections)
{
List<D_Face> faceCollection;
FaceEncoding faceEncoding;
for (int i = 0; i < subFiles.Length; i++)
{
faceCollection = faceCollections[i];
if (!faceCollection.Any())
throw new Exception();
faceEncodingCollections.Add(new List<FaceEncoding>());
for (int j = 0; j < faceCollection.Count; j++)
{
if (!faceCollection[j].Populated)
continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(faceCollection[j].FaceEncoding.RawEncoding);
faceEncodingCollection.Add(faceEncoding);
faceEncodingCollections[i].Add(faceEncoding);
locationIndicesCollection.Add(new int[] { i, j });
}
}
}
private List<Tuple<Shared.Models.Properties.IFace, string>> GetOrderedNoFaceCollection(List<List<D_Face>> faceCollections, int i, D_Face face)
{
List<Tuple<Shared.Models.Properties.IFace, string>> results = new() { new(face, string.Empty) };
if (_Configuration.MaxItemsInDistanceCollection is null)
throw new Exception();
for (int n = 0; n < faceCollections.Count; n++)
{
if (i == n)
continue;
for (int j = 0; j < faceCollections[n].Count; j++)
results.Add(new(faceCollections[n][j], string.Empty));
}
for (int r = results.Count - 1; r > _Configuration.MaxItemsInDistanceCollection.Value; r--)
results.RemoveAt(r);
return results;
}
private List<double[]> GetValues(List<List<D_Face>> faceCollections, List<int[]> locationIndicesCollection, double[] faceDistances)
{
List<double[]> results = new();
if (_Configuration.LocationConfidenceFactor is null)
throw new Exception();
if (_Configuration.DistanceFactor is null)
throw new Exception();
D_Face face;
int[] locationIndices;
for (int d = 0; d < faceDistances.Length; d++)
{
locationIndices = locationIndicesCollection[d];
face = faceCollections[locationIndices[0]][locationIndices[1]];
if (face.Populated && face.LocationIndex is not null && locationIndices[1] != face.LocationIndex)
throw new Exception();
results.Add(new double[] { d, faceDistances[d], (faceDistances[d] * _Configuration.DistanceFactor.Value) + face.Location.Confidence * _Configuration.LocationConfidenceFactor.Value / 10 });
}
results = (from l in results orderby l[2] select l).ToList();
return results;
}
private List<Tuple<Shared.Models.Properties.IFace, string>> GetOrderedFaceCollection(List<List<D_Face>> faceCollections, List<int[]> locationIndicesCollection, List<double[]> indicesAndValues)
{
List<Tuple<Shared.Models.Properties.IFace, string>> results = new();
if (_Configuration.MaxItemsInDistanceCollection is null)
throw new Exception();
int[] locationIndices;
for (int t = 0; t < indicesAndValues.Count; t++)
{
locationIndices = locationIndicesCollection[(int)indicesAndValues[t][0]];
results.Add(new(faceCollections[locationIndices[0]][locationIndices[1]], string.Join('|', (from l in indicesAndValues[t] select l.ToString("0.000")).ToArray(), 1, indicesAndValues[t].Length - 1)));
}
for (int r = results.Count - 1; r > _Configuration.MaxItemsInDistanceCollection.Value; r--)
results.RemoveAt(r);
return results;
}
private static string GetText(string fileNameWithoutExtension, List<List<D_Face>> faceCollections, List<int[]> locationIndicesCollection, List<double[]> indicesAndValues)
{
string result;
D_Face face;
int[] locationIndices;
StringBuilder tvs = new();
_ = tvs.Append("FileNameWithoutExtension").Append('\t').Append("LocationIndex").Append('\t').Append("FaceConfidence").Append('\t').Append("FaceDistance").Append('\t').Append("FactoredValue").AppendLine();
for (int t = 0; t < indicesAndValues.Count; t++)
{
locationIndices = locationIndicesCollection[(int)indicesAndValues[t][0]];
face = faceCollections[locationIndices[0]][locationIndices[1]];
if (face.Populated && face.LocationIndex is not null && locationIndices[1] != face.LocationIndex)
throw new Exception();
_ = tvs.Append(fileNameWithoutExtension).Append('\t').Append(face.LocationIndex).Append('\t').Append(face.Location.Confidence).Append('\t').Append(indicesAndValues[t][1]).Append('\t').Append(indicesAndValues[t][2]).AppendLine();
}
result = tvs.ToString();
return result;
}
private void LoadOrCreateThenSaveDistanceResultsLoop(Property.Models.Configuration configuration, List<List<D_Face>> faceCollections, int subFilesCount, int i, List<D_Face> faceCollection, List<int[]> locationIndicesCollection, List<Tuple<string, DateTime>> subFileTuples, List<FaceEncoding> faceEncodingCollection, List<FaceEncoding> faceEncodingCollections, string fileNameWithoutExtension, string jsonDirectory, string tvsDirectory)
{
string text;
string json;
string jsonFile;
List<Tuple<Shared.Models.Properties.IFace, string>> orderedFaceCollection;
if (!Directory.Exists(jsonDirectory))
_ = Directory.CreateDirectory(jsonDirectory);
if (!Directory.Exists(tvsDirectory))
_ = Directory.CreateDirectory(tvsDirectory);
if (!faceEncodingCollections.Any())
{
int j = 0;
orderedFaceCollection = GetOrderedNoFaceCollection(faceCollections, i, faceCollection[j]);
json = JsonSerializer.Serialize(orderedFaceCollection, _WriteIndentedJsonSerializerOptions);
jsonFile = Path.Combine(jsonDirectory, $"{j} - {fileNameWithoutExtension}.json");
if (Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, compareBeforeWrite: true))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now));
}
else
{
string tvsFile;
double[] faceDistances;
List<double[]> indicesAndValues;
for (int j = 0; j < faceEncodingCollections.Count; j++)
{
if (!faceCollection[j].Populated)
continue;
tvsFile = Path.Combine(tvsDirectory, $"{j} - {fileNameWithoutExtension}.tvs");
jsonFile = Path.Combine(jsonDirectory, $"{j} - {fileNameWithoutExtension}.json");
faceDistances = FaceRecognition.FaceDistances(faceEncodingCollection, faceEncodingCollections[j]).ToArray();
indicesAndValues = GetValues(faceCollections, locationIndicesCollection, faceDistances);
orderedFaceCollection = GetOrderedFaceCollection(faceCollections, locationIndicesCollection, indicesAndValues);
text = GetText(fileNameWithoutExtension, faceCollections, locationIndicesCollection, indicesAndValues);
if (Property.Models.Stateless.IPath.WriteAllText(tvsFile, text, compareBeforeWrite: true))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now));
json = JsonSerializer.Serialize(orderedFaceCollection, _WriteIndentedJsonSerializerOptions);
if (Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, compareBeforeWrite: true))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now));
}
}
}
private void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, string[] subFiles, List<List<D_Face>> faceCollections, List<string[]> directories)
{
string fileNameWithoutExtension;
List<int[]> locationIndicesCollection = new();
List<Tuple<string, DateTime>> subFileTuples = new();
List<FaceEncoding> faceEncodingCollection = new();
List<List<FaceEncoding>> faceEncodingCollections = new();
LoadFaceEncodingCollections(subFiles, faceCollections, locationIndicesCollection, faceEncodingCollection, faceEncodingCollections);
if (faceEncodingCollections.Count != faceCollections.Count)
throw new Exception();
if (locationIndicesCollection.Count != faceEncodingCollection.Count)
throw new Exception();
for (int i = 0; i < subFiles.Length; i++)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(subFiles[i]);
LoadOrCreateThenSaveDistanceResultsLoop(configuration, faceCollections, subFiles.Length, i, faceCollections[i], locationIndicesCollection, subFileTuples, faceEncodingCollection, faceEncodingCollections[i], fileNameWithoutExtension, directories[i][0], directories[i][1]);
}
}
internal void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, string sourceDirectory, string outputResolution, List<Tuple<string, DateTime>> sourceDirectoryChanges, string[] subFiles, List<List<D_Face>> faceCollections)
{
if (_Configuration.CheckJsonForDistanceResults is null)
throw new Exception();
if (_Configuration.PropertiesChangedForDistance is null)
throw new Exception();
string json;
bool check = false;
string parentCheck;
DirectoryInfo directoryInfo;
DirectoryInfo tvsDirectoryInfo;
string fileNameWithoutExtension;
List<string[]> directories = new();
string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) };
List<DateTime> dateTimes = (from l in sourceDirectoryChanges where changesFrom.Contains(l.Item1) select l.Item2).ToList();
List<string> directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration,
sourceDirectory,
nameof(E_Distance),
outputResolution,
includeResizeGroup: true,
includeModel: true,
includePredictorModel: true,
contentDescription: ".tvs File",
singletonDescription: string.Empty,
collectionDescription: "n json file(s) for each face found (one to many)");
for (int i = 0; i < subFiles.Length; i++)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(subFiles[i]);
directoryInfo = new DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), fileNameWithoutExtension));
if (!directoryInfo.Exists)
{
if (directoryInfo.Parent?.Parent is null)
throw new Exception();
parentCheck = Path.Combine(directoryInfo.Parent.Parent.FullName, directoryInfo.Name);
if (Directory.Exists(parentCheck))
{
foreach (string file in Directory.GetFiles(parentCheck))
File.Delete(file);
Directory.Delete(parentCheck);
}
}
tvsDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), fileNameWithoutExtension));
directories.Add(new string[] { directoryInfo.FullName, tvsDirectoryInfo.FullName });
if (_Configuration.CheckJsonForDistanceResults.Value && directoryInfo.Exists)
{
foreach (FileInfo fileInfo in directoryInfo.GetFiles("*.json", SearchOption.AllDirectories))
{
json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfo.FullName, fileInfo);
if (!_Configuration.PropertiesChangedForDistance.Value && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfo.FullName) is null)
check = true;
}
}
if (check)
continue;
if (_Configuration.PropertiesChangedForDistance.Value)
check = true;
else if (!directoryInfo.Exists)
check = true;
else if (!tvsDirectoryInfo.Exists)
check = true;
else if (dateTimes.Any() && dateTimes.Max() > directoryInfo.LastWriteTime)
check = true;
}
if (check)
LoadOrCreateThenSaveDistanceResults(configuration, subFiles, faceCollections, directories);
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()"));
}
private List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> GetFiles(Property.Models.Configuration configuration, string outputResolution)
{
string json;
List<KeyValuePair<string, Shared.Models.Face[]>>? facesKeyValuePairCollection;
List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> results = new();
string dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[[]]");
string[] dFacesCollectionFiles = Directory.GetFiles(dFacesCollectionDirectory, "*.json", SearchOption.TopDirectoryOnly);
foreach (string dFacesCollectionFile in dFacesCollectionFiles)
{
json = File.ReadAllText(dFacesCollectionFile);
facesKeyValuePairCollection = JsonSerializer.Deserialize<List<KeyValuePair<string, Shared.Models.Face[]>>>(json);
if (facesKeyValuePairCollection is null)
continue;
results.Add(new(dFacesCollectionFile, facesKeyValuePairCollection));
}
return results;
}
private static List<(string, List<Shared.Models.Face>, List<FaceEncoding>)> GetMatches(List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> files)
{
List<(string, List<Shared.Models.Face>, List<FaceEncoding>)> results = new();
List<Shared.Models.Face> faces;
FaceEncoding faceEncoding;
List<FaceEncoding> faceEncodings;
foreach ((string, List<KeyValuePair<string, Shared.Models.Face[]>>) file in files)
{
faces = new();
faceEncodings = new();
foreach (KeyValuePair<string, Shared.Models.Face[]> keyValuePair in file.Item2)
{
foreach (Shared.Models.Face face in keyValuePair.Value)
{
if (!face.Populated)
continue;
faces.Add(face);
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
faceEncodings.Add(faceEncoding);
}
}
results.Add(new(file.Item1, faces, faceEncodings));
}
return results;
}
private static int GetIndex(double[] faceDistances)
{
int result;
List<double[]> faceDistancesWithIndex = new();
for (int y = 0; y < faceDistances.Length; y++)
faceDistancesWithIndex.Add(new double[] { faceDistances[y], y });
faceDistancesWithIndex = (from l in faceDistancesWithIndex orderby l[0] select l).ToList();
result = (int)faceDistancesWithIndex[0][1];
return result;
}
private void Save(Property.Models.Configuration configuration, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Shared.Models.Face face, List<Tuple<Shared.Models.Face, string>> faceAndFaceDistanceCollection)
{
if (string.IsNullOrEmpty(eDistanceCollectionDirectory))
eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]");
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(face.RelativePath);
string jsonDirectory = string.Concat(eDistanceCollectionDirectory, Path.Combine(relativePath, fileNameWithoutExtension));
if (!Directory.Exists(jsonDirectory))
_ = Directory.CreateDirectory(jsonDirectory);
string json = JsonSerializer.Serialize(faceAndFaceDistanceCollection, _WriteIndentedJsonSerializerOptions);
string jsonFile = Path.Combine(jsonDirectory, $"{k} - {fileNameWithoutExtension}.nosj");
_ = Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, compareBeforeWrite: true);
}
private static Tuple<Shared.Models.Face, double> Get(FaceEncoding faceEncoding, (string, List<Shared.Models.Face>, List<FaceEncoding>) match)
{
Tuple<Shared.Models.Face, double> result;
double[] faceDistances = FaceRecognition.FaceDistances(match.Item3, faceEncoding).ToArray();
int index = GetIndex(faceDistances);
result = new(match.Item2[index], faceDistances[index]);
return result;
}
internal void LoadOrCreateThenSaveDirectoryDistanceResults(Property.Models.Configuration configuration, string outputResolution)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
string? relativePath;
Shared.Models.Face face;
ParallelOptions parallelOptions = new();
FaceEncoding faceEncoding;
string eDistanceCollectionDirectory = string.Empty;
Tuple<Shared.Models.Face, double> faceAndFaceDistance;
List<Tuple<Shared.Models.Face, string>> faceAndFaceDistanceCollection;
List<(string, List<KeyValuePair<string, Shared.Models.Face[]>>)> files = GetFiles(configuration, outputResolution);
List<(string, List<Shared.Models.Face>, List<FaceEncoding>)> matches = GetMatches(files);
if (files.Count != matches.Count)
throw new Exception();
int filesCount = files.Count;
for (int i = 0; i < filesCount; i++)
{
if (_Configuration.CrossDirectoryMaxItemsInDistanceCollection is null)
continue;
_Log.Debug(string.Concat("LoadOrCreateThenSaveDirectoryDistanceResults - ", nameof(outputResolution), ' ', outputResolution, " - ", i, " of ", filesCount));
for (int j = 0; j < files[i].Item2.Count; j++)
{
if (!matches[i].Item2.Any())
continue;
for (int k = 0; k < files[i].Item2[j].Value.Length; k++)
{
if (!files[i].Item2[j].Value[k].Populated)
continue;
face = files[i].Item2[j].Value[k];
faceAndFaceDistanceCollection = new(matches.Count);
relativePath = Path.GetDirectoryName(face.RelativePath);
if (string.IsNullOrEmpty(relativePath))
continue;
faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding);
_ = Parallel.For(0, matches.Count, parallelOptions, z =>
{
if (z != i && matches[z].Item2.Any())
{
faceAndFaceDistance = Get(faceEncoding, matches[z]);
// if (faceAndFaceDistance.Item2 < _Configuration.)
faceAndFaceDistanceCollection.Add(new(faceAndFaceDistance.Item1, faceAndFaceDistance.Item2.ToString("0.000")));
}
});
if (faceAndFaceDistanceCollection.Any())
{
faceAndFaceDistanceCollection = (from l in faceAndFaceDistanceCollection orderby l.Item2 select l).Take(_Configuration.CrossDirectoryMaxItemsInDistanceCollection.Value).ToList();
Save(configuration, outputResolution, eDistanceCollectionDirectory, k, relativePath, face, faceAndFaceDistanceCollection);
}
}
}
}
}
}

View File

@ -0,0 +1,90 @@
using System.Text.Json;
namespace View_by_Distance.Instance.Models;
/// <summary>
// List<string>
/// </summary>
internal class F_Random
{
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
internal F_Random(Configuration configuration)
{
_Configuration = configuration;
_Log = Serilog.Log.ForContext<F_Random>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = false };
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private bool IsIgnoreRelativePath(string directory)
{
bool result = false;
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string? checkDirectory = Path.GetFullPath(directory);
for (int i = 0; i < int.MaxValue; i++)
{
if (_Configuration.IgnoreRelativePaths.Contains(Path.GetFileName(checkDirectory)))
{
result = true;
break;
}
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == _Configuration.PropertyConfiguration.RootDirectory)
break;
}
return result;
}
internal void Random(Property.Models.Configuration configuration, string outputResolution, List<KeyValuePair<string, string>> fileKeyValuePairs)
{
if (_Configuration.SaveFullYearOfRandomFiles is null)
throw new Exception();
string json;
string jsonFile;
Random random = new();
List<string> relativePaths = new();
List<string> ignoreRelativePaths = new();
DateTime dateTime = new(2024, 1, 1); //Leap year
string fRandomCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(F_Random), "[]");
string[] files = Directory.GetFiles(fRandomCollectionDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
File.Delete(file);
foreach (KeyValuePair<string, string> keyValuePair in fileKeyValuePairs)
{
if (!(from l in _Configuration.IgnoreRelativePaths where keyValuePair.Key.Contains(l) && IsIgnoreRelativePath(keyValuePair.Key) select true).Any())
relativePaths.Add(keyValuePair.Value);
else
ignoreRelativePaths.Add(keyValuePair.Value);
}
if (relativePaths.Any())
{
for (int i = 0; i < 366; i++)
{
relativePaths = (from l in relativePaths orderby random.NextDouble() select l).ToList();
jsonFile = Path.Combine(fRandomCollectionDirectory, $"{dateTime.AddDays(i):MM-dd}.json");
json = JsonSerializer.Serialize(relativePaths, _WriteIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, compareBeforeWrite: false);
if (!_Configuration.SaveFullYearOfRandomFiles.Value)
break;
}
}
if (ignoreRelativePaths.Any())
{
ignoreRelativePaths = (from l in ignoreRelativePaths orderby random.NextDouble() select l).ToList();
jsonFile = Path.Combine(fRandomCollectionDirectory, "01-01.txt");
json = JsonSerializer.Serialize(ignoreRelativePaths, _WriteIndentedJsonSerializerOptions);
_ = Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, compareBeforeWrite: false);
}
}
}

View File

@ -0,0 +1,229 @@
using Phares.Shared;
using System.Text.Json;
using System.Text.Json.Serialization;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Instance.Models;
/// <summary>
// List<G2_Identify>
/// </summary>
public class G2_Identify : Shared.Models.Properties.IIdentify, IIdentify
{
protected int _DirectoryCount;
protected string _ParentDirectoryName;
protected string _Person;
protected string _PossibleYear;
protected string _RelativePath;
public int DirectoryCount => _DirectoryCount;
public string ParentDirectoryName => _ParentDirectoryName;
public string Person => _Person;
public string PossibleYear => _PossibleYear;
public string RelativePath => _RelativePath;
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
#nullable disable
[JsonConstructor]
public G2_Identify(int directoryCount, string parentDirectoryName, string person, string possibleYear, string relativePath)
{
_DirectoryCount = directoryCount;
_ParentDirectoryName = parentDirectoryName;
_Person = person;
_PossibleYear = possibleYear;
_RelativePath = relativePath;
}
internal G2_Identify(Configuration configuration)
{
_DirectoryCount = 0;
_ParentDirectoryName = string.Empty;
_Person = string.Empty;
_PossibleYear = string.Empty;
_RelativePath = string.Empty;
_Configuration = configuration;
_Log = Serilog.Log.ForContext<G2_Identify>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private FileInfo GetNamed()
{
FileInfo result;
string[] jsonFiles = Directory.GetFiles(_Configuration.PropertyConfiguration.RootDirectory, "*Named*.json", SearchOption.TopDirectoryOnly);
if (!jsonFiles.Any())
result = null;
else
result = new FileInfo(jsonFiles[0]);
return result;
}
private void CheckLastWriteTimes(Property.Models.Configuration configuration, IsEnvironment isEnvironment, A2_People a2People, FileInfo named, string g2IdentifySingletonDirectory)
{
string json;
FileInfo fileInfo;
DateTime dateTime = DateTime.MinValue;
string[] jsonFiles = Directory.GetFiles(g2IdentifySingletonDirectory, "*.json", SearchOption.AllDirectories);
foreach (string jsonFile in jsonFiles)
{
fileInfo = new(jsonFile);
if (dateTime < fileInfo.LastWriteTime)
dateTime = fileInfo.LastWriteTime;
}
if (named.LastWriteTime > dateTime)
{
if (!isEnvironment.DebuggerWasAttachedDuringConstructor)
throw new Exception("Only allowed when debugger is attached during constructor!");
foreach (string file in jsonFiles)
File.Delete(file);
}
json = File.ReadAllText(named.FullName);
Person[] people = a2People.GetPeople(configuration);
Dictionary<string, string[]> resultKeyValuePairs = new();
string[] peopleBirthdates = (from l in people select Shared.Models.Stateless.Methods.IPersonBirthday.GetFormated(l.Birthday)).ToArray();
Dictionary<string, string[]> sourceKeyValuePairs = JsonSerializer.Deserialize<Dictionary<string, string[]>>(json);
foreach (KeyValuePair<string, string[]> keyValuePair in sourceKeyValuePairs)
{
if (!(from l in keyValuePair.Value where peopleBirthdates.Contains(l) select false).Any())
continue;
resultKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value);
}
if (resultKeyValuePairs.Count != sourceKeyValuePairs.Count)
{
json = JsonSerializer.Serialize(resultKeyValuePairs, _WriteIndentedJsonSerializerOptions);
if (!isEnvironment.DebuggerWasAttachedDuringConstructor)
throw new Exception("Only allowed when debugger is attached during constructor!");
_ = Property.Models.Stateless.IPath.WriteAllText(named.FullName, json, compareBeforeWrite: true);
}
}
internal List<G2_Identify> GetIdentifiedCollection(Property.Models.Configuration configuration, IsEnvironment isEnvironment, A2_People a2People)
{
List<G2_Identify> results = new();
string json;
string[] people;
string[] jsonFiles;
int directoryCount;
string possibleYear;
G2_Identify identify;
FileInfo named = GetNamed();
string testDirectoryFullName;
string checkDirectoryFullName;
Dictionary<int, string[]> keyValuePairs;
List<string> missing = new();
List<G_Index> indices = new();
string directoryName = Path.GetFileName(_Configuration.PropertyConfiguration.RootDirectory);
string g2IdentifySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]");
string jsonRootDirectory = Path.Combine(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, " - Copied"), string.Concat(directoryName, " - 4) Info"), _Configuration.PropertyConfiguration.DateGroup, "[]");
if (named is not null && named.Exists)
CheckLastWriteTimes(configuration, isEnvironment, a2People, named, g2IdentifySingletonDirectory);
if (Directory.Exists(jsonRootDirectory))
{
jsonFiles = Directory.GetFiles(jsonRootDirectory, "*.json", SearchOption.AllDirectories);
for (int i = 0; i < jsonFiles.Length; i++)
{
json = Shared.Models.Stateless.Methods.IIndex.GetJson(jsonFiles[i], fileInfo: null);
indices.AddRange(JsonSerializer.Deserialize<List<G_Index>>(json));
}
if (named is not null && named.Exists)
{
json = File.ReadAllText(named.FullName);
keyValuePairs = JsonSerializer.Deserialize<Dictionary<int, string[]>>(json);
foreach (G_Index index in indices)
{
if (index?.Index is null)
continue;
if (!keyValuePairs.ContainsKey(index.Index.Value))
{
missing.Add(index.Index.Value.ToString());
continue;
}
if (index.RelativePaths is null)
{
missing.Add(index.Index.Value.ToString());
continue;
}
people = keyValuePairs[index.Index.Value];
foreach (string relativePath in index.RelativePaths)
{
foreach (string person in people)
{
directoryCount = 0;
checkDirectoryFullName = string.Concat(_Configuration.PropertyConfiguration.RootDirectory, relativePath);
for (int i = 0; i < int.MaxValue; i++)
{
testDirectoryFullName = Path.GetDirectoryName(checkDirectoryFullName);
if (testDirectoryFullName == _Configuration.PropertyConfiguration.RootDirectory)
break;
directoryCount += 1;
checkDirectoryFullName = testDirectoryFullName;
}
possibleYear = checkDirectoryFullName.Split(' ').Last();
if (possibleYear.Length != 4)
possibleYear = "0000";
identify = new G2_Identify(directoryCount, Path.GetFileName(checkDirectoryFullName), person, possibleYear, relativePath);
results.Add(identify);
}
}
}
}
}
results = (from l in results orderby l.PossibleYear descending, l.DirectoryCount, l.ParentDirectoryName, l.RelativePath select l).ToList();
return results;
}
internal void WriteAllText(Property.Models.Configuration configuration, string outputResolution, List<G2_Identify> identifiedCollection)
{
string key;
string json;
string jsonFile;
string directoryFullName;
string fileNameWithoutExtension;
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
string g2IdentifyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(G2_Identify), "[]");
Dictionary<string, List<KeyValuePair<string, string>>> keyValuePairs = new();
foreach (G2_Identify identified in identifiedCollection)
{
key = Path.GetDirectoryName(identified.RelativePath);
if (!keyValuePairs.ContainsKey(key))
keyValuePairs.Add(key, new List<KeyValuePair<string, string>>());
keyValuePairs[key].Add(new KeyValuePair<string, string>(identified.RelativePath, identified.Person));
}
foreach (KeyValuePair<string, List<KeyValuePair<string, string>>> keyValuePair in keyValuePairs)
{
directoryFullName = string.Concat(aPropertySingletonDirectory, keyValuePair.Key);
if (!Directory.Exists(directoryFullName))
continue;
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(keyValue.Key);
jsonFile = Path.Combine(directoryFullName, $"{fileNameWithoutExtension}.json");
if (!File.Exists(jsonFile))
{
directoryFullName = string.Empty;
break;
}
}
if (string.IsNullOrEmpty(directoryFullName))
continue;
directoryFullName = Path.GetDirectoryName(string.Concat(g2IdentifyCollectionDirectory, keyValuePair.Key));
if (!Directory.Exists(directoryFullName))
_ = Directory.CreateDirectory(directoryFullName);
jsonFile = string.Concat(g2IdentifyCollectionDirectory, keyValuePair.Key, ".json");
json = JsonSerializer.Serialize(keyValuePair.Value, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(jsonFile, json, compareBeforeWrite: true))
continue;
}
}
}

213
Instance/Models/_G_Index.cs Normal file
View File

@ -0,0 +1,213 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Instance.Models;
/// <summary>
// G_Index && G_Index[]
/// </summary>
public class G_Index : Shared.Models.Properties.IIndex, IIndex
{
private readonly Serilog.ILogger? _Log;
private readonly Configuration _Configuration;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
protected DateTime? _DateTime;
protected int? _Index;
protected List<string> _RelativePaths;
public DateTime? DateTime => _DateTime;
public int? Index => _Index;
public List<string> RelativePaths => _RelativePaths;
#nullable disable
[JsonConstructor]
public G_Index(DateTime? dateTime, int? index, List<string> relativePaths)
{
_DateTime = dateTime;
_Index = index;
_RelativePaths = relativePaths;
}
internal G_Index()
{
_DateTime = null;
_Index = null;
_RelativePaths = new();
}
internal G_Index(Configuration configuration)
{
_Configuration = configuration;
_Log = Serilog.Log.ForContext<G_Index>();
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private G_Index GetIndexInfo(FileInfo fileInfo, List<string> parseExceptions)
{
G_Index result;
List<int> indices = new();
string json = File.ReadAllText(fileInfo.FullName);
try
{
result = JsonSerializer.Deserialize<G_Index>(json);
}
catch (Exception)
{
result = null;
parseExceptions.Add(nameof(G_Index));
}
if (_Configuration.MappedMaxIndex.HasValue && result.Index.HasValue && _Configuration.MappedMaxIndex.Value < result.Index.Value)
{
result = null;
File.Delete(fileInfo.FullName);
}
else if (result.Index is null)
result = null;
return result;
}
private void WriteNeeded(List<int> indices, List<Tuple<List<string>, string, A_Property>> neededTuples)
{
string json;
DateTime dateTime;
A_Property property;
G_Index indexInfo;
int maxIndexPlusOne;
DateTime?[] dateTimes;
if (indices.Any())
maxIndexPlusOne = indices.Max() + 1;
else
{
maxIndexPlusOne = 1000000;
throw new Exception("Are you sure exception. Use debugger to step over.");
}
foreach (Tuple<List<string>, string, A_Property> tuple in neededTuples)
{
maxIndexPlusOne += 1;
property = tuple.Item3;
dateTimes = new DateTime?[] { property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp };
dateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
indexInfo = new(dateTime, maxIndexPlusOne, tuple.Item1);
json = JsonSerializer.Serialize(indexInfo, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(tuple.Item2, json, compareBeforeWrite: true))
continue;
}
}
private void WriteGroup(Property.Models.Configuration configuration, string outputResolution, List<Tuple<string, Dictionary<int, G_Index>>> indexInfoTuples)
{
string json;
G_Index[] indices;
List<string> directoryInfoCollection;
foreach (Tuple<string, Dictionary<int, G_Index>> tuple in indexInfoTuples)
{
indices = (from l in tuple.Item2 select l.Value).ToArray();
directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, tuple.Item1, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: string.Empty, collectionDescription: "Unknown A");
json = JsonSerializer.Serialize(indices, _WriteIndentedJsonSerializerOptions);
if (!Property.Models.Stateless.IPath.WriteAllText(string.Concat(directoryInfoCollection[0].Replace("<>", "[]"), ".json"), json, compareBeforeWrite: true))
continue;
}
}
private void AppendTSV(Property.Models.Configuration configuration, string outputResolution, Dictionary<string, List<Tuple<string, A_Property>>> filePropertiesKeyValuePairs)
{
A_Property property;
DateTime?[] dateTimes;
DateTime? maximumDateTime;
DateTime? minimumDateTime;
List<string> directoryInfoCollection;
long ticks = System.DateTime.Now.Ticks;
foreach (KeyValuePair<string, List<Tuple<string, A_Property>>> tuples in filePropertiesKeyValuePairs)
{
maximumDateTime = null;
minimumDateTime = null;
foreach (Tuple<string, A_Property> tuple in tuples.Value)
{
property = tuple.Item2;
dateTimes = new DateTime?[] { maximumDateTime, minimumDateTime, property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeOriginal, property.GPSDateStamp };
maximumDateTime = (from l in dateTimes where l.HasValue select l.Value).Max();
minimumDateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
}
directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unkown B", collectionDescription: string.Empty);
}
}
internal void SetIndex(Property.Models.Configuration configuration, string outputResolution, Dictionary<string, List<Tuple<string, A_Property>>> filePropertiesKeyValuePairs)
{
if (_Configuration.PropertiesChangedForIndex is null)
throw new Exception();
FileInfo fileInfo;
G_Index indexInfo;
string parentCheck;
List<int> indices = new();
Dictionary<int, G_Index> valuePairs;
List<string> directoryInfoCollection;
List<string> parseExceptions = new();
List<Tuple<List<string>, string, A_Property>> neededTuples = new();
List<Tuple<string, Dictionary<int, G_Index>>> indexInfoTuples = new();
for (short i = 0; i < short.MaxValue; i++)
{
if (i != 0)
{
if (!neededTuples.Any() && !parseExceptions.Any())
break;
indices.Clear();
indexInfoTuples.Clear();
parseExceptions.Clear();
}
neededTuples.Clear();
foreach (KeyValuePair<string, List<Tuple<string, A_Property>>> tuples in filePropertiesKeyValuePairs)
{
valuePairs = new Dictionary<int, G_Index>();
directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, tuples.Key, nameof(G_Index), outputResolution, includeResizeGroup: false, includeModel: false, includePredictorModel: false, contentDescription: string.Empty, singletonDescription: "Unknown C", collectionDescription: string.Empty);
foreach (Tuple<string, A_Property> tuple in tuples.Value)
{
fileInfo = new FileInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "{}"), string.Concat(Path.GetFileNameWithoutExtension(tuple.Item1), ".json")));
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
File.Delete(parentCheck);
}
if (_Configuration.PropertiesChangedForIndex.Value)
indexInfo = null;
else if (!fileInfo.Exists)
indexInfo = null;
else
indexInfo = GetIndexInfo(fileInfo, parseExceptions);
if (indexInfo?.Index is not null)
{
indices.Add(indexInfo.Index.Value);
valuePairs.Add(indexInfo.Index.Value, indexInfo);
}
else
neededTuples.Add(new Tuple<List<string>, string, A_Property>(new List<string> { tuple.Item1 }, fileInfo.FullName, tuple.Item2));
}
indexInfoTuples.Add(new Tuple<string, Dictionary<int, G_Index>>(tuples.Key, valuePairs));
}
if (_Configuration.MappedMaxIndex.HasValue)
break;
WriteNeeded(indices, neededTuples);
}
if (parseExceptions.Any())
throw new Exception(string.Join(Environment.NewLine, parseExceptions));
if (neededTuples.Any())
throw new Exception();
WriteGroup(configuration, outputResolution, indexInfoTuples);
AppendTSV(configuration, outputResolution, filePropertiesKeyValuePairs);
}
string Shared.Models.Stateless.Methods.IIndex.TestStatic_GetJson(string jsonFileFullName, FileInfo fileInfo) => throw new NotImplementedException();
}

71
Instance/Program.cs Normal file
View File

@ -0,0 +1,71 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.Instance.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Instance;
public class Program
{
public static void Secondary(List<string> args)
{
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
IConfigurationRoot configurationRoot = configurationBuilder.Build();
AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot);
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception("MaxDegreeOfParallelism must be set!");
if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount)
throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!");
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>();
int silentIndex = args.IndexOf("s");
if (silentIndex > -1)
args.RemoveAt(silentIndex);
try
{
if (args is null)
throw new Exception("args is null!");
Shared.Models.Console console = new();
DlibDotNet _ = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console);
}
catch (Exception ex)
{
log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace));
}
finally
{
Log.CloseAndFlush();
}
if (silentIndex > -1)
log.Debug("Done. Bye");
else
{
log.Debug("Done. Press 'Enter' to end");
_ = Console.ReadLine();
}
}
public static void Main(string[] args)
{
if (args is not null)
Secondary(args.ToList());
else
Secondary(new List<string>());
}
}

View File

@ -0,0 +1,457 @@
{
"Company": "Mike Phares",
"Linux": {},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MaxDegreeOfParallelism": 6,
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"CheckJsonForDistanceResults": true,
"CrossDirectoryMaxItemsInDistanceCollection": 7,
"DateGroup": "2022-04-07",
"DistanceFactor": 8,
"FileNameDirectorySeparator": ".Z.",
"ForceMetadataLastWriteTimeToCreationTime": false,
"ForcePropertyLastWriteTimeToCreationTime": false,
"ForceResizeLastWriteTimeToCreationTime": false,
"LoadOrCreateThenSaveDirectoryDistanceResults": true,
"LoadOrCreateThenSaveDistanceResults": true,
"LoadOrCreateThenSaveImageFacesResults": true,
"LoadOrCreateThenSaveIndex": false,
"LocationConfidenceFactor": 2,
"MappedMaxIndex": 1034720,
"MaxImagesInDirectoryForTopLevelFirstPass": 50,
"MaxItemsInDistanceCollection": 50,
"ModelDirectory": "C:/GitHub/dlib-models",
"ModelName": "Hog",
"NumJitters": 1,
"OutputExtension": ".jpg",
"OutputQuality": 95,
"OverrideForFaceImages": false,
"OverrideForFaceLandmarkImages": false,
"OverrideForResizeImages": false,
"PaddingLoops": 5,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PredictorModelName": "Large",
"PopulatePropertyId": true,
"PropertiesChangedForDistance": false,
"PropertiesChangedForFaces": false,
"PropertiesChangedForIndex": false,
"PropertiesChangedForMetadata": false,
"PropertiesChangedForProperty": false,
"PropertiesChangedForResize": false,
"Reverse": false,
"RootDirectory": "C:/Tmp/phares/Pictures",
"SaveFullYearOfRandomFiles": true,
"SaveResizedSubFiles": true,
"SearchForAbandonedFilesFull": true,
"SkipSearch": false,
"TestDistanceResults": true,
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"OutputResolutions": [
"176 x 176",
"256 x 256",
"353 x 353",
"1024 x 768"
],
"PropertyContentCollectionFiles": [],
"SaveFaceLandmarkForOutputResolutions": [
"176 x 176",
"256 x 256"
],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".amr",
".AMR",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidResolutions": [
"176 x 176",
"256 x 256",
"353 x 353",
"1024 x 768",
"1280 x 720",
"1280 x 800",
"1376 x 768",
"1600 x 1200",
"1920 x 1080",
"2256 x 1496",
"3840 x 2160",
"7680 x 4320"
],
"VerifyToSeason": [
". 2000",
". 2001",
". 2002",
". 2003",
". 2004",
". 2005",
". 2006",
". 2007",
". 2008",
". 2009",
". 2010",
". 2011",
". 2012",
". 2013",
". 2014",
". 2015",
". 2016",
". 2017",
". 2018",
". 2019",
". 2020",
". 2021",
". 2022",
". 2023",
". 2024",
". 2025",
". 2026",
". 2027",
". 2028",
". 2029",
"=2000.0 Winter",
"=2002.1 Spring",
"=2002.4 Winter",
"=2003.0 Winter",
"=2003.1 Spring",
"=2003.3 Fall",
"=2003.4 Winter",
"=2004.0 Winter",
"=2005.1 Spring",
"=2005.2 Summer",
"=2005.3 Fall",
"=2005.4 Winter",
"=2006.0 Winter",
"=2006.1 Spring",
"=2006.3 Fall",
"=2007.0 Winter",
"=2007.2 Summer Logan Michael",
"=2007.2 Summer",
"=2007.3 Fall Logan Michael",
"=2007.4 Winter Logan Michael",
"=2008.0 Winter Logan Michael",
"=2008.1 Spring Logan Michael",
"=2008.2 Summer Logan Michael",
"=2008.2 Summer",
"=2008.3 Fall Logan Michael",
"=2009.0 Winter Logan Michael",
"=2009.0 Winter",
"=2009.1 Spring Logan Michael",
"=2009.1 Spring",
"=2009.2 Summer Logan Michael",
"=2009.2 Summer",
"=2009.3 Fall Logan Michael",
"=2009.3 Fall",
"=2009.4 Winter Logan Michael",
"=2009.4 Winter",
"=2010.0 Winter Logan Michael",
"=2010.0 Winter",
"=2010.1 Spring Logan Michael",
"=2010.1 Spring",
"=2010.2 Summer",
"=2010.3 Fall Logan Michael",
"=2010.3 Fall",
"=2010.4 Winter",
"=2011.0 Winter",
"=2011.1 Spring",
"=2011.2 Summer",
"=2011.3 Fall",
"=2011.4 Winter",
"=2012.0 Winter Chelsea 2012",
"=2012.0 Winter Chelsea",
"=2012.0 Winter",
"=2012.1 Spring Chelsea",
"=2012.1 Spring",
"=2012.2 Summer Chelsea",
"=2012.2 Summer",
"=2012.3 Fall Chelsea",
"=2012.3 Fall",
"=2012.4 Winter Chelsea",
"=2012.4 Winter",
"=2013.0 Winter Chelsea 2013",
"=2013.0 Winter Chelsea",
"=2013.0 Winter",
"=2013.1 Spring",
"=2013.2 Summer Chelsea",
"=2013.2 Summer",
"=2013.3 Fall Chelsea",
"=2013.3 Fall",
"=2013.4 Winter",
"=2014.0 Winter",
"=2014.1 Spring",
"=2014.2 Summer",
"=2014.3 Fall",
"=2014.4 Winter",
"=2015.0 Winter",
"=2015.1 Spring",
"=2015.2 Summer",
"=2015.3 Fall",
"=2015.4 Winter",
"=2016.0 Winter",
"=2016.1 Spring",
"=2016.2 Summer",
"=2016.3 Fall",
"=2016.4 Winter",
"=2017.1 Spring",
"=2017.2 Summer",
"=2017.3 Fall",
"=2017.4 Winter",
"=2018.0 Winter",
"=2018.1 Spring",
"=2018.3 Fall",
"=2018.4 Winter",
"=2019.0 Winter",
"=2019.1 Spring",
"=2019.2 Summer",
"=2019.3 Fall",
"=2019.4 Winter",
"=2020.0 Winter",
"=2020.1 Spring",
"=2020.2 Summer",
"=2020.3 Fall",
"=2020.4 Winter",
"=2021.1 Spring",
"=2021.2 Summer",
"=2021.3 Fall",
"=2021.4 Winter",
"=2022.0 Winter",
"=2022.1 Spring",
"Anthem 2015",
"April 2010",
"April 2013",
"December 2006",
"December 2010",
"Fall 2005",
"Fall 2015",
"Fall 2016",
"Fall 2017",
"Fall 2018",
"Fall 2019",
"Fall 2020",
"Fall 2021",
"February 2010",
"January 2015",
"July 2010",
"June 2010",
"Kids 2005",
"March 2013",
"May 2010",
"May 2011",
"May 2013",
"October 2005",
"October 2014",
"Spring 2013",
"Spring 2014",
"Spring 2016",
"Spring 2018",
"Spring 2019",
"Spring 2020",
"Summer 2011",
"Summer 2012",
"Summer 2013",
"Summer 2014",
"Summer 2015",
"Summer 2016",
"Summer 2017",
"Summer 2018",
"Summer 2020",
"Summer 2021",
"Winter 2015",
"Winter 2016",
"Winter 2017",
"Winter 2018",
"Winter 2019-2020",
"Winter 2020",
"zzz =2005.0 Winter Tracy Pictures",
"zzz =2005.1 Spring Tracy Pictures",
"zzz =2005.2 Summer Tracy Pictures",
"zzz =2005.3 Fall Tracy Pictures",
"zzz =2005.4 Winter Tracy Pictures",
"zzz =2006.1 Spring Tracy Pictures",
"zzz =2007.0 Winter Tracy Pictures",
"zzz =2007.2 Summer Tracy Pictures",
"zzz =2008.0 Winter Tracy Pictures",
"zzz =2008.2 Summer Tracy Pictures",
"zzz =2009.0 Winter Tracy Pictures",
"zzz =2009.2 Summer Tracy Pictures",
"zzz =2009.3 Fall Tracy Pictures",
"zzz =2009.4 Winter Tracy Pictures",
"zzz =2010.0 Winter Tracy Pictures",
"zzz =2010.1 Spring Tracy Pictures",
"zzz =2010.2 Summer Tracy Pictures",
"zzz =2010.3 Fall Tracy Pictures",
"zzz =2011.0 Winter Tracy Pictures",
"zzz =2011.1 Spring Tracy Pictures",
"zzz =2011.2 Summer Tracy Pictures",
"zzz =2011.3 Fall Tracy Pictures",
"zzz =2011.4 Winter Tracy Pictures",
"zzz =2012.0 Winter Tracy Pictures",
"zzz =2012.1 Spring Tracy Pictures",
"zzz =2012.2 Summer Tracy Pictures",
"zzz =2012.3 Fall Tracy Pictures",
"zzz =2012.4 Winter Tracy Pictures",
"zzz =2013.0 Winter Tracy Pictures",
"zzz =2013.1 Spring Tracy Pictures",
"zzz =2013.2 Summer Tracy Pictures",
"zzz =2013.3 Fall Tracy Pictures",
"zzz =2013.4 Winter Tracy Pictures",
"zzz =2014.0 Winter Tracy Pictures",
"zzz =2014.1 Spring Tracy Pictures",
"zzz =2014.2 Summer Tracy Pictures",
"zzz =2014.3 Fall Tracy Pictures",
"zzz =2014.4 Winter Tracy Pictures",
"zzz =2015.0 Winter Tracy Pictures"
],
"MixedYearRelativePaths": [
"Edited",
"Phares Slides",
"Rex Memorial",
"Scanned Grandma's Quilt",
"Scanned Pictures Of Kids",
"Scanned Prints",
"Slide in Name Order Originals (622)",
"Slides Pictures"
],
"IgnoreRelativePaths": [
"3757 W Whitman 2017",
"501 Playful Meadows 2006",
"501 Playful Meadows 2007",
"501 Playful Meadows 2008",
"501 Playful Meadows 2009",
"501 Playful Meadows 2010",
"501 Playful Meadows 2013",
"501 Playful Meadows 2015",
"6309 Evesham 2003",
"6309 Evesham 2004",
"Crystal's Wedding 2003",
"Danny's Wedding 2009",
"Door images 2019",
"Family Pictures 2006",
"Family Pictures 2007",
"Family Pictures 2011",
"Family Pictures 2013",
"GrandPrix 2004",
"Kids School Pictures 2004",
"Kristy 2002",
"Kristy Parents Wedding 2005",
"Logan Ultrasound 2007",
"Mandy's Dogs 2008",
"Motorcycles 2010",
"Motorcycles 2013",
"Motorcycles 2014",
"Phares Slides",
"Portrait Innovations April 2008",
"Portrait Innovations December 2007",
"Portrait Innovations June 2008",
"Portrait Innovations March 2012",
"The guys house 2000",
"Tracy Pictures 2005",
"Tracy Pictures 2006",
"Tracy Pictures 2007",
"Tracy Pictures 2008",
"Tracy Pictures 2009",
"Tracy Pictures 2010",
"Tracy Pictures 2011",
"Tracy Pictures 2012",
"Tracy Pictures 2013 Jan-July",
"Tracy Pictures 2013 July- Dec",
"Tracy Pictures 2014",
"Tracy Pictures 2015",
"Tracy Took The Kids 2006",
"Tracy's Bday 2012",
"Tracy's Wedding 2002",
"Trip to Colorado 10 2002",
"Trip to Colorado June 2002",
"Tub 2002",
"Vericruz 2011"
]
}
}
}

View File

@ -0,0 +1,457 @@
{
"Company": "Mike Phares",
"Linux": {},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MaxDegreeOfParallelism": 12,
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"CheckJsonForDistanceResults": true,
"CrossDirectoryMaxItemsInDistanceCollection": 7,
"DateGroup": "2022-04-07",
"DistanceFactor": 8,
"FileNameDirectorySeparator": ".Z.",
"ForceMetadataLastWriteTimeToCreationTime": false,
"ForcePropertyLastWriteTimeToCreationTime": false,
"ForceResizeLastWriteTimeToCreationTime": false,
"LoadOrCreateThenSaveDirectoryDistanceResults": false,
"LoadOrCreateThenSaveDistanceResults": false,
"LoadOrCreateThenSaveImageFacesResults": false,
"LoadOrCreateThenSaveIndex": false,
"LocationConfidenceFactor": 2,
"MappedMaxIndex": 1034720,
"MaxImagesInDirectoryForTopLevelFirstPass": 50,
"MaxItemsInDistanceCollection": 50,
"ModelDirectory": "L:/GitHub/dlib-models",
"ModelName": "Hog",
"NumJitters": 1,
"OutputExtension": ".jpg",
"OutputQuality": 95,
"OverrideForFaceImages": false,
"OverrideForFaceLandmarkImages": false,
"OverrideForResizeImages": false,
"PaddingLoops": 5,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true,
"PredictorModelName": "Large",
"PropertiesChangedForDistance": false,
"PropertiesChangedForFaces": false,
"PropertiesChangedForIndex": false,
"PropertiesChangedForMetadata": false,
"PropertiesChangedForProperty": false,
"PropertiesChangedForResize": false,
"Reverse": false,
"RootDirectory": "E:/Images",
"SaveFullYearOfRandomFiles": true,
"SaveResizedSubFiles": true,
"SearchForAbandonedFilesFull": false,
"SkipSearch": false,
"TestDistanceResults": true,
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"OutputResolutions": [
"176 x 176",
"256 x 256",
"353 x 353",
"1024 x 768"
],
"PropertyContentCollectionFiles": [],
"SaveFaceLandmarkForOutputResolutions": [
"176 x 176",
"256 x 256"
],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".amr",
".AMR",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidResolutions": [
"176 x 176",
"256 x 256",
"353 x 353",
"1024 x 768",
"1280 x 720",
"1280 x 800",
"1376 x 768",
"1600 x 1200",
"1920 x 1080",
"2256 x 1496",
"3840 x 2160",
"7680 x 4320"
],
"VerifyToSeason": [
". 2000",
". 2001",
". 2002",
". 2003",
". 2004",
". 2005",
". 2006",
". 2007",
". 2008",
". 2009",
". 2010",
". 2011",
". 2012",
". 2013",
". 2014",
". 2015",
". 2016",
". 2017",
". 2018",
". 2019",
". 2020",
". 2021",
". 2022",
". 2023",
". 2024",
". 2025",
". 2026",
". 2027",
". 2028",
". 2029",
"=2000.0 Winter",
"=2002.1 Spring",
"=2002.4 Winter",
"=2003.0 Winter",
"=2003.1 Spring",
"=2003.3 Fall",
"=2003.4 Winter",
"=2004.0 Winter",
"=2005.1 Spring",
"=2005.2 Summer",
"=2005.3 Fall",
"=2005.4 Winter",
"=2006.0 Winter",
"=2006.1 Spring",
"=2006.3 Fall",
"=2007.0 Winter",
"=2007.2 Summer Logan Michael",
"=2007.2 Summer",
"=2007.3 Fall Logan Michael",
"=2007.4 Winter Logan Michael",
"=2008.0 Winter Logan Michael",
"=2008.1 Spring Logan Michael",
"=2008.2 Summer Logan Michael",
"=2008.2 Summer",
"=2008.3 Fall Logan Michael",
"=2009.0 Winter Logan Michael",
"=2009.0 Winter",
"=2009.1 Spring Logan Michael",
"=2009.1 Spring",
"=2009.2 Summer Logan Michael",
"=2009.2 Summer",
"=2009.3 Fall Logan Michael",
"=2009.3 Fall",
"=2009.4 Winter Logan Michael",
"=2009.4 Winter",
"=2010.0 Winter Logan Michael",
"=2010.0 Winter",
"=2010.1 Spring Logan Michael",
"=2010.1 Spring",
"=2010.2 Summer",
"=2010.3 Fall Logan Michael",
"=2010.3 Fall",
"=2010.4 Winter",
"=2011.0 Winter",
"=2011.1 Spring",
"=2011.2 Summer",
"=2011.3 Fall",
"=2011.4 Winter",
"=2012.0 Winter Chelsea 2012",
"=2012.0 Winter Chelsea",
"=2012.0 Winter",
"=2012.1 Spring Chelsea",
"=2012.1 Spring",
"=2012.2 Summer Chelsea",
"=2012.2 Summer",
"=2012.3 Fall Chelsea",
"=2012.3 Fall",
"=2012.4 Winter Chelsea",
"=2012.4 Winter",
"=2013.0 Winter Chelsea 2013",
"=2013.0 Winter Chelsea",
"=2013.0 Winter",
"=2013.1 Spring",
"=2013.2 Summer Chelsea",
"=2013.2 Summer",
"=2013.3 Fall Chelsea",
"=2013.3 Fall",
"=2013.4 Winter",
"=2014.0 Winter",
"=2014.1 Spring",
"=2014.2 Summer",
"=2014.3 Fall",
"=2014.4 Winter",
"=2015.0 Winter",
"=2015.1 Spring",
"=2015.2 Summer",
"=2015.3 Fall",
"=2015.4 Winter",
"=2016.0 Winter",
"=2016.1 Spring",
"=2016.2 Summer",
"=2016.3 Fall",
"=2016.4 Winter",
"=2017.1 Spring",
"=2017.2 Summer",
"=2017.3 Fall",
"=2017.4 Winter",
"=2018.0 Winter",
"=2018.1 Spring",
"=2018.3 Fall",
"=2018.4 Winter",
"=2019.0 Winter",
"=2019.1 Spring",
"=2019.2 Summer",
"=2019.3 Fall",
"=2019.4 Winter",
"=2020.0 Winter",
"=2020.1 Spring",
"=2020.2 Summer",
"=2020.3 Fall",
"=2020.4 Winter",
"=2021.1 Spring",
"=2021.2 Summer",
"=2021.3 Fall",
"=2021.4 Winter",
"=2022.0 Winter",
"=2022.1 Spring",
"Anthem 2015",
"April 2010",
"April 2013",
"December 2006",
"December 2010",
"Fall 2005",
"Fall 2015",
"Fall 2016",
"Fall 2017",
"Fall 2018",
"Fall 2019",
"Fall 2020",
"Fall 2021",
"February 2010",
"January 2015",
"July 2010",
"June 2010",
"Kids 2005",
"March 2013",
"May 2010",
"May 2011",
"May 2013",
"October 2005",
"October 2014",
"Spring 2013",
"Spring 2014",
"Spring 2016",
"Spring 2018",
"Spring 2019",
"Spring 2020",
"Summer 2011",
"Summer 2012",
"Summer 2013",
"Summer 2014",
"Summer 2015",
"Summer 2016",
"Summer 2017",
"Summer 2018",
"Summer 2020",
"Summer 2021",
"Winter 2015",
"Winter 2016",
"Winter 2017",
"Winter 2018",
"Winter 2019-2020",
"Winter 2020",
"zzz =2005.0 Winter Tracy Pictures",
"zzz =2005.1 Spring Tracy Pictures",
"zzz =2005.2 Summer Tracy Pictures",
"zzz =2005.3 Fall Tracy Pictures",
"zzz =2005.4 Winter Tracy Pictures",
"zzz =2006.1 Spring Tracy Pictures",
"zzz =2007.0 Winter Tracy Pictures",
"zzz =2007.2 Summer Tracy Pictures",
"zzz =2008.0 Winter Tracy Pictures",
"zzz =2008.2 Summer Tracy Pictures",
"zzz =2009.0 Winter Tracy Pictures",
"zzz =2009.2 Summer Tracy Pictures",
"zzz =2009.3 Fall Tracy Pictures",
"zzz =2009.4 Winter Tracy Pictures",
"zzz =2010.0 Winter Tracy Pictures",
"zzz =2010.1 Spring Tracy Pictures",
"zzz =2010.2 Summer Tracy Pictures",
"zzz =2010.3 Fall Tracy Pictures",
"zzz =2011.0 Winter Tracy Pictures",
"zzz =2011.1 Spring Tracy Pictures",
"zzz =2011.2 Summer Tracy Pictures",
"zzz =2011.3 Fall Tracy Pictures",
"zzz =2011.4 Winter Tracy Pictures",
"zzz =2012.0 Winter Tracy Pictures",
"zzz =2012.1 Spring Tracy Pictures",
"zzz =2012.2 Summer Tracy Pictures",
"zzz =2012.3 Fall Tracy Pictures",
"zzz =2012.4 Winter Tracy Pictures",
"zzz =2013.0 Winter Tracy Pictures",
"zzz =2013.1 Spring Tracy Pictures",
"zzz =2013.2 Summer Tracy Pictures",
"zzz =2013.3 Fall Tracy Pictures",
"zzz =2013.4 Winter Tracy Pictures",
"zzz =2014.0 Winter Tracy Pictures",
"zzz =2014.1 Spring Tracy Pictures",
"zzz =2014.2 Summer Tracy Pictures",
"zzz =2014.3 Fall Tracy Pictures",
"zzz =2014.4 Winter Tracy Pictures",
"zzz =2015.0 Winter Tracy Pictures"
],
"MixedYearRelativePaths": [
"Edited",
"Phares Slides",
"Rex Memorial",
"Scanned Grandma's Quilt",
"Scanned Pictures Of Kids",
"Scanned Prints",
"Slide in Name Order Originals (622)",
"Slides Pictures"
],
"IgnoreRelativePaths": [
"3757 W Whitman 2017",
"501 Playful Meadows 2006",
"501 Playful Meadows 2007",
"501 Playful Meadows 2008",
"501 Playful Meadows 2009",
"501 Playful Meadows 2010",
"501 Playful Meadows 2013",
"501 Playful Meadows 2015",
"6309 Evesham 2003",
"6309 Evesham 2004",
"Crystal's Wedding 2003",
"Danny's Wedding 2009",
"Door images 2019",
"Family Pictures 2006",
"Family Pictures 2007",
"Family Pictures 2011",
"Family Pictures 2013",
"GrandPrix 2004",
"Kids School Pictures 2004",
"Kristy 2002",
"Kristy Parents Wedding 2005",
"Logan Ultrasound 2007",
"Mandy's Dogs 2008",
"Motorcycles 2010",
"Motorcycles 2013",
"Motorcycles 2014",
"Phares Slides",
"Portrait Innovations April 2008",
"Portrait Innovations December 2007",
"Portrait Innovations June 2008",
"Portrait Innovations March 2012",
"The guys house 2000",
"Tracy Pictures 2005",
"Tracy Pictures 2006",
"Tracy Pictures 2007",
"Tracy Pictures 2008",
"Tracy Pictures 2009",
"Tracy Pictures 2010",
"Tracy Pictures 2011",
"Tracy Pictures 2012",
"Tracy Pictures 2013 Jan-July",
"Tracy Pictures 2013 July- Dec",
"Tracy Pictures 2014",
"Tracy Pictures 2015",
"Tracy Took The Kids 2006",
"Tracy's Bday 2012",
"Tracy's Wedding 2002",
"Trip to Colorado 10 2002",
"Trip to Colorado June 2002",
"Tub 2002",
"Vericruz 2011"
]
}
}
}

458
Instance/appsettings.json Normal file
View File

@ -0,0 +1,458 @@
{
"Company": "Mike Phares",
"Linux": {},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MaxDegreeOfParallelism": 12,
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"CheckJsonForDistanceResults": true,
"CrossDirectoryMaxItemsInDistanceCollection": 7,
"DateGroup": "2022-04-07",
"DistanceFactor": 8,
"FileNameDirectorySeparator": ".Z.",
"ForceMetadataLastWriteTimeToCreationTime": false,
"ForcePropertyLastWriteTimeToCreationTime": false,
"ForceResizeLastWriteTimeToCreationTime": false,
"LoadOrCreateThenSaveDirectoryDistanceResults": true,
"LoadOrCreateThenSaveDistanceResults": true,
"LoadOrCreateThenSaveImageFacesResults": true,
"LoadOrCreateThenSaveIndex": false,
"LocationConfidenceFactor": 2,
"MappedMaxIndex": 1034720,
"MaxImagesInDirectoryForTopLevelFirstPass": 50,
"MaxItemsInDistanceCollection": 50,
"ModelDirectory": "C:/GitHub/dlib-models",
"ModelName": "Hog",
"NumJitters": 1,
"OutputExtension": ".jpg",
"OutputQuality": 95,
"OverrideForFaceImages": false,
"OverrideForFaceLandmarkImages": false,
"OverrideForResizeImages": false,
"PaddingLoops": 5,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true,
"PredictorModelName": "Large",
"PropertiesChangedForDistance": false,
"PropertiesChangedForFaces": false,
"PropertiesChangedForIndex": false,
"PropertiesChangedForMetadata": false,
"PropertiesChangedForProperty": false,
"PropertiesChangedForResize": false,
"Reverse": false,
"RootDirectory": "D:/Images",
"SaveFullYearOfRandomFiles": true,
"SaveResizedSubFiles": true,
"SearchForAbandonedFilesFull": false,
"SkipSearch": false,
"TestDistanceResults": true,
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"OutputResolutions": [
"176 x 176",
"256 x 256",
"353 x 353",
"1024 x 768",
"1920 x 1080"
],
"PropertyContentCollectionFiles": [],
"SaveFaceLandmarkForOutputResolutions": [
"176 x 176",
"256 x 256"
],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".amr",
".AMR",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidResolutions": [
"176 x 176",
"256 x 256",
"353 x 353",
"1024 x 768",
"1280 x 720",
"1280 x 800",
"1376 x 768",
"1600 x 1200",
"1920 x 1080",
"2256 x 1496",
"3840 x 2160",
"7680 x 4320"
],
"VerifyToSeason": [
". 2000",
". 2001",
". 2002",
". 2003",
". 2004",
". 2005",
". 2006",
". 2007",
". 2008",
". 2009",
". 2010",
". 2011",
". 2012",
". 2013",
". 2014",
". 2015",
". 2016",
". 2017",
". 2018",
". 2019",
". 2020",
". 2021",
". 2022",
". 2023",
". 2024",
". 2025",
". 2026",
". 2027",
". 2028",
". 2029",
"=2000.0 Winter",
"=2002.1 Spring",
"=2002.4 Winter",
"=2003.0 Winter",
"=2003.1 Spring",
"=2003.3 Fall",
"=2003.4 Winter",
"=2004.0 Winter",
"=2005.1 Spring",
"=2005.2 Summer",
"=2005.3 Fall",
"=2005.4 Winter",
"=2006.0 Winter",
"=2006.1 Spring",
"=2006.3 Fall",
"=2007.0 Winter",
"=2007.2 Summer Logan Michael",
"=2007.2 Summer",
"=2007.3 Fall Logan Michael",
"=2007.4 Winter Logan Michael",
"=2008.0 Winter Logan Michael",
"=2008.1 Spring Logan Michael",
"=2008.2 Summer Logan Michael",
"=2008.2 Summer",
"=2008.3 Fall Logan Michael",
"=2009.0 Winter Logan Michael",
"=2009.0 Winter",
"=2009.1 Spring Logan Michael",
"=2009.1 Spring",
"=2009.2 Summer Logan Michael",
"=2009.2 Summer",
"=2009.3 Fall Logan Michael",
"=2009.3 Fall",
"=2009.4 Winter Logan Michael",
"=2009.4 Winter",
"=2010.0 Winter Logan Michael",
"=2010.0 Winter",
"=2010.1 Spring Logan Michael",
"=2010.1 Spring",
"=2010.2 Summer",
"=2010.3 Fall Logan Michael",
"=2010.3 Fall",
"=2010.4 Winter",
"=2011.0 Winter",
"=2011.1 Spring",
"=2011.2 Summer",
"=2011.3 Fall",
"=2011.4 Winter",
"=2012.0 Winter Chelsea 2012",
"=2012.0 Winter Chelsea",
"=2012.0 Winter",
"=2012.1 Spring Chelsea",
"=2012.1 Spring",
"=2012.2 Summer Chelsea",
"=2012.2 Summer",
"=2012.3 Fall Chelsea",
"=2012.3 Fall",
"=2012.4 Winter Chelsea",
"=2012.4 Winter",
"=2013.0 Winter Chelsea 2013",
"=2013.0 Winter Chelsea",
"=2013.0 Winter",
"=2013.1 Spring",
"=2013.2 Summer Chelsea",
"=2013.2 Summer",
"=2013.3 Fall Chelsea",
"=2013.3 Fall",
"=2013.4 Winter",
"=2014.0 Winter",
"=2014.1 Spring",
"=2014.2 Summer",
"=2014.3 Fall",
"=2014.4 Winter",
"=2015.0 Winter",
"=2015.1 Spring",
"=2015.2 Summer",
"=2015.3 Fall",
"=2015.4 Winter",
"=2016.0 Winter",
"=2016.1 Spring",
"=2016.2 Summer",
"=2016.3 Fall",
"=2016.4 Winter",
"=2017.1 Spring",
"=2017.2 Summer",
"=2017.3 Fall",
"=2017.4 Winter",
"=2018.0 Winter",
"=2018.1 Spring",
"=2018.3 Fall",
"=2018.4 Winter",
"=2019.0 Winter",
"=2019.1 Spring",
"=2019.2 Summer",
"=2019.3 Fall",
"=2019.4 Winter",
"=2020.0 Winter",
"=2020.1 Spring",
"=2020.2 Summer",
"=2020.3 Fall",
"=2020.4 Winter",
"=2021.1 Spring",
"=2021.2 Summer",
"=2021.3 Fall",
"=2021.4 Winter",
"=2022.0 Winter",
"=2022.1 Spring",
"Anthem 2015",
"April 2010",
"April 2013",
"December 2006",
"December 2010",
"Fall 2005",
"Fall 2015",
"Fall 2016",
"Fall 2017",
"Fall 2018",
"Fall 2019",
"Fall 2020",
"Fall 2021",
"February 2010",
"January 2015",
"July 2010",
"June 2010",
"Kids 2005",
"March 2013",
"May 2010",
"May 2011",
"May 2013",
"October 2005",
"October 2014",
"Spring 2013",
"Spring 2014",
"Spring 2016",
"Spring 2018",
"Spring 2019",
"Spring 2020",
"Summer 2011",
"Summer 2012",
"Summer 2013",
"Summer 2014",
"Summer 2015",
"Summer 2016",
"Summer 2017",
"Summer 2018",
"Summer 2020",
"Summer 2021",
"Winter 2015",
"Winter 2016",
"Winter 2017",
"Winter 2018",
"Winter 2019-2020",
"Winter 2020",
"zzz =2005.0 Winter Tracy Pictures",
"zzz =2005.1 Spring Tracy Pictures",
"zzz =2005.2 Summer Tracy Pictures",
"zzz =2005.3 Fall Tracy Pictures",
"zzz =2005.4 Winter Tracy Pictures",
"zzz =2006.1 Spring Tracy Pictures",
"zzz =2007.0 Winter Tracy Pictures",
"zzz =2007.2 Summer Tracy Pictures",
"zzz =2008.0 Winter Tracy Pictures",
"zzz =2008.2 Summer Tracy Pictures",
"zzz =2009.0 Winter Tracy Pictures",
"zzz =2009.2 Summer Tracy Pictures",
"zzz =2009.3 Fall Tracy Pictures",
"zzz =2009.4 Winter Tracy Pictures",
"zzz =2010.0 Winter Tracy Pictures",
"zzz =2010.1 Spring Tracy Pictures",
"zzz =2010.2 Summer Tracy Pictures",
"zzz =2010.3 Fall Tracy Pictures",
"zzz =2011.0 Winter Tracy Pictures",
"zzz =2011.1 Spring Tracy Pictures",
"zzz =2011.2 Summer Tracy Pictures",
"zzz =2011.3 Fall Tracy Pictures",
"zzz =2011.4 Winter Tracy Pictures",
"zzz =2012.0 Winter Tracy Pictures",
"zzz =2012.1 Spring Tracy Pictures",
"zzz =2012.2 Summer Tracy Pictures",
"zzz =2012.3 Fall Tracy Pictures",
"zzz =2012.4 Winter Tracy Pictures",
"zzz =2013.0 Winter Tracy Pictures",
"zzz =2013.1 Spring Tracy Pictures",
"zzz =2013.2 Summer Tracy Pictures",
"zzz =2013.3 Fall Tracy Pictures",
"zzz =2013.4 Winter Tracy Pictures",
"zzz =2014.0 Winter Tracy Pictures",
"zzz =2014.1 Spring Tracy Pictures",
"zzz =2014.2 Summer Tracy Pictures",
"zzz =2014.3 Fall Tracy Pictures",
"zzz =2014.4 Winter Tracy Pictures",
"zzz =2015.0 Winter Tracy Pictures"
],
"MixedYearRelativePaths": [
"Edited",
"Phares Slides",
"Rex Memorial",
"Scanned Grandma's Quilt",
"Scanned Pictures Of Kids",
"Scanned Prints",
"Slide in Name Order Originals (622)",
"Slides Pictures"
],
"IgnoreRelativePaths": [
"3757 W Whitman 2017",
"501 Playful Meadows 2006",
"501 Playful Meadows 2007",
"501 Playful Meadows 2008",
"501 Playful Meadows 2009",
"501 Playful Meadows 2010",
"501 Playful Meadows 2013",
"501 Playful Meadows 2015",
"6309 Evesham 2003",
"6309 Evesham 2004",
"Crystal's Wedding 2003",
"Danny's Wedding 2009",
"Door images 2019",
"Family Pictures 2006",
"Family Pictures 2007",
"Family Pictures 2011",
"Family Pictures 2013",
"GrandPrix 2004",
"Kids School Pictures 2004",
"Kristy 2002",
"Kristy Parents Wedding 2005",
"Logan Ultrasound 2007",
"Mandy's Dogs 2008",
"Motorcycles 2010",
"Motorcycles 2013",
"Motorcycles 2014",
"Phares Slides",
"Portrait Innovations April 2008",
"Portrait Innovations December 2007",
"Portrait Innovations June 2008",
"Portrait Innovations March 2012",
"The guys house 2000",
"Tracy Pictures 2005",
"Tracy Pictures 2006",
"Tracy Pictures 2007",
"Tracy Pictures 2008",
"Tracy Pictures 2009",
"Tracy Pictures 2010",
"Tracy Pictures 2011",
"Tracy Pictures 2012",
"Tracy Pictures 2013 Jan-July",
"Tracy Pictures 2013 July- Dec",
"Tracy Pictures 2014",
"Tracy Pictures 2015",
"Tracy Took The Kids 2006",
"Tracy's Bday 2012",
"Tracy's Wedding 2002",
"Trip to Colorado 10 2002",
"Trip to Colorado June 2002",
"Tub 2002",
"Vericruz 2011"
]
}
}
}

7
Metadata/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"cSpell.words": [
"dlib",
"Exif",
"Serilog"
]
}

47
Metadata/Metadata.csproj Normal file
View File

@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Metadata</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
<PackageReference Include="Serilog" Version="2.10.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,181 @@
using System.Diagnostics;
using System.Text.Json;
using View_by_Distance.Metadata.Models.Stateless;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Metadata.Models;
/// <summary>
// Dictionary<string, List<KeyValuePair<string, string>>>
/// </summary>
public class B_Metadata
{
public List<string> AngleBracketCollection { get; }
private readonly Serilog.ILogger? _Log;
private readonly bool _PropertiesChangedForMetadata;
private readonly bool _ForceMetadataLastWriteTimeToCreationTime;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
public static string DateTimeFormat() => "ddd MMM dd HH:mm:ss yyyy";
public B_Metadata(bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata)
{
AngleBracketCollection = new List<string>();
_Log = Serilog.Log.ForContext<B_Metadata>();
_PropertiesChangedForMetadata = propertiesChangedForMetadata;
_ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime;
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private Dictionary<string, List<KeyValuePair<string, string>>> GetMetadataCollection(string subFile)
{
Dictionary<string, List<KeyValuePair<string, string>>> results = new();
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
try
{
object? @object;
string? tagDescription;
int type = (int)IExif.Tags.Orientation;
List<string> tagNames = new();
string key = nameof(IExif.Tags.Orientation);
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(subFile);
foreach (MetadataExtractor.Directory directory in directories)
{
if (!results.ContainsKey(directory.Name))
results.Add(directory.Name, new());
foreach (MetadataExtractor.Tag tag in directory.Tags)
{
tagNames.Add(tag.Name);
if (string.IsNullOrEmpty(tag.Description))
continue;
results[directory.Name].Add(new KeyValuePair<string, string>(string.Concat(tag.Type, '\t', tag.Name), tag.Description));
}
if (tagNames.Contains(key) && !results.ContainsKey(key))
{
@object = directory.GetObject(type);
if (@object is null)
continue;
tagDescription = @object.ToString();
if (string.IsNullOrEmpty(tagDescription))
continue;
results.Add(key, new() { new(string.Concat(type, '\t', key), tagDescription) });
}
}
}
catch (Exception)
{
_Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", subFile, ">"));
}
return results;
}
public (int, List<KeyValuePair<string, string>>) GetMetadataCollection(List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string subFile, string relativePath, string fileNameWithoutExtension)
{
List<KeyValuePair<string, string>> results = new();
Dictionary<string, List<KeyValuePair<string, string>>>? dictionary;
string json = string.Empty;
string[] changesFrom = Array.Empty<string>();
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(fileNameWithoutExtension, ".json")));
if (!fileInfo.Exists)
{
if (fileInfo.Directory?.Parent is null)
throw new Exception();
string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name);
if (File.Exists(parentCheck))
{
File.Move(parentCheck, fileInfo.FullName);
fileInfo.Refresh();
}
}
if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
fileInfo.Refresh();
}
if (_ForceMetadataLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime)
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
}
if (_PropertiesChangedForMetadata)
dictionary = new();
else if (!fileInfo.Exists)
dictionary = new();
else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime)
dictionary = new();
else
{
json = File.ReadAllText(fileInfo.FullName);
try
{
dictionary = JsonSerializer.Deserialize<Dictionary<string, List<KeyValuePair<string, string>>>>(json);
if (dictionary is null)
throw new Exception();
subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), fileInfo.LastWriteTime));
}
catch (Exception)
{
dictionary = new();
parseExceptions.Add(nameof(B_Metadata));
}
}
if (dictionary is null || !dictionary.Any())
{
dictionary = GetMetadataCollection(subFile);
json = JsonSerializer.Serialize(dictionary, _WriteIndentedJsonSerializerOptions);
if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true))
{
if (!_ForceMetadataLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime))
subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), DateTime.Now));
else
{
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
fileInfo.Refresh();
subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), fileInfo.CreationTime));
}
}
}
foreach (KeyValuePair<string, List<KeyValuePair<string, string>>> keyValuePair in dictionary)
{
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
results.Add(new(string.Concat(keyValuePair.Key, '\t', keyValue.Key), keyValue.Value));
}
return new(dictionary.Count, results);
}
public static List<KeyValuePair<string, string>> GetFiltered(List<KeyValuePair<string, string>> metadataCollection)
{
List<KeyValuePair<string, string>> results = new();
foreach (KeyValuePair<string, string> keyValuePair in metadataCollection)
{
if (keyValuePair.Key.Contains("File") || keyValuePair.Key.Contains("JPEG") || keyValuePair.Key.Contains("Orientation") || keyValuePair.Key.Contains("Thumbnail"))
continue;
results.Add(new(keyValuePair.Key, keyValuePair.Value));
}
if (!results.Any())
results = metadataCollection;
return results;
}
public static string GetUniqueImageId(List<KeyValuePair<string, string>> metadataCollection)
{
string result = string.Empty;
const string exifSubIFD = "Exif SubIFD";
const string uniqueImageID = "42016\tUnique Image ID";
List<string> uniqueImageIDs = (from l in metadataCollection where l.Key.StartsWith(exifSubIFD) && l.Key.EndsWith(uniqueImageID) select l.Value).ToList();
if (uniqueImageIDs.Any())
result = uniqueImageIDs[0];
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Metadata.Models.Stateless;
internal static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -0,0 +1 @@
[]

30
Not-Copy-Copy/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net6.0/win-x64/Not-Copy-Copy.dll",
"args": [],
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "externalTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processName": "Not-Copy-Copy"
}
]
}

11
Not-Copy-Copy/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"cSpell.words": [
"Barrick",
"Beichler",
"Bohdi",
"Dlib",
"Phares",
"Serilog",
"Vericruz"
]
}

42
Not-Copy-Copy/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Not-Copy-Copy.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Not-Copy-Copy.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/Not-Copy-Copy.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@ -0,0 +1,35 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Not.Copy.Copy.Models;
public class AppSettings
{
protected string _Company;
protected string _WorkingDirectoryName;
protected int? _MaxDegreeOfParallelism;
public string Company => _Company;
public string WorkingDirectoryName => _WorkingDirectoryName;
public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism;
// public AppSettings()
// {
// }
[JsonConstructor]
public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism)
{
_Company = company;
_WorkingDirectoryName = workingDirectoryName;
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Not.Copy.Copy.Models.Binder;
public class AppSettings
{
[Display(Name = "Company"), Required] public string Company { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
[Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; }
public AppSettings()
{
Company = string.Empty;
WorkingDirectoryName = string.Empty;
MaxDegreeOfParallelism = -1;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Not.Copy.Copy.Models.Binder;
public class Configuration
{
[Display(Name = "Compare Source"), Required] public string CompareSource { get; set; }
[Display(Name = "Empty Destination"), Required] public string EmptyDestination { get; set; }
[Display(Name = "Property Configuration"), Required] public Property.Models.Configuration? PropertyConfiguration { get; set; }
[Display(Name = "Selected Source"), Required] public string SelectedSource { get; set; }
public Configuration()
{
CompareSource = string.Empty;
EmptyDestination = string.Empty;
SelectedSource = string.Empty;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,43 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Not.Copy.Copy.Models;
public class Configuration
{
protected string _CompareSource;
protected string _EmptyDestination;
protected Property.Models.Configuration? _PropertyConfiguration;
protected string _SelectedSource;
public string CompareSource => _CompareSource;
public string EmptyDestination => _EmptyDestination;
public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration;
public string SelectedSource => _SelectedSource;
[JsonConstructor]
public Configuration(string compareSource, string emptyDestination, Property.Models.Configuration? propertyConfiguration, string selectedSource)
{
_CompareSource = compareSource;
_EmptyDestination = emptyDestination;
_PropertyConfiguration = propertyConfiguration;
_SelectedSource = selectedSource;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration;
public void Update()
{
_PropertyConfiguration?.Update();
_CompareSource = Path.GetFullPath(_CompareSource);
_SelectedSource = Path.GetFullPath(_SelectedSource);
_EmptyDestination = Path.GetFullPath(_EmptyDestination);
}
}

View File

@ -0,0 +1,40 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace View_by_Distance.Not.Copy.Copy.Models.Stateless;
public abstract class AppSettings
{
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
namespace View_by_Distance.Not.Copy.Copy.Models.Stateless;
public abstract class Configuration
{
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory, Property.Models.Configuration propertyConfiguration)
{
Models.Configuration? result;
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Binder.Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
Binder.Configuration configuration = configurationSection.Get<Binder.Configuration>();
string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.Configuration>(json);
if (result is null)
throw new Exception(json);
string jsonThis = result.ToString();
result.Set(propertyConfiguration);
result.Update();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Not.Copy.Copy.Models.Stateless;
public static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -0,0 +1,193 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using View_by_Distance.Not.Copy.Copy.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Not.Copy.Copy;
public class NotCopyCopy
{
private readonly Serilog.ILogger? _Log;
private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment;
private readonly Models.Configuration _Configuration;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs;
public NotCopyCopy(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{
if (isSilent)
{ }
if (args is null)
{ }
if (console is null)
{ }
_AppSettings = appSettings;
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!");
_IsEnvironment = isEnvironment;
_Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<NotCopyCopy>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory);
Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration);
_Configuration = configuration;
if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!");
if (propertyConfiguration.PopulatePropertyId is null)
throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!");
if (!_IsEnvironment.Development)
throw new Exception("This program only allows development environments!");
string searchPattern = "*";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
List<Group> compareSourceGroupCollection;
List<Group> selectedSourceGroupCollection;
PropertyLogic propertyLogic = GetPropertyLogic();
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection;
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(_Configuration.CompareSource, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
compareSourceGroupCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.GetParallelWork));
topDirectories.Clear();
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(configuration.SelectedSource, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
selectedSourceGroupCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.GetParallelWork));
string directoryName;
List<string> distinct = new();
List<(string Source, string[] Destination)> copyCollection = GetCopyCollection(compareSourceGroupCollection, selectedSourceGroupCollection);
foreach ((string source, string[] destination) in copyCollection)
{
directoryName = Path.Combine(destination.Take(destination.Length - 1).ToArray());
if (distinct.Contains(directoryName))
continue;
distinct.Add(directoryName);
if (!Directory.Exists(directoryName))
_ = Directory.CreateDirectory(directoryName);
}
_Log.Information($"Ready to copy {copyCollection.Count} file(s)?");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to to copy file(s)");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
int copied = 0;
string fullFileName;
foreach ((string source, string[] destination) in copyCollection)
{
if (copied % 500 == 0)
_Log.Information($"{copied})");
fullFileName = Path.Combine(destination);
if (File.Exists(fullFileName))
continue;
File.Copy(source, fullFileName);
copied += 1;
}
_Log.Information($"{copied} file(s) copied");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to continue or close console");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
}
private static void Verify(Models.Configuration configuration)
{
if (Path.GetPathRoot(configuration.SelectedSource) == configuration.SelectedSource)
throw new Exception($"{nameof(configuration.SelectedSource)} should have at least one level!");
if (string.IsNullOrEmpty(configuration.CompareSource) || !Directory.Exists(configuration.CompareSource))
throw new Exception($"{nameof(configuration.CompareSource)} must have a value and exits!");
if (string.IsNullOrEmpty(configuration.EmptyDestination) || Directory.Exists(configuration.EmptyDestination))
throw new Exception($"{nameof(configuration.EmptyDestination)} can't exit!");
if (string.IsNullOrEmpty(configuration.SelectedSource) || !Directory.Exists(configuration.SelectedSource))
throw new Exception($"{nameof(configuration.SelectedSource)} must have a value and exits!");
if (configuration.SelectedSource.Length != configuration.CompareSource.Length)
throw new Exception($"{nameof(configuration.SelectedSource)} and {nameof(configuration.CompareSource)} must be the same length!");
}
private long LogDelta(long ticks, string methodName)
{
long result;
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds;
_Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)");
result = DateTime.Now.Ticks;
return result;
}
private PropertyLogic GetPropertyLogic()
{
PropertyLogic result;
string[] verifyToSeason = Array.Empty<string>();
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason);
return result;
}
private List<(string Source, string[] Destination)> GetCopyCollection(List<Group> compareSourceGroupCollection, List<Group> selectedSourceGroupCollection)
{
List<(string Source, string[] Destination)> results = new();
string key;
string fileName;
A_Property? property;
string destinationDirectory;
List<string> directoryNames;
List<string> destinationCollection;
string filteredSourceDirectoryFile;
Dictionary<string, A_Property> keyValuePairs = new();
foreach (Group group in compareSourceGroupCollection)
{
for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++)
{
property = group.PropertyCollection[i];
if (property is null)
continue;
key = string.Concat(group.SourceDirectory[_Configuration.CompareSource.Length..], Path.GetFileName(group.FilteredSourceDirectoryFiles[i]));
keyValuePairs.Add(key, property);
}
}
foreach (Group group in selectedSourceGroupCollection)
{
for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++)
{
destinationCollection = new();
property = group.PropertyCollection[i];
if (property is null)
continue;
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
fileName = Path.GetFileName(filteredSourceDirectoryFile);
key = string.Concat(group.SourceDirectory[_Configuration.SelectedSource.Length..], fileName);
if (keyValuePairs.ContainsKey(key) && keyValuePairs[key].LastWriteTime == property.LastWriteTime)
continue;
destinationDirectory = string.Concat(_Configuration.EmptyDestination, group.SourceDirectory[_Configuration.SelectedSource.Length..]);
directoryNames = Property.Models.Stateless.IPath.GetDirectoryNames(destinationDirectory);
destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName);
results.Add(new(filteredSourceDirectoryFile, destinationCollection.ToArray()));
}
}
return results;
}
}

View File

@ -0,0 +1,63 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Not.Copy.Copy</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

127
Not-Copy-Copy/Program.cs Normal file
View File

@ -0,0 +1,127 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.Not.Copy.Copy.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Not.Copy.Copy;
public class Program
{
public static void Secondary(List<string> args)
{
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
IConfigurationRoot configurationRoot = configurationBuilder.Build();
AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot);
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception("MaxDegreeOfParallelism must be set!");
if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount)
throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!");
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>();
int silentIndex = args.IndexOf("s");
if (silentIndex > -1)
args.RemoveAt(silentIndex);
try
{
if (args is null)
throw new Exception("args is null!");
#nullable disable
if (Property.Models.Stateless.A_Property.IsWrongYear("-".Split(' '), "2021").Item1.HasValue)
throw new Exception("-");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass".Split(' '), "2021").Item1.HasValue)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("England 2017".Split(' '), "2017").Item1.Value)
throw new Exception("England");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael".Split(' '), "2021").Item1.HasValue)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item2[0] != "~2021.4")
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Chelsea's 2nd Birthday =2014".Split(' '), "2014").Item1.Value)
throw new Exception("Chelsea");
#nullable restore
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp")[0] != @"C:\")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp")[1] != "Tmp")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp\mike.txt")[1] != "Tmp")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp\a.txt")[1] != "Tmp")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"C:\Tmp\Mike\a.txt")[2] != "Mike")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[0] != @"I:\")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[1] != @"Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer\Dsc_8558.jpg")[2] != @"=2010.2 Summer")
throw new Exception();
if (Property.Models.Stateless.IPath.GetDirectoryNames(@"I:\Images 2019-06-08 - 34a9240ac28b52da97428d7725153a80a757ee6b - II\=2010.2 Summer")[2] != @"=2010.2 Summer")
throw new Exception();
Shared.Models.Console console = new();
NotCopyCopy _ = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console);
}
catch (Exception ex)
{
log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace));
}
finally
{
Log.CloseAndFlush();
}
if (silentIndex > -1)
log.Debug("Done. Bye");
else
{
log.Debug("Done. Press 'Enter' to end");
_ = Console.ReadLine();
}
}
public static void Main(string[] args)
{
if (args is not null)
Secondary(args.ToList());
else
Secondary(new List<string>());
}
}

View File

@ -0,0 +1,339 @@
{
"Company": "Mike Phares",
"Linux": {},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MaxDegreeOfParallelism": 6,
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"DateGroup": "2022-04-07",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": false,
"PropertiesChangedForProperty": false,
"CompareSource": "E:/Images 2021-10-29 - 34a9240ac28b52da97428d7725153a80a757ee6b - III",
"SelectedSource": "E:/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - III",
"EmptyDestination": "E:/. Not-Copy-Copy/Images 2018-05-12 - b01d4763d8853b6d6057a3870b2723449726da75 - Not-Copy-Copy",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"PropertyContentCollectionFiles": [],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".amr",
".AMR",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"VerifyToSeason": [
". 2000",
". 2001",
". 2002",
". 2003",
". 2004",
". 2005",
". 2006",
". 2007",
". 2008",
". 2009",
". 2010",
". 2011",
". 2012",
". 2013",
". 2014",
". 2015",
". 2016",
". 2017",
". 2018",
". 2019",
". 2020",
". 2021",
". 2022",
". 2023",
". 2024",
". 2025",
". 2026",
". 2027",
". 2028",
". 2029",
"=2000.0 Winter",
"=2002.1 Spring",
"=2002.4 Winter",
"=2003.0 Winter",
"=2003.1 Spring",
"=2003.3 Fall",
"=2003.4 Winter",
"=2004.0 Winter",
"=2005.1 Spring",
"=2005.2 Summer",
"=2005.3 Fall",
"=2005.4 Winter",
"=2006.0 Winter",
"=2006.1 Spring",
"=2006.3 Fall",
"=2007.0 Winter",
"=2007.2 Summer Logan Michael",
"=2007.2 Summer",
"=2007.3 Fall Logan Michael",
"=2007.4 Winter Logan Michael",
"=2008.0 Winter Logan Michael",
"=2008.1 Spring Logan Michael",
"=2008.2 Summer Logan Michael",
"=2008.2 Summer",
"=2008.3 Fall Logan Michael",
"=2009.0 Winter Logan Michael",
"=2009.0 Winter",
"=2009.1 Spring Logan Michael",
"=2009.1 Spring",
"=2009.2 Summer Logan Michael",
"=2009.2 Summer",
"=2009.3 Fall Logan Michael",
"=2009.3 Fall",
"=2009.4 Winter Logan Michael",
"=2009.4 Winter",
"=2010.0 Winter Logan Michael",
"=2010.0 Winter",
"=2010.1 Spring Logan Michael",
"=2010.1 Spring",
"=2010.2 Summer",
"=2010.3 Fall Logan Michael",
"=2010.3 Fall",
"=2010.4 Winter",
"=2011.0 Winter",
"=2011.1 Spring",
"=2011.2 Summer",
"=2011.3 Fall",
"=2011.4 Winter",
"=2012.0 Winter Chelsea 2012",
"=2012.0 Winter Chelsea",
"=2012.0 Winter",
"=2012.1 Spring Chelsea",
"=2012.1 Spring",
"=2012.2 Summer Chelsea",
"=2012.2 Summer",
"=2012.3 Fall Chelsea",
"=2012.3 Fall",
"=2012.4 Winter Chelsea",
"=2012.4 Winter",
"=2013.0 Winter Chelsea 2013",
"=2013.0 Winter Chelsea",
"=2013.0 Winter",
"=2013.1 Spring",
"=2013.2 Summer Chelsea",
"=2013.2 Summer",
"=2013.3 Fall Chelsea",
"=2013.3 Fall",
"=2013.4 Winter",
"=2014.0 Winter",
"=2014.1 Spring",
"=2014.2 Summer",
"=2014.3 Fall",
"=2014.4 Winter",
"=2015.0 Winter",
"=2015.1 Spring",
"=2015.2 Summer",
"=2015.3 Fall",
"=2015.4 Winter",
"=2016.0 Winter",
"=2016.1 Spring",
"=2016.2 Summer",
"=2016.3 Fall",
"=2016.4 Winter",
"=2017.1 Spring",
"=2017.2 Summer",
"=2017.3 Fall",
"=2017.4 Winter",
"=2018.0 Winter",
"=2018.1 Spring",
"=2018.3 Fall",
"=2018.4 Winter",
"=2019.0 Winter",
"=2019.1 Spring",
"=2019.2 Summer",
"=2019.3 Fall",
"=2019.4 Winter",
"=2020.0 Winter",
"=2020.1 Spring",
"=2020.2 Summer",
"=2020.3 Fall",
"=2020.4 Winter",
"=2021.1 Spring",
"=2021.2 Summer",
"=2021.3 Fall",
"=2021.4 Winter",
"=2022.0 Winter",
"=2022.1 Spring",
"Anthem 2015",
"April 2010",
"April 2013",
"December 2006",
"December 2010",
"Fall 2005",
"Fall 2015",
"Fall 2016",
"Fall 2017",
"Fall 2018",
"Fall 2019",
"Fall 2020",
"Fall 2021",
"February 2010",
"January 2015",
"July 2010",
"June 2010",
"Kids 2005",
"March 2013",
"May 2010",
"May 2011",
"May 2013",
"October 2005",
"October 2014",
"Spring 2013",
"Spring 2014",
"Spring 2016",
"Spring 2018",
"Spring 2019",
"Spring 2020",
"Summer 2011",
"Summer 2012",
"Summer 2013",
"Summer 2014",
"Summer 2015",
"Summer 2016",
"Summer 2017",
"Summer 2018",
"Summer 2020",
"Summer 2021",
"Winter 2015",
"Winter 2016",
"Winter 2017",
"Winter 2018",
"Winter 2019-2020",
"Winter 2020",
"zzz =2005.0 Winter Tracy Pictures",
"zzz =2005.1 Spring Tracy Pictures",
"zzz =2005.2 Summer Tracy Pictures",
"zzz =2005.3 Fall Tracy Pictures",
"zzz =2005.4 Winter Tracy Pictures",
"zzz =2006.1 Spring Tracy Pictures",
"zzz =2007.0 Winter Tracy Pictures",
"zzz =2007.2 Summer Tracy Pictures",
"zzz =2008.0 Winter Tracy Pictures",
"zzz =2008.2 Summer Tracy Pictures",
"zzz =2009.0 Winter Tracy Pictures",
"zzz =2009.2 Summer Tracy Pictures",
"zzz =2009.3 Fall Tracy Pictures",
"zzz =2009.4 Winter Tracy Pictures",
"zzz =2010.0 Winter Tracy Pictures",
"zzz =2010.1 Spring Tracy Pictures",
"zzz =2010.2 Summer Tracy Pictures",
"zzz =2010.3 Fall Tracy Pictures",
"zzz =2011.0 Winter Tracy Pictures",
"zzz =2011.1 Spring Tracy Pictures",
"zzz =2011.2 Summer Tracy Pictures",
"zzz =2011.3 Fall Tracy Pictures",
"zzz =2011.4 Winter Tracy Pictures",
"zzz =2012.0 Winter Tracy Pictures",
"zzz =2012.1 Spring Tracy Pictures",
"zzz =2012.2 Summer Tracy Pictures",
"zzz =2012.3 Fall Tracy Pictures",
"zzz =2012.4 Winter Tracy Pictures",
"zzz =2013.0 Winter Tracy Pictures",
"zzz =2013.1 Spring Tracy Pictures",
"zzz =2013.2 Summer Tracy Pictures",
"zzz =2013.3 Fall Tracy Pictures",
"zzz =2013.4 Winter Tracy Pictures",
"zzz =2014.0 Winter Tracy Pictures",
"zzz =2014.1 Spring Tracy Pictures",
"zzz =2014.2 Summer Tracy Pictures",
"zzz =2014.3 Fall Tracy Pictures",
"zzz =2014.4 Winter Tracy Pictures",
"zzz =2015.0 Winter Tracy Pictures"
]
}
}
}

View File

@ -0,0 +1 @@
[]

30
PrepareForOld/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net6.0/win-x64/PrepareForOld.dll",
"args": [],
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "externalTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processName": "PrepareForOld"
}
]
}

14
PrepareForOld/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"cSpell.words": [
"Barrick",
"bcdfghjklmnpqrstvwxyz",
"Beichler",
"Bohdi",
"Dlib",
"exif",
"nosj",
"Phares",
"Serilog",
"Vericruz"
]
}

42
PrepareForOld/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/PrepareForOld.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/PrepareForOld.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/PrepareForOld.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@ -0,0 +1,35 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.PrepareForOld.Models;
public class AppSettings
{
protected string _Company;
protected string _WorkingDirectoryName;
protected int? _MaxDegreeOfParallelism;
public string Company => _Company;
public string WorkingDirectoryName => _WorkingDirectoryName;
public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism;
// public AppSettings()
// {
// }
[JsonConstructor]
public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism)
{
_Company = company;
_WorkingDirectoryName = workingDirectoryName;
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.PrepareForOld.Models.Binder;
public class AppSettings
{
[Display(Name = "Company"), Required] public string Company { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
[Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; }
public AppSettings()
{
Company = string.Empty;
WorkingDirectoryName = string.Empty;
MaxDegreeOfParallelism = -1;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.PrepareForOld.Models.Binder;
public class Configuration
{
[Display(Name = "Property Configuration"), Required] public Property.Models.Configuration? PropertyConfiguration { get; set; }
[Display(Name = "Spelling"), Required] public string[] Spelling { get; set; }
public Configuration() => Spelling = Array.Empty<string>();
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,31 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.PrepareForOld.Models;
public class Configuration
{
protected Property.Models.Configuration? _PropertyConfiguration;
protected readonly string[] _Spelling;
public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration;
public string[] Spelling => _Spelling;
[JsonConstructor]
public Configuration(Property.Models.Configuration? propertyConfiguration, string[] spelling)
{
_PropertyConfiguration = propertyConfiguration;
_Spelling = spelling;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration;
public void Update() => _PropertyConfiguration?.Update();
}

View File

@ -0,0 +1,17 @@
namespace View_by_Distance.PrepareForOld.Models.SaveTabSeparatedValues;
public class ImageExifInfo
{
public int Index { get; set; }
public DateTime CreationTime { get; set; }
public DateTime LastWriteTime { get; set; }
public DateTime? DateTime { get; set; }
public DateTime? DateTimeDigitized { get; set; }
public DateTime? DateTimeOriginal { get; set; }
public DateTime? GPSDateStamp { get; set; }
public string? Make { get; set; }
public string? Model { get; set; }
public string? Orientation { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.PrepareForOld.Models.SaveTabSeparatedValues;
public class IndexInfo
{
public int Index { get; set; }
public string[]? FileSegmentCollection { get; set; }
public DateTime DateTime { get; set; }
}

View File

@ -0,0 +1,40 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace View_by_Distance.PrepareForOld.Models.Stateless;
public abstract class AppSettings
{
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
namespace View_by_Distance.PrepareForOld.Models.Stateless;
public abstract class Configuration
{
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory, Property.Models.Configuration propertyConfiguration)
{
Models.Configuration? result;
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Binder.Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
Binder.Configuration configuration = configurationSection.Get<Binder.Configuration>();
string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.Configuration>(json);
if (result is null)
throw new Exception(json);
string jsonThis = result.ToString();
result.Set(propertyConfiguration);
result.Update();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.PrepareForOld.Models.Stateless;
public static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

View File

@ -0,0 +1,666 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
using System.Text.RegularExpressions;
using View_by_Distance.PrepareForOld.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.PrepareForOld;
public class PrepareForOld
{
private readonly Serilog.ILogger? _Log;
private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment;
private readonly Models.Configuration _Configuration;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly List<(string Find, string Replace)> _SpellingFindReplace;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs;
public PrepareForOld(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{
if (isSilent)
{ }
if (console is null)
{ }
string spellingA;
string spellingB;
_AppSettings = appSettings;
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!");
_SpellingFindReplace = new();
_IsEnvironment = isEnvironment;
_Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<PrepareForOld>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory);
Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration);
if (propertyConfiguration.IgnoreExtensions is null)
throw new Exception($"{nameof(propertyConfiguration.IgnoreExtensions)} is null!");
if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!");
for (int i = 0; i < configuration.Spelling.Length; i++)
{
spellingA = configuration.Spelling[i];
spellingB = configuration.Spelling[i + 1];
if (spellingB.Contains(spellingA))
throw new Exception("Change configuration!");
_SpellingFindReplace.Add(new(spellingA, spellingB));
i += 1;
}
string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories);
foreach (string dbFile in dbFiles)
File.Delete(dbFile);
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A_Property), "{}");
if (!Directory.Exists(aPropertySingletonDirectory))
throw new Exception(aPropertySingletonDirectory);
ConsoleKey? consoleKey = null;
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Execute {nameof(VerifyAgainstIndexInfoJsonFiles)} \"Y(es)\" or \"N(o)\"?");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
break;
}
_Log.Information(". . .");
if (consoleKey == ConsoleKey.Y)
VerifyAgainstIndexInfoJsonFiles(propertyConfiguration, aPropertySingletonDirectory);
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Execute {nameof(SaveTabSeparatedValues)} \"Y(es)\" or \"N(o)\"?");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
break;
}
_Log.Information(". . .");
if (consoleKey == ConsoleKey.Y)
SaveTabSeparatedValues(propertyConfiguration, aPropertySingletonDirectory);
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Execute {nameof(ReSaveJsonFiles)} \"Y(es)\" or \"N(o)\"?");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
break;
}
_Log.Information(". . .");
if (consoleKey == ConsoleKey.Y)
ReSaveJsonFiles();
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information($"Execute {nameof(CopyMissingImagesLogs)} \"Y(es)\" or \"N(o)\"?");
consoleKey = Console.ReadKey().Key;
if (consoleKey is ConsoleKey.Y or ConsoleKey.N)
break;
}
_Log.Information(". . .");
if (consoleKey == ConsoleKey.Y)
CopyMissingImagesLogs();
string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message);
if (_Exceptions.Count != 0)
throw new Exception(message);
_Configuration = configuration;
}
private static void Verify(Models.Configuration configuration)
{
if (configuration.Spelling is null || !configuration.Spelling.Any())
throw new Exception($"{nameof(configuration.Spelling)} should have at least one!");
}
private static List<Models.SaveTabSeparatedValues.ImageExifInfo> GetExifCollection(string infoDirectory, string infoDirectoryExtra, bool checkDistinct)
{
List<Models.SaveTabSeparatedValues.ImageExifInfo> results = new();
string json;
Models.SaveTabSeparatedValues.ImageExifInfo[]? exifCollection;
List<string> exifInfoFiles = Directory.GetFiles(infoDirectory, "ImageExifInfo.json", SearchOption.AllDirectories).ToList();
if (!string.IsNullOrEmpty(infoDirectoryExtra))
exifInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "ImageExifInfo.json", SearchOption.AllDirectories));
foreach (string exifInfoFile in exifInfoFiles)
{
json = File.ReadAllText(exifInfoFile);
exifCollection = JsonSerializer.Deserialize<Models.SaveTabSeparatedValues.ImageExifInfo[]>(json);
if (exifCollection is null)
continue;
results.AddRange(exifCollection);
}
if (checkDistinct)
{
int[] check = (from l in results select l.Index).Distinct().ToArray();
if (check.Length != results.Count)
throw new Exception();
}
return results;
}
private List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> GetIndexCollection(string infoDirectory, string infoDirectoryExtra, bool checkDistinct)
{
List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> results = new();
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
long ticks;
string json;
string extension;
string corrected;
string regexResult;
string relativeDirectory;
List<DateTime> dateTimes;
string fileNameWithoutExtension;
string firstFileSegmentCollection;
Dictionary<int, long> keyValuePairs = new();
Models.SaveTabSeparatedValues.IndexInfo[]? indexCollection;
List<Models.SaveTabSeparatedValues.ImageExifInfo> exifCollection = GetExifCollection(infoDirectory, infoDirectoryExtra, checkDistinct);
List<string> indexInfoFiles = Directory.GetFiles(infoDirectory, "IndexInfo.json", SearchOption.AllDirectories).ToList();
if (!string.IsNullOrEmpty(infoDirectoryExtra))
indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryExtra, "IndexInfo.json", SearchOption.AllDirectories));
foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection)
{
dateTimes = Property.Models.Stateless.A_Property.GetDateTimes(exifInfo.CreationTime, exifInfo.LastWriteTime, exifInfo.DateTime, exifInfo.DateTimeDigitized, exifInfo.DateTimeOriginal, exifInfo.GPSDateStamp);
if (!checkDistinct && keyValuePairs.ContainsKey(exifInfo.Index))
continue;
keyValuePairs.Add(exifInfo.Index, dateTimes.Min().Ticks);
}
foreach (string indexInfoFile in indexInfoFiles)
{
json = File.ReadAllText(indexInfoFile);
indexCollection = JsonSerializer.Deserialize<Models.SaveTabSeparatedValues.IndexInfo[]>(json);
if (indexCollection is null)
continue;
foreach (Models.SaveTabSeparatedValues.IndexInfo indexInfo in indexCollection)
{
if (indexInfo.FileSegmentCollection is null)
continue;
// if (indexInfo.FileSegmentCollection.Length != 1)
// continue;
ticks = keyValuePairs[indexInfo.Index];
firstFileSegmentCollection = indexInfo.FileSegmentCollection[0];
extension = Path.GetExtension(firstFileSegmentCollection);
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(firstFileSegmentCollection);
corrected = firstFileSegmentCollection[..(firstFileSegmentCollection.Length - extension.Length)];
relativeDirectory = firstFileSegmentCollection[..(firstFileSegmentCollection.Length - fileNameWithoutExtension.Length - extension.Length)];
if ((from l in _SpellingFindReplace where corrected.Contains(l.Find) select true).Any())
{
foreach ((string find, string replace) in _SpellingFindReplace)
corrected = corrected.Replace(find, replace);
}
if (string.IsNullOrEmpty(_Configuration.PropertyConfiguration.Pattern))
regexResult = corrected;
else
regexResult = Regex.Replace(corrected, _Configuration.PropertyConfiguration.Pattern, string.Empty);
results.Add(new(indexInfo.Index, ticks, relativeDirectory, fileNameWithoutExtension, extension, regexResult));
}
}
return results;
}
private static List<int> GetUseTabSeparatedValueIndices(string useDirectory)
{
List<int> results = new();
string[] lines;
string[] segments;
string[] tabSeparatedValueFiles = Directory.GetFiles(useDirectory, "*.tsv", SearchOption.TopDirectoryOnly);
foreach (string tabSeparatedValueFile in tabSeparatedValueFiles)
{
lines = File.ReadAllLines(tabSeparatedValueFile);
foreach (string line in lines)
{
if (string.IsNullOrEmpty(line))
continue;
segments = line.Split('\t');
if (segments.Length < 1)
continue;
if (!int.TryParse(segments[0], out int index))
continue;
results.Add(index);
}
}
return results.Distinct().OrderBy(l => l).ToList();
}
private void SaveTabSeparatedValues(Property.Models.Configuration configuration, string aPropertySingletonDirectory)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory);
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new Exception($"{nameof(rootDirectoryParent)} is null!");
int z = 0;
int mappedIndex;
int? propertyId;
long? propertyTicks;
int loadLessThan = 7;
string useDirectory = Path.Combine(rootDirectoryParent, "Use - ==");
if (!Directory.Exists(useDirectory))
_ = Directory.CreateDirectory(useDirectory);
string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp");
if (!Directory.Exists(tempDirectory))
_ = Directory.CreateDirectory(tempDirectory);
string diffRootDirectory = string.Empty;
List<PropertyCompare.Models.PropertyCompare> duplicates = new();
string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared");
string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json");
string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07");
string infoDirectoryExtra = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Extra", "2022-04-14");
List<int> mappedIndices = GetUseTabSeparatedValueIndices(useDirectory);
List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new();
PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory);
PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan, duplicates, deleteExtension: false);
{
long ticks = DateTime.Now.Ticks;
string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray();
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "[{}]");
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);
}
List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryExtra, checkDistinct: true);
foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection)
{
z += 1;
if (_IsEnvironment.Development && z % 1000 == 0)
_Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}");
propertyId = null;
propertyTicks = null;
foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompareCollection)
{
if (propertyCompare?.Property?.Id is null)
continue;
if (ticks != propertyCompare.MinimumDateTime.Ticks)
{
// if (ticks > propertyCompare.MinimumDateTime.AddHours(18).Ticks || ticks < propertyCompare.MinimumDateTime.AddHours(-18).Ticks)
continue;
}
if (!regexResult.Equals(propertyCompare.RegexResult, StringComparison.CurrentCultureIgnoreCase))
continue;
propertyId = propertyCompare.Property.Id;
propertyTicks = propertyCompare.MinimumDateTime.Ticks;
mappedIndex = mappedIndices.IndexOf(index);
if (mappedIndex > -1)
mappedIndices.RemoveAt(mappedIndex);
break;
}
collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks));
}
(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] matched = (from l in collection where l.PropertyId.HasValue select l).ToArray();
(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] notMatched = (from l in collection where l.PropertyId is null select l).ToArray();
string[] duplicatesLines = (
from l
in duplicates
select $"{l.Property.Id}\t{l.RegexResult}\t{l.MinimumDateTime:yyyy-MM-dd_HH-mm-ss}\t{l.MinimumDateTime}\t{l.RelativeDirectory}\t{l.FileNameWithoutExtension}{l.Extension}.___"
).ToArray();
string[] matchedLines = (
from l
in matched
select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}"
).ToArray();
List<string> notMatchedLines = (
from l
in notMatched
where !mappedIndices.Contains(l.Index)
select $"{l.Index}\t______________\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t_________________\t{l.RelativeDirectory}\t{l.FileName}"
).ToList();
{
long ticks = DateTime.Now.Ticks;
notMatchedLines.AddRange(from l in mappedIndices select $"{l}\tFrom other files");
File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.tsv", matchedLines);
File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.txt", duplicatesLines);
File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}-Not.tsv", notMatchedLines);
}
_Log.Debug($"Done with {nameof(SaveTabSeparatedValues)}");
}
private static void GetUseTabSeparatedValueLines(string useDirectory, Dictionary<int, List<string>> mappedLines)
{
string[] lines;
string[] segments;
string useDirectoryName = Path.GetFileName(useDirectory).Split('-')[1].Trim();
string[] tabSeparatedValueFiles = Directory.GetFiles(useDirectory, "*.tsv", SearchOption.TopDirectoryOnly);
foreach (string tabSeparatedValueFile in tabSeparatedValueFiles)
{
lines = File.ReadAllLines(tabSeparatedValueFile);
foreach (string line in lines)
{
if (string.IsNullOrEmpty(line))
continue;
segments = line.Split('\t');
if (segments.Length < 1)
continue;
if (!int.TryParse(segments[0], out int index))
continue;
if (!mappedLines.ContainsKey(index))
mappedLines.Add(index, new());
mappedLines[index].Add($"{line},\t{useDirectoryName}");
}
}
}
private static void Populate(Dictionary<int, List<int>> keyValuePairs, Dictionary<int, List<string>> mappedLines)
{
string[] segments;
foreach (KeyValuePair<int, List<string>> keyValuePair in mappedLines)
{
segments = keyValuePair.Value[0].Split('\t');
if (segments.Length < 2)
continue;
if (!int.TryParse(segments[1], out int id))
continue;
if (!keyValuePairs.ContainsKey(id))
keyValuePairs.Add(id, new() { id });
keyValuePairs[id].Add(keyValuePair.Key);
}
}
private static Dictionary<int, int> GetUseTabSeparatedValue(string useEqualsDirectory, string use18HoursDirectory, string useAnyDateDirectory, Dictionary<int, List<int>> keyValuePairs, List<string> lines)
{
Dictionary<int, int> results = new();
string[] segments;
Dictionary<int, List<string>> mappedLines = new();
GetUseTabSeparatedValueLines(useEqualsDirectory, mappedLines);
GetUseTabSeparatedValueLines(use18HoursDirectory, mappedLines);
GetUseTabSeparatedValueLines(useAnyDateDirectory, mappedLines);
Populate(keyValuePairs, mappedLines);
foreach (KeyValuePair<int, List<string>> keyValuePair in mappedLines)
{
segments = keyValuePair.Value[0].Split('\t');
if (segments.Length < 2)
continue;
if (!int.TryParse(segments[1], out int id))
continue;
foreach (string line in keyValuePair.Value)
lines.Add(line);
results.Add(keyValuePair.Key, id);
}
return results;
}
private static void ReSaveExifFiles(string infoDirectory, string infoDirectoryIgnore, Dictionary<int, int> findReplace, List<int> missingIndices)
{
string json;
int propertyId;
Models.SaveTabSeparatedValues.ImageExifInfo[]? exifCollection;
List<string> exifInfoFiles = Directory.GetFiles(infoDirectory, "ImageExifInfo.json", SearchOption.AllDirectories).ToList();
exifInfoFiles.AddRange(Directory.GetFiles(infoDirectoryIgnore, "ImageExifInfo.json", SearchOption.AllDirectories));
foreach (string exifInfoFile in exifInfoFiles)
{
json = File.ReadAllText(exifInfoFile);
exifCollection = JsonSerializer.Deserialize<Models.SaveTabSeparatedValues.ImageExifInfo[]>(json);
if (exifCollection is null)
continue;
foreach (Models.SaveTabSeparatedValues.ImageExifInfo exifInfo in exifCollection)
{
if (missingIndices.Contains(exifInfo.Index))
continue;
propertyId = findReplace[exifInfo.Index];
exifInfo.Index = propertyId;
}
json = JsonSerializer.Serialize(exifCollection);
File.WriteAllText(exifInfoFile, json);
}
}
private static void ReSaveNamedFaceInfoFile(string namedFaceInfoFile, Dictionary<int, int> findReplace, List<int> missingIndices)
{
Dictionary<int, string[]> destination = new();
string json = File.ReadAllText(namedFaceInfoFile);
List<(int PropertyId, string[] Birthdays)> collection = new();
JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true };
Dictionary<int, string[]>? source = JsonSerializer.Deserialize<Dictionary<int, string[]>>(json);
if (source is null)
throw new Exception($"{nameof(source)} is null!");
{
int propertyId;
foreach (KeyValuePair<int, string[]> keyValuePair in source)
{
if (missingIndices.Contains(keyValuePair.Key))
continue;
propertyId = findReplace[keyValuePair.Key];
collection.Add(new(propertyId, keyValuePair.Value));
}
}
foreach ((int propertyId, string[] birthdays) in collection.OrderBy(l => l.PropertyId))
{
if (destination.ContainsKey(propertyId))
{
if (birthdays.Length != destination[propertyId].Length)
throw new Exception($"{birthdays.Length} != {destination[propertyId].Length}");
if (birthdays[0] != destination[propertyId][0])
throw new Exception($"{birthdays[0]} != {destination[propertyId][0]}");
continue;
}
destination.Add(propertyId, birthdays);
}
json = JsonSerializer.Serialize(destination, jsonSerializerOptions);
File.WriteAllText(namedFaceInfoFile, json);
}
private static void ReSaveIndexFiles(string infoDirectory, string infoDirectoryIgnore, Dictionary<int, int> findReplace, List<int> missingIndices)
{
string json;
int propertyId;
Models.SaveTabSeparatedValues.IndexInfo[]? indexCollection;
List<string> indexInfoFiles = Directory.GetFiles(infoDirectory, "IndexInfo.json", SearchOption.AllDirectories).ToList();
indexInfoFiles.AddRange(Directory.GetFiles(infoDirectoryIgnore, "IndexInfo.json", SearchOption.AllDirectories));
foreach (string indexInfoFile in indexInfoFiles)
{
json = File.ReadAllText(indexInfoFile);
indexCollection = JsonSerializer.Deserialize<Models.SaveTabSeparatedValues.IndexInfo[]>(json);
if (indexCollection is null)
continue;
foreach (Models.SaveTabSeparatedValues.IndexInfo indexInfo in indexCollection)
{
if (missingIndices.Contains(indexInfo.Index))
continue;
propertyId = findReplace[indexInfo.Index];
indexInfo.Index = propertyId;
}
json = JsonSerializer.Serialize(indexCollection);
File.WriteAllText(indexInfoFile, json);
}
}
private void ReSaveJsonFiles()
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory);
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new Exception($"{nameof(rootDirectoryParent)} is null!");
int z = 0;
int propertyId;
List<int> missingIndices = new();
Dictionary<int, int> findReplace = new();
List<string> useTabSeparatedValueLines = new();
Dictionary<int, List<int>> keyValuePairs = new();
string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp");
string useEqualsDirectory = Path.Combine(rootDirectoryParent, "Use - ==");
string use18HoursDirectory = Path.Combine(rootDirectoryParent, "Use - 18 Hours");
string useAnyDateDirectory = Path.Combine(rootDirectoryParent, "Use - Any Date");
string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared");
string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json");
string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07");
string infoDirectoryIgnore = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Ignore", "2022-04-14");
Dictionary<int, int> useTabSeparatedValueCollection = GetUseTabSeparatedValue(useEqualsDirectory, use18HoursDirectory, useAnyDateDirectory, keyValuePairs, useTabSeparatedValueLines);
{
long ticks = DateTime.Now.Ticks;
string json = JsonSerializer.Serialize(keyValuePairs, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText($"{tempDirectory}/{nameof(keyValuePairs)}-{ticks}.json", json);
}
List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryIgnore, checkDistinct: true);
foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection)
{
z += 1;
if (_IsEnvironment.Development && z % 1000 == 0)
_Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}");
if (!useTabSeparatedValueCollection.ContainsKey(index))
{
missingIndices.Add(index);
continue;
}
propertyId = useTabSeparatedValueCollection[index];
findReplace.Add(index, propertyId);
}
ReSaveIndexFiles(infoDirectory, infoDirectoryIgnore, findReplace, missingIndices);
ReSaveExifFiles(infoDirectory, infoDirectoryIgnore, findReplace, missingIndices);
ReSaveNamedFaceInfoFile(namedFaceInfoFile, findReplace, missingIndices);
{
long ticks = DateTime.Now.Ticks;
File.WriteAllLines($"{tempDirectory}/{nameof(useTabSeparatedValueLines)}-{ticks}.tsv", useTabSeparatedValueLines);
File.WriteAllText($"{tempDirectory}/{nameof(missingIndices)}-{ticks}.txt", string.Join(Environment.NewLine, missingIndices));
}
_Log.Debug($"Done with {nameof(ReSaveJsonFiles)}");
}
private void CopyMissingImagesLogs()
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory);
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new Exception($"{nameof(rootDirectoryParent)} is null!");
int z = 0;
int propertyId;
Dictionary<int, int> findReplace = new();
List<int> missingIndices = new();
List<string> useTabSeparatedValueLines = new();
Dictionary<int, List<int>> keyValuePairs = new();
string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp");
string currentDirectory = Path.Combine(rootDirectoryParent, "@) Images");
string useEqualsDirectory = Path.Combine(rootDirectoryParent, "Use - ==");
string use18HoursDirectory = Path.Combine(rootDirectoryParent, "Use - 18 Hours");
string useAnyDateDirectory = Path.Combine(rootDirectoryParent, "Use - Any Date");
string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared");
string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json");
string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07");
string infoDirectoryIgnore = Path.Combine(imageSharedDirectory, "Images - 4) Info - - - Ignore", "2022-04-14");
Dictionary<int, int> useTabSeparatedValueCollection = GetUseTabSeparatedValue(useEqualsDirectory, use18HoursDirectory, useAnyDateDirectory, keyValuePairs, useTabSeparatedValueLines);
{
long ticks = DateTime.Now.Ticks;
string json = JsonSerializer.Serialize(keyValuePairs, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText($"{tempDirectory}/{nameof(keyValuePairs)}-{ticks}.json", json);
}
List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryIgnore, checkDistinct: false);
foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection)
{
z += 1;
if (_IsEnvironment.Development && z % 1000 == 0)
_Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}");
if (!useTabSeparatedValueCollection.ContainsKey(index))
{
missingIndices.Add(index);
continue;
}
propertyId = useTabSeparatedValueCollection[index];
findReplace.Add(index, propertyId);
}
{
long ticks = DateTime.Now.Ticks;
File.WriteAllLines($"{tempDirectory}/{nameof(useTabSeparatedValueLines)}-{ticks}.tsv", useTabSeparatedValueLines);
File.WriteAllText($"{tempDirectory}/{nameof(missingIndices)}-{ticks}.txt", string.Join(Environment.NewLine, missingIndices));
}
_Log.Debug($"Done with {nameof(CopyMissingImagesLogs)}");
}
private static Dictionary<int, List<PropertyCompare.Models.PropertyCompare>> GetKeyValuePairs(PropertyCompare.Models.PropertyCompare[] propertyCompares)
{
Dictionary<int, List<PropertyCompare.Models.PropertyCompare>> results = new();
foreach (PropertyCompare.Models.PropertyCompare propertyCompare in propertyCompares)
{
if (propertyCompare?.Property?.Id is null)
continue;
if (!results.ContainsKey(propertyCompare.Property.Id.Value))
results.Add(propertyCompare.Property.Id.Value, new());
results[propertyCompare.Property.Id.Value].Add(propertyCompare);
}
return results;
}
private void VerifyAgainstIndexInfoJsonFiles(Property.Models.Configuration configuration, string aPropertySingletonDirectory)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string? rootDirectoryParent = Path.GetDirectoryName(_Configuration.PropertyConfiguration.RootDirectory);
if (string.IsNullOrEmpty(rootDirectoryParent))
throw new Exception($"{nameof(rootDirectoryParent)} is null!");
int z = 0;
int? propertyId;
long? propertyTicks;
int loadLessThan = 7;
string diffRootDirectory = string.Empty;
PropertyCompare.Models.PropertyCompare propertyCompare;
string tempDirectory = Path.Combine(rootDirectoryParent, "Tmp");
if (!Directory.Exists(tempDirectory))
_ = Directory.CreateDirectory(tempDirectory);
string imageSharedDirectory = Path.Combine(rootDirectoryParent, "Images - Shared");
string namedFaceInfoFile = Path.Combine(imageSharedDirectory, "NamedFaceInfo.json");
string infoDirectory = Path.Combine(imageSharedDirectory, "Images - 4) Info", "2020-06-07");
List<(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)> collection = new();
PropertyCompare.Models.PropertyCompareLogic propertyCompareLogic = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, _SpellingFindReplace, diffRootDirectory);
PropertyCompare.Models.PropertyCompare[] propertyCompareCollection = propertyCompareLogic.Get(aPropertySingletonDirectory, loadLessThan);
{
long ticks = DateTime.Now.Ticks;
string[] lines = (from l in propertyCompareCollection select l.GetSelect()).ToArray();
string aPropertyCollectionDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "[{}]");
File.WriteAllLines(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.txt"), lines);
string json = JsonSerializer.Serialize(propertyCompareCollection, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(Path.Join(aPropertyCollectionDirectory, $". . . Ids - {ticks}.nosj"), json);
}
Dictionary<int, List<PropertyCompare.Models.PropertyCompare>> keyValuePairs = GetKeyValuePairs(propertyCompareCollection);
List<(int Index, long Ticks, string RelativeDirectory, string FileNameWithoutExtension, string Extension, string RegexResult)> indexCollection = GetIndexCollection(infoDirectory, infoDirectoryExtra: string.Empty, checkDistinct: false);
foreach ((int index, long ticks, string relativeDirectory, string fileNameWithoutExtension, string extension, string regexResult) in indexCollection)
{
z += 1;
if (_IsEnvironment.Development && z % 1000 == 0)
_Log.Debug($"{z}) Loop {_Configuration.PropertyConfiguration.RootDirectory}");
propertyId = null;
propertyTicks = null;
if (keyValuePairs.ContainsKey(index))
{
propertyCompare = keyValuePairs[index][0];
if (propertyCompare?.Property?.Id is null)
continue;
propertyId = propertyCompare.Property.Id;
propertyTicks = propertyCompare.MinimumDateTime.Ticks;
}
collection.Add(new(index, relativeDirectory, $"{fileNameWithoutExtension}{extension}", regexResult, ticks, propertyId, propertyTicks));
}
(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] matched = (from l in collection where l.PropertyId.HasValue select l).ToArray();
(int Index, string RelativeDirectory, string FileName, string RegexResult, long Ticks, int? PropertyId, long? PropertyTicks)[] notMatched = (from l in collection where l.PropertyId is null select l).ToArray();
string[] matchedLines = (
from l
in matched
select $"{l.Index}\t{l.PropertyId}\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t{l.PropertyTicks}\t{l.RelativeDirectory}\t{l.FileName}"
).ToArray();
List<string> notMatchedLines = (
from l
in notMatched
select $"{l.Index}\t______________\t{l.RegexResult}\t{new DateTime(l.Ticks):yyyy-MM-dd_HH-mm-ss}\t_________________\t{l.RelativeDirectory}\t{l.FileName}"
).ToList();
{
long ticks = DateTime.Now.Ticks;
File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}.tsv", matchedLines);
File.WriteAllLines($"{tempDirectory}/{collection.Count}-{ticks}-Not.tsv", notMatchedLines);
}
_Log.Debug($"Done with {nameof(VerifyAgainstIndexInfoJsonFiles)}");
}
}

View File

@ -0,0 +1,60 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.PrepareForOld</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

71
PrepareForOld/Program.cs Normal file
View File

@ -0,0 +1,71 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.PrepareForOld.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.PrepareForOld;
public class Program
{
public static void Secondary(List<string> args)
{
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
IConfigurationRoot configurationRoot = configurationBuilder.Build();
AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot);
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception("MaxDegreeOfParallelism must be set!");
if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount)
throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!");
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>();
int silentIndex = args.IndexOf("s");
if (silentIndex > -1)
args.RemoveAt(silentIndex);
try
{
if (args is null)
throw new Exception("args is null!");
Shared.Models.Console console = new();
PrepareForOld dlibDotNet = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console);
}
catch (Exception ex)
{
log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace));
}
finally
{
Log.CloseAndFlush();
}
if (silentIndex > -1)
log.Debug("Done. Bye");
else
{
log.Debug("Done. Press 'Enter' to end");
_ = Console.ReadLine();
}
}
public static void Main(string[] args)
{
if (args is not null)
Secondary(args.ToList());
else
Secondary(new List<string>());
}
}

View File

@ -0,0 +1,364 @@
{
"Company": "Mike Phares",
"Linux": {},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MaxDegreeOfParallelism": 6,
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"DateGroup": "2022-04-07",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"KeepFullPath": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": false,
"PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Pictures",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"PropertyContentCollectionFiles": [],
"Spelling": [
"Bday",
"Birthday",
"Childrens",
"Children's",
"Darrens",
"Darren's",
"Febuary",
"February",
"Feburay",
"February",
"Frist",
"First",
"Goolgle",
"Google",
"Kristys",
"Kristy's",
"Micael's",
"Michael's",
"Origanls",
"Originals",
"Patrict",
"Patrick",
"Sebtember",
"September"
],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".amr",
".AMR",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"VerifyToSeason": [
". 2000",
". 2001",
". 2002",
". 2003",
". 2004",
". 2005",
". 2006",
". 2007",
". 2008",
". 2009",
". 2010",
". 2011",
". 2012",
". 2013",
". 2014",
". 2015",
". 2016",
". 2017",
". 2018",
". 2019",
". 2020",
". 2021",
". 2022",
". 2023",
". 2024",
". 2025",
". 2026",
". 2027",
". 2028",
". 2029",
"=2000.0 Winter",
"=2002.1 Spring",
"=2002.4 Winter",
"=2003.0 Winter",
"=2003.1 Spring",
"=2003.3 Fall",
"=2003.4 Winter",
"=2004.0 Winter",
"=2005.1 Spring",
"=2005.2 Summer",
"=2005.3 Fall",
"=2005.4 Winter",
"=2006.0 Winter",
"=2006.1 Spring",
"=2006.3 Fall",
"=2007.0 Winter",
"=2007.2 Summer Logan Michael",
"=2007.2 Summer",
"=2007.3 Fall Logan Michael",
"=2007.4 Winter Logan Michael",
"=2008.0 Winter Logan Michael",
"=2008.1 Spring Logan Michael",
"=2008.2 Summer Logan Michael",
"=2008.2 Summer",
"=2008.3 Fall Logan Michael",
"=2009.0 Winter Logan Michael",
"=2009.0 Winter",
"=2009.1 Spring Logan Michael",
"=2009.1 Spring",
"=2009.2 Summer Logan Michael",
"=2009.2 Summer",
"=2009.3 Fall Logan Michael",
"=2009.3 Fall",
"=2009.4 Winter Logan Michael",
"=2009.4 Winter",
"=2010.0 Winter Logan Michael",
"=2010.0 Winter",
"=2010.1 Spring Logan Michael",
"=2010.1 Spring",
"=2010.2 Summer",
"=2010.3 Fall Logan Michael",
"=2010.3 Fall",
"=2010.4 Winter",
"=2011.0 Winter",
"=2011.1 Spring",
"=2011.2 Summer",
"=2011.3 Fall",
"=2011.4 Winter",
"=2012.0 Winter Chelsea 2012",
"=2012.0 Winter Chelsea",
"=2012.0 Winter",
"=2012.1 Spring Chelsea",
"=2012.1 Spring",
"=2012.2 Summer Chelsea",
"=2012.2 Summer",
"=2012.3 Fall Chelsea",
"=2012.3 Fall",
"=2012.4 Winter Chelsea",
"=2012.4 Winter",
"=2013.0 Winter Chelsea 2013",
"=2013.0 Winter Chelsea",
"=2013.0 Winter",
"=2013.1 Spring",
"=2013.2 Summer Chelsea",
"=2013.2 Summer",
"=2013.3 Fall Chelsea",
"=2013.3 Fall",
"=2013.4 Winter",
"=2014.0 Winter",
"=2014.1 Spring",
"=2014.2 Summer",
"=2014.3 Fall",
"=2014.4 Winter",
"=2015.0 Winter",
"=2015.1 Spring",
"=2015.2 Summer",
"=2015.3 Fall",
"=2015.4 Winter",
"=2016.0 Winter",
"=2016.1 Spring",
"=2016.2 Summer",
"=2016.3 Fall",
"=2016.4 Winter",
"=2017.1 Spring",
"=2017.2 Summer",
"=2017.3 Fall",
"=2017.4 Winter",
"=2018.0 Winter",
"=2018.1 Spring",
"=2018.3 Fall",
"=2018.4 Winter",
"=2019.0 Winter",
"=2019.1 Spring",
"=2019.2 Summer",
"=2019.3 Fall",
"=2019.4 Winter",
"=2020.0 Winter",
"=2020.1 Spring",
"=2020.2 Summer",
"=2020.3 Fall",
"=2020.4 Winter",
"=2021.1 Spring",
"=2021.2 Summer",
"=2021.3 Fall",
"=2021.4 Winter",
"=2022.0 Winter",
"=2022.1 Spring",
"Anthem 2015",
"April 2010",
"April 2013",
"December 2006",
"December 2010",
"Fall 2005",
"Fall 2015",
"Fall 2016",
"Fall 2017",
"Fall 2018",
"Fall 2019",
"Fall 2020",
"Fall 2021",
"February 2010",
"January 2015",
"July 2010",
"June 2010",
"Kids 2005",
"March 2013",
"May 2010",
"May 2011",
"May 2013",
"October 2005",
"October 2014",
"Spring 2013",
"Spring 2014",
"Spring 2016",
"Spring 2018",
"Spring 2019",
"Spring 2020",
"Summer 2011",
"Summer 2012",
"Summer 2013",
"Summer 2014",
"Summer 2015",
"Summer 2016",
"Summer 2017",
"Summer 2018",
"Summer 2020",
"Summer 2021",
"Winter 2015",
"Winter 2016",
"Winter 2017",
"Winter 2018",
"Winter 2019-2020",
"Winter 2020",
"zzz =2005.0 Winter Tracy Pictures",
"zzz =2005.1 Spring Tracy Pictures",
"zzz =2005.2 Summer Tracy Pictures",
"zzz =2005.3 Fall Tracy Pictures",
"zzz =2005.4 Winter Tracy Pictures",
"zzz =2006.1 Spring Tracy Pictures",
"zzz =2007.0 Winter Tracy Pictures",
"zzz =2007.2 Summer Tracy Pictures",
"zzz =2008.0 Winter Tracy Pictures",
"zzz =2008.2 Summer Tracy Pictures",
"zzz =2009.0 Winter Tracy Pictures",
"zzz =2009.2 Summer Tracy Pictures",
"zzz =2009.3 Fall Tracy Pictures",
"zzz =2009.4 Winter Tracy Pictures",
"zzz =2010.0 Winter Tracy Pictures",
"zzz =2010.1 Spring Tracy Pictures",
"zzz =2010.2 Summer Tracy Pictures",
"zzz =2010.3 Fall Tracy Pictures",
"zzz =2011.0 Winter Tracy Pictures",
"zzz =2011.1 Spring Tracy Pictures",
"zzz =2011.2 Summer Tracy Pictures",
"zzz =2011.3 Fall Tracy Pictures",
"zzz =2011.4 Winter Tracy Pictures",
"zzz =2012.0 Winter Tracy Pictures",
"zzz =2012.1 Spring Tracy Pictures",
"zzz =2012.2 Summer Tracy Pictures",
"zzz =2012.3 Fall Tracy Pictures",
"zzz =2012.4 Winter Tracy Pictures",
"zzz =2013.0 Winter Tracy Pictures",
"zzz =2013.1 Spring Tracy Pictures",
"zzz =2013.2 Summer Tracy Pictures",
"zzz =2013.3 Fall Tracy Pictures",
"zzz =2013.4 Winter Tracy Pictures",
"zzz =2014.0 Winter Tracy Pictures",
"zzz =2014.1 Spring Tracy Pictures",
"zzz =2014.2 Summer Tracy Pictures",
"zzz =2014.3 Fall Tracy Pictures",
"zzz =2014.4 Winter Tracy Pictures",
"zzz =2015.0 Winter Tracy Pictures"
]
}
}
}

Some files were not shown because too many files have changed in this diff Show More