Init
This commit is contained in:
commit
4a3e24236f
243
.editorconfig
Normal file
243
.editorconfig
Normal 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
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
461
.gitignore
vendored
Normal file
461
.gitignore
vendored
Normal 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
10
.txt
Normal 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
28
.vscode/launch.json
vendored
Normal 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
11
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"Barrick",
|
||||||
|
"Beichler",
|
||||||
|
"Bohdi",
|
||||||
|
"Dlib",
|
||||||
|
"Phares",
|
||||||
|
"Serilog",
|
||||||
|
"Vericruz"
|
||||||
|
]
|
||||||
|
}
|
17
.vscode/tasks.json
vendored
Normal file
17
.vscode/tasks.json
vendored
Normal 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
1
Compare/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
32
Compare/.vscode/launch.json
vendored
Normal file
32
Compare/.vscode/launch.json
vendored
Normal 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
14
Compare/.vscode/settings.json
vendored
Normal 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
42
Compare/.vscode/tasks.json
vendored
Normal 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
906
Compare/Compare.cs
Normal 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
67
Compare/Compare.csproj
Normal 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>
|
35
Compare/Models/AppSettings.cs
Normal file
35
Compare/Models/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
Compare/Models/Binder/AppSettings.cs
Normal file
26
Compare/Models/Binder/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
Compare/Models/Binder/Configuration.cs
Normal file
30
Compare/Models/Binder/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
Compare/Models/Configuration.cs
Normal file
43
Compare/Models/Configuration.cs
Normal 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();
|
||||||
|
|
||||||
|
}
|
40
Compare/Models/Stateless/AppSettings.cs
Normal file
40
Compare/Models/Stateless/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
Compare/Models/Stateless/Configuration.cs
Normal file
44
Compare/Models/Stateless/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
Compare/Models/Stateless/SerilogExtensionMethods.cs
Normal file
10
Compare/Models/Stateless/SerilogExtensionMethods.cs
Normal 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
71
Compare/Program.cs
Normal 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>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1609
Compare/appsettings.Development.json
Normal file
1609
Compare/appsettings.Development.json
Normal file
File diff suppressed because it is too large
Load Diff
1609
Compare/appsettings.json
Normal file
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
1
Date-Group/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
30
Date-Group/.vscode/launch.json
vendored
Normal file
30
Date-Group/.vscode/launch.json
vendored
Normal 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
11
Date-Group/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"Barrick",
|
||||||
|
"Beichler",
|
||||||
|
"Bohdi",
|
||||||
|
"Dlib",
|
||||||
|
"Phares",
|
||||||
|
"Serilog",
|
||||||
|
"Vericruz"
|
||||||
|
]
|
||||||
|
}
|
42
Date-Group/.vscode/tasks.json
vendored
Normal file
42
Date-Group/.vscode/tasks.json
vendored
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
63
Date-Group/Date-Group.csproj
Normal file
63
Date-Group/Date-Group.csproj
Normal 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
426
Date-Group/DateGroup.cs
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
Date-Group/Models/AppSettings.cs
Normal file
35
Date-Group/Models/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
Date-Group/Models/Binder/AppSettings.cs
Normal file
26
Date-Group/Models/Binder/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
Date-Group/Models/Binder/Configuration.cs
Normal file
30
Date-Group/Models/Binder/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
Date-Group/Models/Configuration.cs
Normal file
43
Date-Group/Models/Configuration.cs
Normal 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();
|
||||||
|
|
||||||
|
}
|
40
Date-Group/Models/Stateless/AppSettings.cs
Normal file
40
Date-Group/Models/Stateless/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
Date-Group/Models/Stateless/Configuration.cs
Normal file
44
Date-Group/Models/Stateless/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
Date-Group/Models/Stateless/SerilogExtensionMethods.cs
Normal file
10
Date-Group/Models/Stateless/SerilogExtensionMethods.cs
Normal 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
109
Date-Group/Program.cs
Normal 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>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
342
Date-Group/appsettings.Development.json
Normal file
342
Date-Group/appsettings.Development.json
Normal 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
1
Instance/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
32
Instance/.vscode/launch.json
vendored
Normal file
32
Instance/.vscode/launch.json
vendored
Normal 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
14
Instance/.vscode/settings.json
vendored
Normal 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
42
Instance/.vscode/tasks.json
vendored
Normal 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
796
Instance/DlibDotNet.cs
Normal 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
92
Instance/Instance.csproj
Normal 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>
|
35
Instance/Models/AppSettings.cs
Normal file
35
Instance/Models/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
Instance/Models/Binder/AppSettings.cs
Normal file
26
Instance/Models/Binder/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
99
Instance/Models/Binder/Configuration.cs
Normal file
99
Instance/Models/Binder/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
145
Instance/Models/Configuration.cs
Normal file
145
Instance/Models/Configuration.cs
Normal 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();
|
||||||
|
|
||||||
|
}
|
40
Instance/Models/Stateless/AppSettings.cs
Normal file
40
Instance/Models/Stateless/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
Instance/Models/Stateless/Configuration.cs
Normal file
44
Instance/Models/Stateless/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
Instance/Models/Stateless/SerilogExtensionMethods.cs
Normal file
10
Instance/Models/Stateless/SerilogExtensionMethods.cs
Normal 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);
|
||||||
|
|
||||||
|
}
|
79
Instance/Models/_A2_People.cs
Normal file
79
Instance/Models/_A2_People.cs
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
161
Instance/Models/_D2_FaceLandmark.cs
Normal file
161
Instance/Models/_D2_FaceLandmark.cs
Normal 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
498
Instance/Models/_D_Face.cs
Normal 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();
|
||||||
|
|
||||||
|
}
|
230
Instance/Models/_E2_Navigate.cs
Normal file
230
Instance/Models/_E2_Navigate.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
338
Instance/Models/_E3_Rename.cs
Normal file
338
Instance/Models/_E3_Rename.cs
Normal 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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
390
Instance/Models/_E_Distance.cs
Normal file
390
Instance/Models/_E_Distance.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
90
Instance/Models/_F_Random.cs
Normal file
90
Instance/Models/_F_Random.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
229
Instance/Models/_G2_Identify.cs
Normal file
229
Instance/Models/_G2_Identify.cs
Normal 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
213
Instance/Models/_G_Index.cs
Normal 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
71
Instance/Program.cs
Normal 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>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
457
Instance/appsettings.Development.json
Normal file
457
Instance/appsettings.Development.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
457
Instance/appsettings.Staging.json
Normal file
457
Instance/appsettings.Staging.json
Normal 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
458
Instance/appsettings.json
Normal 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
7
Metadata/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"dlib",
|
||||||
|
"Exif",
|
||||||
|
"Serilog"
|
||||||
|
]
|
||||||
|
}
|
47
Metadata/Metadata.csproj
Normal file
47
Metadata/Metadata.csproj
Normal 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>
|
181
Metadata/Models/B_Metadata.cs
Normal file
181
Metadata/Models/B_Metadata.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
Metadata/Models/Stateless/SerilogExtensionMethods.cs
Normal file
10
Metadata/Models/Stateless/SerilogExtensionMethods.cs
Normal 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);
|
||||||
|
|
||||||
|
}
|
1
Not-Copy-Copy/.vscode/format-report.json
vendored
Normal file
1
Not-Copy-Copy/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
30
Not-Copy-Copy/.vscode/launch.json
vendored
Normal file
30
Not-Copy-Copy/.vscode/launch.json
vendored
Normal 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
11
Not-Copy-Copy/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"Barrick",
|
||||||
|
"Beichler",
|
||||||
|
"Bohdi",
|
||||||
|
"Dlib",
|
||||||
|
"Phares",
|
||||||
|
"Serilog",
|
||||||
|
"Vericruz"
|
||||||
|
]
|
||||||
|
}
|
42
Not-Copy-Copy/.vscode/tasks.json
vendored
Normal file
42
Not-Copy-Copy/.vscode/tasks.json
vendored
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
35
Not-Copy-Copy/Models/AppSettings.cs
Normal file
35
Not-Copy-Copy/Models/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
Not-Copy-Copy/Models/Binder/AppSettings.cs
Normal file
26
Not-Copy-Copy/Models/Binder/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
Not-Copy-Copy/Models/Binder/Configuration.cs
Normal file
27
Not-Copy-Copy/Models/Binder/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
Not-Copy-Copy/Models/Configuration.cs
Normal file
43
Not-Copy-Copy/Models/Configuration.cs
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
Not-Copy-Copy/Models/Stateless/AppSettings.cs
Normal file
40
Not-Copy-Copy/Models/Stateless/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
Not-Copy-Copy/Models/Stateless/Configuration.cs
Normal file
44
Not-Copy-Copy/Models/Stateless/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
Not-Copy-Copy/Models/Stateless/SerilogExtensionMethods.cs
Normal file
10
Not-Copy-Copy/Models/Stateless/SerilogExtensionMethods.cs
Normal 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);
|
||||||
|
|
||||||
|
}
|
193
Not-Copy-Copy/Not-Copy-Copy.cs
Normal file
193
Not-Copy-Copy/Not-Copy-Copy.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
63
Not-Copy-Copy/Not-Copy-Copy.csproj
Normal file
63
Not-Copy-Copy/Not-Copy-Copy.csproj
Normal 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
127
Not-Copy-Copy/Program.cs
Normal 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>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
339
Not-Copy-Copy/appsettings.Development.json
Normal file
339
Not-Copy-Copy/appsettings.Development.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
PrepareForOld/.vscode/format-report.json
vendored
Normal file
1
PrepareForOld/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
30
PrepareForOld/.vscode/launch.json
vendored
Normal file
30
PrepareForOld/.vscode/launch.json
vendored
Normal 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
14
PrepareForOld/.vscode/settings.json
vendored
Normal 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
42
PrepareForOld/.vscode/tasks.json
vendored
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
35
PrepareForOld/Models/AppSettings.cs
Normal file
35
PrepareForOld/Models/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
PrepareForOld/Models/Binder/AppSettings.cs
Normal file
26
PrepareForOld/Models/Binder/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
PrepareForOld/Models/Binder/Configuration.cs
Normal file
20
PrepareForOld/Models/Binder/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
PrepareForOld/Models/Configuration.cs
Normal file
31
PrepareForOld/Models/Configuration.cs
Normal 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();
|
||||||
|
|
||||||
|
}
|
17
PrepareForOld/Models/SaveTabSeparatedValues/ImageExifInfo.cs
Normal file
17
PrepareForOld/Models/SaveTabSeparatedValues/ImageExifInfo.cs
Normal 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; }
|
||||||
|
}
|
8
PrepareForOld/Models/SaveTabSeparatedValues/IndexInfo.cs
Normal file
8
PrepareForOld/Models/SaveTabSeparatedValues/IndexInfo.cs
Normal 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; }
|
||||||
|
}
|
40
PrepareForOld/Models/Stateless/AppSettings.cs
Normal file
40
PrepareForOld/Models/Stateless/AppSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
PrepareForOld/Models/Stateless/Configuration.cs
Normal file
44
PrepareForOld/Models/Stateless/Configuration.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
PrepareForOld/Models/Stateless/SerilogExtensionMethods.cs
Normal file
10
PrepareForOld/Models/Stateless/SerilogExtensionMethods.cs
Normal 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);
|
||||||
|
|
||||||
|
}
|
666
PrepareForOld/PrepareForOld.cs
Normal file
666
PrepareForOld/PrepareForOld.cs
Normal 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)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
60
PrepareForOld/PrepareForOld.csproj
Normal file
60
PrepareForOld/PrepareForOld.csproj
Normal 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
71
PrepareForOld/Program.cs
Normal 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>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
364
PrepareForOld/appsettings.Development.json
Normal file
364
PrepareForOld/appsettings.Development.json
Normal 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
Loading…
x
Reference in New Issue
Block a user