mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
switched to xunit
This commit is contained in:
450
.editorconfig
450
.editorconfig
@@ -1,50 +1,127 @@
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# use unix newline characters
|
||||
end_of_line = lf
|
||||
|
||||
[*.cs]
|
||||
dotnet_naming_rule.methods_must_be_camel_case.severity = warning
|
||||
dotnet_naming_rule.methods_must_be_camel_case.symbols = private_methods
|
||||
dotnet_naming_rule.methods_must_be_camel_case.style = camel_case_style
|
||||
|
||||
dotnet_naming_symbols.private_methods.applicable_kinds = method
|
||||
dotnet_naming_symbols.private_methods.applicable_accessibilities = private
|
||||
|
||||
dotnet_naming_style.camel_case_style.capitalization = camel_case
|
||||
dotnet_diagnostic.CA2254.severity = none
|
||||
|
||||
[*.razor]
|
||||
indent_style = ignore
|
||||
indent_size = ignore
|
||||
|
||||
|
||||
# Default settings:
|
||||
# A newline ending every file
|
||||
# Use 4 spaces as indentation
|
||||
# All files
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[project.json]
|
||||
indent_size = 2
|
||||
|
||||
# Generated code
|
||||
[*{_AssemblyInfo.cs,.notsupported.cs}]
|
||||
generated_code = true
|
||||
end_of_line = lf
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
tab_width = 2
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{cs,vb}]
|
||||
|
||||
# Organize usings
|
||||
dotnet_separate_import_directive_groups = true
|
||||
dotnet_sort_system_directives_first = true
|
||||
file_header_template = unset
|
||||
|
||||
# this. and Me. preferences
|
||||
dotnet_style_qualification_for_event = false:silent
|
||||
dotnet_style_qualification_for_field = false:silent
|
||||
dotnet_style_qualification_for_method = false:silent
|
||||
dotnet_style_qualification_for_property = false:silent
|
||||
|
||||
# Language keywords vs BCL types preferences
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||
dotnet_style_predefined_type_for_member_access = true:silent
|
||||
|
||||
# Parentheses preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
|
||||
|
||||
# Modifier preferences
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
dotnet_style_prefer_auto_properties = true:suggestion
|
||||
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
|
||||
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||
|
||||
# Field preferences
|
||||
dotnet_style_readonly_field = true:warning
|
||||
|
||||
# Parameter preferences
|
||||
dotnet_code_quality_unused_parameters = all:suggestion
|
||||
|
||||
# Suppression preferences
|
||||
dotnet_remove_unnecessary_suppression_exclusions = none
|
||||
|
||||
#### C# Coding Conventions ####
|
||||
[*.cs]
|
||||
|
||||
# var preferences
|
||||
csharp_style_var_elsewhere = false:silent
|
||||
csharp_style_var_for_built_in_types = false:silent
|
||||
csharp_style_var_when_type_is_apparent = false:silent
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:suggestion
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_prefer_not_pattern = true:suggestion
|
||||
csharp_style_prefer_pattern_matching = true:silent
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Modifier preferences
|
||||
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:silent
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_prefer_simple_using_statement = true:suggestion
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
||||
csharp_style_prefer_index_operator = true:suggestion
|
||||
csharp_style_prefer_range_operator = true:suggestion
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
|
||||
# 'using' directive preferences
|
||||
csharp_using_directive_placement = outside_namespace:silent
|
||||
|
||||
#### C# Formatting Rules ####
|
||||
|
||||
# New line preferences
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = 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_object_initializers = 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
|
||||
|
||||
# Indentation preferences
|
||||
@@ -52,100 +129,8 @@ csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = one_less_than_current
|
||||
|
||||
# Modifier preferences
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
|
||||
|
||||
# avoid this. unless absolutely necessary
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
dotnet_style_qualification_for_method = false:suggestion
|
||||
dotnet_style_qualification_for_event = false:suggestion
|
||||
|
||||
# Types: use keywords instead of BCL types, and permit var only when the type is clear
|
||||
# csharp_style_var_for_built_in_types = false:suggestion
|
||||
csharp_style_var_when_type_is_apparent = false:none
|
||||
# csharp_style_var_elsewhere = false:suggestion
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
# name all constant fields using PascalCase
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
|
||||
# static fields should have s_ prefix
|
||||
# dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
|
||||
# dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
|
||||
# dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
|
||||
# dotnet_naming_symbols.static_fields.applicable_kinds = field
|
||||
# dotnet_naming_symbols.static_fields.required_modifiers = static
|
||||
# dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
|
||||
# dotnet_naming_style.static_prefix_style.required_prefix = s_
|
||||
# dotnet_naming_style.static_prefix_style.capitalization = camel_case
|
||||
|
||||
# internal and private fields should be _camelCase
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
|
||||
# Code style defaults
|
||||
csharp_using_directive_placement = outside_namespace:suggestion
|
||||
dotnet_sort_system_directives_first = true
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_preserve_single_line_blocks = true:none
|
||||
csharp_preserve_single_line_statements = false:none
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_prefer_simple_using_statement = false:none
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_auto_properties = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_methods = true:silent
|
||||
csharp_style_expression_bodied_constructors = true:silent
|
||||
csharp_style_expression_bodied_operators = true:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:silent
|
||||
csharp_style_expression_bodied_local_functions = true:silent
|
||||
|
||||
# Pattern matching
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
|
||||
# Null checking preferences
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Other features
|
||||
csharp_style_prefer_index_operator = false:none
|
||||
csharp_style_prefer_range_operator = false:none
|
||||
csharp_style_pattern_local_over_anonymous_function = false:none
|
||||
csharp_indent_switch_labels = true
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
@@ -155,7 +140,7 @@ 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 = do_not_ignore
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
@@ -171,34 +156,193 @@ csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
# C++ Files
|
||||
[*.{cpp,h,in}]
|
||||
curly_bracket_next_line = true
|
||||
indent_brace_style = Allman
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
||||
|
||||
# Xml project files
|
||||
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
|
||||
indent_size = 2
|
||||
#### Naming styles ####
|
||||
[*.{cs,vb}]
|
||||
|
||||
[*.{csproj,vbproj,proj,nativeproj,locproj}]
|
||||
charset = utf-8
|
||||
# Naming rules
|
||||
|
||||
# Xml build files
|
||||
[*.builds]
|
||||
indent_size = 2
|
||||
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces
|
||||
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase
|
||||
|
||||
# Xml files
|
||||
[*.{xml,stylecop,resx,ruleset}]
|
||||
indent_size = 2
|
||||
dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion
|
||||
dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces
|
||||
dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase
|
||||
|
||||
# Xml config files
|
||||
[*.{props,targets,config,nuspec}]
|
||||
indent_size = 2
|
||||
dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion
|
||||
dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters
|
||||
dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase
|
||||
|
||||
# YAML config files
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods
|
||||
dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties
|
||||
dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.events_should_be_pascalcase.symbols = events
|
||||
dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables
|
||||
dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants
|
||||
dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters
|
||||
dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields
|
||||
dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.private_fields_should_be_s_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.private_fields_should_be_s_camelcase.symbols = private_fields
|
||||
dotnet_naming_rule.private_fields_should_be_s_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields
|
||||
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase
|
||||
|
||||
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields
|
||||
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields
|
||||
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields
|
||||
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums
|
||||
dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions
|
||||
dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
dotnet_naming_symbols.interfaces.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interfaces.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.enums.applicable_kinds = enum
|
||||
dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.enums.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.events.applicable_kinds = event
|
||||
dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.events.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.methods.applicable_kinds = method
|
||||
dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.methods.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.properties.applicable_kinds = property
|
||||
dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.properties.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.public_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal
|
||||
dotnet_naming_symbols.public_fields.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.private_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_fields.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_static_fields.required_modifiers = static
|
||||
|
||||
dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum
|
||||
dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types_and_namespaces.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.type_parameters.applicable_kinds = namespace
|
||||
dotnet_naming_symbols.type_parameters.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.type_parameters.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.private_constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_constant_fields.required_modifiers = const
|
||||
|
||||
dotnet_naming_symbols.local_variables.applicable_kinds = local
|
||||
dotnet_naming_symbols.local_variables.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.local_variables.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.local_constants.applicable_kinds = local
|
||||
dotnet_naming_symbols.local_constants.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.local_constants.required_modifiers = const
|
||||
|
||||
dotnet_naming_symbols.parameters.applicable_kinds = parameter
|
||||
dotnet_naming_symbols.parameters.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.parameters.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.public_constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal
|
||||
dotnet_naming_symbols.public_constant_fields.required_modifiers = const
|
||||
|
||||
dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal
|
||||
dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static
|
||||
|
||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static
|
||||
|
||||
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
|
||||
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.local_functions.required_modifiers =
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.pascalcase.required_prefix =
|
||||
dotnet_naming_style.pascalcase.required_suffix =
|
||||
dotnet_naming_style.pascalcase.word_separator =
|
||||
dotnet_naming_style.pascalcase.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.ipascalcase.required_prefix = I
|
||||
dotnet_naming_style.ipascalcase.required_suffix =
|
||||
dotnet_naming_style.ipascalcase.word_separator =
|
||||
dotnet_naming_style.ipascalcase.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.tpascalcase.required_prefix = T
|
||||
dotnet_naming_style.tpascalcase.required_suffix =
|
||||
dotnet_naming_style.tpascalcase.word_separator =
|
||||
dotnet_naming_style.tpascalcase.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.camelcase.required_prefix =
|
||||
dotnet_naming_style.camelcase.required_suffix =
|
||||
dotnet_naming_style.camelcase.word_separator =
|
||||
dotnet_naming_style.camelcase.capitalization = camel_case
|
||||
|
||||
dotnet_naming_style.s_camelcase.required_prefix = s_
|
||||
dotnet_naming_style.s_camelcase.required_suffix =
|
||||
dotnet_naming_style.s_camelcase.word_separator =
|
||||
dotnet_naming_style.s_camelcase.capitalization = camel_case
|
||||
|
||||
# Shell scripts
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
|
||||
@@ -3,7 +3,7 @@ using CanvasModel.EnrollmentTerms;
|
||||
|
||||
public class DeserializationTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestTerm()
|
||||
{
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
public class CalendarMonthTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCalendarMonthCanGetFirstWeek()
|
||||
{
|
||||
var month = new CalendarMonth(2023, 2);
|
||||
@@ -12,7 +12,7 @@ public class CalendarMonthTests
|
||||
month.Weeks.First().Should().BeEquivalentTo(expectedFirstWeek);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanGetAnotherMonthsFirstWeek()
|
||||
{
|
||||
var month = new CalendarMonth(2023, 4);
|
||||
@@ -24,7 +24,7 @@ public class CalendarMonthTests
|
||||
month.Weeks.First().Should().BeEquivalentTo(expectedFirstWeek);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCorrectNumberOfWeeks()
|
||||
{
|
||||
var month = new CalendarMonth(2023, 4);
|
||||
@@ -32,7 +32,7 @@ public class CalendarMonthTests
|
||||
month.Weeks.Count().Should().Be(6);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestLastWeekIsCorrect()
|
||||
{
|
||||
var month = new CalendarMonth(2023, 4);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// public class ConfigurationTests
|
||||
// {
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void TestCanCreateConfigFromTermAndDays()
|
||||
// {
|
||||
// DateTime startAt = new DateTime(2022, 1, 1);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// public class ModuleTests
|
||||
// {
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void CanAddModule()
|
||||
// {
|
||||
// var manager = new ModuleManager();
|
||||
@@ -11,7 +11,7 @@
|
||||
// manager.Modules.First().Should().Be(module);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void CanAddAssignmentToCorrectModule()
|
||||
// {
|
||||
// var manager = new ModuleManager();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
// public class SemesterPlannerTests
|
||||
// {
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void TestCanCreatePlanner()
|
||||
// {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// semester.Months.Count().Should().Be(1);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void TestNewPlannerHasCorrectNumberOfMonths()
|
||||
// {
|
||||
// var config = new SemesterCalendarConfig(
|
||||
@@ -33,7 +33,7 @@
|
||||
// semester.Months.Count().Should().Be(2);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void TestNewPlannerHandlesTermsThatWrapYears()
|
||||
// {
|
||||
// var config = new SemesterCalendarConfig(
|
||||
@@ -47,7 +47,7 @@
|
||||
// semester.Months.Count().Should().Be(2);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void TestSemesterGetsCorrectMonths()
|
||||
// {
|
||||
// var config = new SemesterCalendarConfig(
|
||||
@@ -63,7 +63,7 @@
|
||||
// }
|
||||
|
||||
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void TestMonthsCanWrapYears()
|
||||
// {
|
||||
// var config = new SemesterCalendarConfig(
|
||||
@@ -81,7 +81,7 @@
|
||||
// semester.Months.Last().Year.Should().Be(2023);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public void TestSemesterTracksDaysOfWeek()
|
||||
// {
|
||||
// DayOfWeek[] days = new DayOfWeek[] { DayOfWeek.Monday };
|
||||
|
||||
@@ -9,15 +9,25 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="akka.testkit" Version="1.5.18" />
|
||||
<PackageReference Include="Akka.TestKit.Xunit2" Version="1.5.18" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.8.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="nsubstitute" Version="5.1.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="RestSharp" Version="108.0.3" />
|
||||
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit" Version="2.7.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -2,7 +2,7 @@ using LocalModels;
|
||||
|
||||
public class AssignmentMarkdownTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseAssignmentSettings()
|
||||
{
|
||||
var assignment = new LocalAssignment()
|
||||
@@ -24,7 +24,7 @@ public class AssignmentMarkdownTests
|
||||
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void AssignmentWithEmptyRubric_CanBeParsed()
|
||||
{
|
||||
var assignment = new LocalAssignment()
|
||||
@@ -43,7 +43,7 @@ public class AssignmentMarkdownTests
|
||||
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void AssignmentWithEmptySubmissionTypes_CanBeParsed()
|
||||
{
|
||||
var assignment = new LocalAssignment()
|
||||
@@ -66,7 +66,7 @@ public class AssignmentMarkdownTests
|
||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void AssignmentWithoutLockAtDate_CanBeParsed()
|
||||
{
|
||||
var assignment = new LocalAssignment()
|
||||
@@ -89,7 +89,7 @@ public class AssignmentMarkdownTests
|
||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void AssignmentWithoutDescription_CanBeParsed()
|
||||
{
|
||||
var assignment = new LocalAssignment()
|
||||
@@ -111,7 +111,7 @@ public class AssignmentMarkdownTests
|
||||
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void Assignments_CanHaveThreeDashes()
|
||||
{
|
||||
var assignment = new LocalAssignment()
|
||||
|
||||
@@ -5,14 +5,13 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
public class FileStorageTests
|
||||
{
|
||||
private IFileStorageManager fileManager { get; set; }
|
||||
private FileStorageManager fileManager { get; set; }
|
||||
|
||||
|
||||
private static string setupTempDirectory()
|
||||
public FileStorageTests()
|
||||
{
|
||||
var tempDirectory = Path.GetTempPath();
|
||||
var storageDirectory = tempDirectory + "fileStorageTests";
|
||||
@@ -29,14 +28,6 @@ public class FileStorageTests
|
||||
dir.Delete(true);
|
||||
}
|
||||
|
||||
return storageDirectory;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
var storageDirectory = setupTempDirectory();
|
||||
|
||||
var fileManagerLogger = new MyLogger<FileStorageManager>(NullLogger<FileStorageManager>.Instance);
|
||||
var markdownLoaderLogger = new MyLogger<CourseMarkdownLoader>(NullLogger<CourseMarkdownLoader>.Instance);
|
||||
var markdownSaverLogger = new MyLogger<MarkdownCourseSaver>(NullLogger<MarkdownCourseSaver>.Instance);
|
||||
@@ -52,7 +43,7 @@ public class FileStorageTests
|
||||
fileManager = new FileStorageManager(fileManagerLogger, markdownLoader, markdownSaver, otherLogger, fileConfiguration);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public async Task EmptyCourse_CanBeSavedAndLoaded()
|
||||
{
|
||||
LocalCourse testCourse = new LocalCourse
|
||||
@@ -69,7 +60,7 @@ public class FileStorageTests
|
||||
loadedCourse.Should().BeEquivalentTo(testCourse);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public async Task CourseSettings_CanBeSavedAndLoaded()
|
||||
{
|
||||
LocalCourse testCourse = new()
|
||||
@@ -95,7 +86,7 @@ public class FileStorageTests
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public async Task EmptyCourseModules_CanBeSavedAndLoaded()
|
||||
{
|
||||
LocalCourse testCourse = new()
|
||||
@@ -119,7 +110,7 @@ public class FileStorageTests
|
||||
loadedCourse.Modules.Should().BeEquivalentTo(testCourse.Modules);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public async Task CourseModules_WithAssignments_CanBeSavedAndLoaded()
|
||||
{
|
||||
LocalCourse testCourse = new()
|
||||
@@ -160,7 +151,7 @@ public class FileStorageTests
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public async Task CourseModules_WithQuizzes_CanBeSavedAndLoaded()
|
||||
{
|
||||
LocalCourse testCourse = new()
|
||||
@@ -204,7 +195,7 @@ public class FileStorageTests
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public async Task MarkdownStorage_FullyPopulated_DoesNotLoseData()
|
||||
{
|
||||
LocalCourse testCourse = new()
|
||||
@@ -271,7 +262,7 @@ public class FileStorageTests
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public async Task MarkdownStorage_CanPersistPages()
|
||||
{
|
||||
LocalCourse testCourse = new()
|
||||
|
||||
@@ -2,7 +2,7 @@ using LocalModels;
|
||||
|
||||
public class PageMarkdownTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParsePage()
|
||||
{
|
||||
var page = new LocalCoursePage
|
||||
|
||||
@@ -2,7 +2,7 @@ using LocalModels;
|
||||
|
||||
public class MatchingTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanParseMatchingQuestion()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -29,7 +29,7 @@ Match the following terms & definitions
|
||||
firstQuestion.Answers.First().MatchedText.Should().Be("a single command to be executed");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanCreateMarkdownForMatchingQuesiton()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -59,7 +59,7 @@ Match the following terms & definitions
|
||||
^ keyword - reserved word that has special meaning in a program (e.g. class, void, static, etc.)";
|
||||
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void WhitespaceIsOptional()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
|
||||
@@ -3,7 +3,7 @@ using LocalModels;
|
||||
public class MultipleAnswersTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void QuzMarkdownIncludesMultipleAnswerQuestion()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -43,7 +43,7 @@ oneline question
|
||||
markdown.Should().Contain(expectedQuestionString);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanParseQuestionWithMultipleAnswers()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -81,7 +81,7 @@ Which events are triggered when the user clicks on an input field?
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanUseBracesInAnswerFormultipleAnswer()
|
||||
{
|
||||
var rawMarkdownQuestion = @"
|
||||
@@ -95,7 +95,7 @@ Which events are triggered when the user clicks on an input field?
|
||||
question.Answers.Count().Should().Be(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanUseBracesInAnswerFormultipleAnswer_MultiLine()
|
||||
{
|
||||
var rawMarkdownQuestion = @"
|
||||
|
||||
@@ -2,7 +2,7 @@ using LocalModels;
|
||||
|
||||
public class MultipleChoiceTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void QuzMarkdownIncludesMultipleChoiceQuestion()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -58,7 +58,7 @@ endline
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void LetterOptionalForMultipleChoice()
|
||||
{
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ using LocalModels;
|
||||
public class QuizDeterministicChecks
|
||||
{
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void SerializationIsDeterministic_EmptyQuiz()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -23,7 +23,7 @@ public class QuizDeterministicChecks
|
||||
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void SerializationIsDeterministic_ShowCorrectAnswers()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -43,7 +43,7 @@ public class QuizDeterministicChecks
|
||||
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void SerializationIsDeterministic_ShortAnswer()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -71,7 +71,7 @@ public class QuizDeterministicChecks
|
||||
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void SerializationIsDeterministic_Essay()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -99,7 +99,7 @@ public class QuizDeterministicChecks
|
||||
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void SerializationIsDeterministic_MultipleAnswer()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -138,7 +138,7 @@ public class QuizDeterministicChecks
|
||||
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void SerializationIsDeterministic_MultipleChoice()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -176,7 +176,7 @@ public class QuizDeterministicChecks
|
||||
var parsedQuiz = LocalQuiz.ParseMarkdown(quizMarkdown);
|
||||
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void SerializationIsDeterministic_Matching()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
|
||||
@@ -4,7 +4,7 @@ using LocalModels;
|
||||
// try to follow syntax from https://github.com/gpoore/text2qti
|
||||
public class QuizMarkdownTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanSerializeQuizToMarkdown()
|
||||
{
|
||||
var quiz = new LocalQuiz()
|
||||
@@ -37,7 +37,7 @@ this is my description in markdown
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseMarkdownQuizWithNoQuestions()
|
||||
{
|
||||
var rawMarkdownQuiz = new StringBuilder();
|
||||
@@ -68,7 +68,7 @@ this is my description in markdown
|
||||
quiz.AllowedAttempts.Should().Be(-1);
|
||||
quiz.Description.Should().Be(expectedDescription.ToString());
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseMarkdownQuizPassword()
|
||||
{
|
||||
|
||||
@@ -94,7 +94,7 @@ this is my description in markdown
|
||||
quiz.Password.Should().Be(password);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseMarkdownQuiz_CanConfigureToShowCorrectAnswers()
|
||||
{
|
||||
var rawMarkdownQuiz = new StringBuilder();
|
||||
@@ -118,7 +118,7 @@ this is my description in markdown
|
||||
quiz.showCorrectAnswers.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseQuizWithQuestions()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -159,7 +159,7 @@ b) false
|
||||
firstQuestion.Answers.ElementAt(1).Text.Should().Contain("endline");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanParseMultipleQuestions()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -192,7 +192,7 @@ b) false
|
||||
secondQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_CHOICE);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void ShortAnswerToMarkdown_IsCorrect()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -220,7 +220,7 @@ Which events are triggered when the user clicks on an input field?
|
||||
short_answer";
|
||||
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void NegativePoints_IsAllowed()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -244,7 +244,7 @@ short answer
|
||||
var firstQuestion = quiz.Questions.First();
|
||||
firstQuestion.Points.Should().Be(-4);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void FloatingPointPoints_IsAllowed()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
|
||||
@@ -2,7 +2,7 @@ using LocalModels;
|
||||
|
||||
public class TextAnswerTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanParseEssay()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -28,7 +28,7 @@ essay
|
||||
firstQuestion.Text.Should().NotContain("essay");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void CanParseShortAnswer()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -54,7 +54,7 @@ short answer
|
||||
firstQuestion.Text.Should().NotContain("short answer");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void ShortAnswerToMarkdown_IsCorrect()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
@@ -83,7 +83,7 @@ short_answer";
|
||||
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void EssayQuestionToMarkdown_IsCorrect()
|
||||
{
|
||||
var rawMarkdownQuiz = @"
|
||||
|
||||
@@ -3,7 +3,7 @@ using LocalModels;
|
||||
public class RubricMarkdownTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseOneItem()
|
||||
{
|
||||
var rawRubric = @"
|
||||
@@ -17,7 +17,7 @@ public class RubricMarkdownTests
|
||||
rubric.First().Points.Should().Be(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseMultipleItems()
|
||||
{
|
||||
var rawRubric = @"
|
||||
@@ -32,7 +32,7 @@ public class RubricMarkdownTests
|
||||
rubric.ElementAt(1).Points.Should().Be(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseSinglePoint()
|
||||
{
|
||||
var rawRubric = @"
|
||||
@@ -45,7 +45,7 @@ public class RubricMarkdownTests
|
||||
rubric.First().Points.Should().Be(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseSingleExtraCredit_LowerCase()
|
||||
{
|
||||
var rawRubric = @"
|
||||
@@ -57,7 +57,7 @@ public class RubricMarkdownTests
|
||||
rubric.First().Label.Should().Be("(extra credit) this is the task");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseSingleExtraCredit_UpperCase()
|
||||
{
|
||||
var rawRubric = @"
|
||||
@@ -69,7 +69,7 @@ public class RubricMarkdownTests
|
||||
rubric.First().Label.Should().Be("(Extra Credit) this is the task");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseFloatingPointNubmers()
|
||||
{
|
||||
var rawRubric = @"
|
||||
@@ -79,7 +79,7 @@ public class RubricMarkdownTests
|
||||
var rubric = LocalAssignment.ParseRubricMarkdown(rawRubric);
|
||||
rubric.First().Points.Should().Be(1.5);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseNegativeNubmers()
|
||||
{
|
||||
var rawRubric = @"
|
||||
@@ -89,7 +89,7 @@ public class RubricMarkdownTests
|
||||
var rubric = LocalAssignment.ParseRubricMarkdown(rawRubric);
|
||||
rubric.First().Points.Should().Be(-2.0);
|
||||
}
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanParseNegativeFloatingPointNubmers()
|
||||
{
|
||||
var rawRubric = @"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
// public class ICanvasServiceTests
|
||||
// {
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public async Task CanReadCanvasSemesters()
|
||||
// {
|
||||
// var expectedTerms = new EnrollmentTermModel[] {
|
||||
@@ -28,7 +28,7 @@
|
||||
// canvasTerms.Should().BeEquivalentTo(expectedTerms);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// [Fact]
|
||||
// public async Task CanGetActiveTerms()
|
||||
// {
|
||||
// var expectedTerms = new EnrollmentTermModel[] {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
global using System.Text.Json;
|
||||
global using FluentAssertions;
|
||||
global using NUnit.Framework;
|
||||
global using Xunit;
|
||||
|
||||
@@ -2,7 +2,7 @@ using Management.Web.Pages.Course.CourseCalendar;
|
||||
|
||||
public class MonthDetailTests
|
||||
{
|
||||
[Test]
|
||||
[Fact]
|
||||
public void TestCanGetMonthName()
|
||||
{
|
||||
var calendarMonth = new CalendarMonth(2022, 2);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Akka" Version="1.5.20" />
|
||||
<PackageReference Include="Akka.DependencyInjection" Version="1.5.20" />
|
||||
<PackageReference Include="BlazorMonaco" Version="3.0.0" />
|
||||
<PackageReference Include="dotenv.net" Version="3.1.2" />
|
||||
<PackageReference Include="Markdig" Version="0.31.0" />
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
global using System.ComponentModel.DataAnnotations;
|
||||
global using System.Text.Json;
|
||||
global using System.Text.Json.Serialization;
|
||||
|
||||
global using CanvasModel;
|
||||
global using CanvasModel.Courses;
|
||||
global using CanvasModel.EnrollmentTerms;
|
||||
|
||||
global using LocalModels;
|
||||
|
||||
global using Management.Planner;
|
||||
global using Management.Services;
|
||||
global using Management.Services.Canvas;
|
||||
global using Management.Web.Shared;
|
||||
global using Management.Web.Shared.Components;
|
||||
|
||||
using dotenv.net;
|
||||
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using Microsoft.AspNetCore.ResponseCompression;
|
||||
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.Metrics;
|
||||
@@ -69,25 +75,40 @@ builder.Services.AddServerSideBlazor();
|
||||
|
||||
builder.Services.AddLogging();
|
||||
|
||||
builder.Services.AddScoped(typeof(MyLogger<>));
|
||||
builder.Services.AddSingleton(typeof(MyLogger<>));
|
||||
|
||||
builder.Services.AddScoped<IWebRequestor, WebRequestor>();
|
||||
builder.Services.AddScoped<CanvasServiceUtils>();
|
||||
builder.Services.AddScoped<ICanvasAssignmentService, CanvasAssignmentService>();
|
||||
builder.Services.AddScoped<ICanvasCoursePageService, CanvasCoursePageService>();
|
||||
builder.Services.AddScoped<ICanvasAssignmentGroupService, CanvasAssignmentGroupService>();
|
||||
builder.Services.AddScoped<ICanvasQuizService, CanvasQuizService>();
|
||||
builder.Services.AddScoped<ICanvasModuleService, CanvasModuleService>();
|
||||
builder.Services.AddScoped<ICanvasService, CanvasService>();
|
||||
// stateless services
|
||||
builder.Services.AddSingleton<IWebRequestor, WebRequestor>();
|
||||
builder.Services.AddSingleton<CanvasServiceUtils>();
|
||||
builder.Services.AddSingleton<ICanvasAssignmentService, CanvasAssignmentService>();
|
||||
builder.Services.AddSingleton<ICanvasCoursePageService, CanvasCoursePageService>();
|
||||
builder.Services.AddSingleton<ICanvasAssignmentGroupService, CanvasAssignmentGroupService>();
|
||||
builder.Services.AddSingleton<ICanvasQuizService, CanvasQuizService>();
|
||||
builder.Services.AddSingleton<ICanvasModuleService, CanvasModuleService>();
|
||||
builder.Services.AddSingleton<ICanvasService, CanvasService>();
|
||||
|
||||
builder.Services.AddScoped<MarkdownCourseSaver>();
|
||||
builder.Services.AddScoped<CourseMarkdownLoader>();
|
||||
builder.Services.AddScoped<IFileStorageManager>(sp =>
|
||||
builder.Services.AddSingleton<MarkdownCourseSaver>();
|
||||
builder.Services.AddSingleton<CourseMarkdownLoader>();
|
||||
|
||||
builder.Services.AddSingleton<FileStorageManager>();
|
||||
|
||||
// one actor system, maybe different actor for different pages?
|
||||
builder.Services.AddSingleton<AkkaService>();
|
||||
builder.Services.AddHostedService(sp => sp.GetRequiredService<AkkaService>());
|
||||
|
||||
|
||||
// TODO: need to handle scoped requirements
|
||||
builder.Services.AddSingleton(sp =>
|
||||
{
|
||||
var manager = ActivatorUtilities.CreateInstance<FileStorageManager>(sp);
|
||||
var logger = sp.GetRequiredService<ILogger<FileStorageManagerCached>>();
|
||||
return new FileStorageManagerCached(manager, logger);
|
||||
var akka = sp.GetRequiredService<AkkaService>();
|
||||
return new CanvasQueue(akka.CanvasQueueActor ?? throw new Exception("Canvas queue actor not properly created"));
|
||||
});
|
||||
builder.Services.AddSingleton<IFileStorageManager>(sp =>
|
||||
{
|
||||
var akka = sp.GetRequiredService<AkkaService>();
|
||||
return new LocalStorageCache(akka.StorageActor ?? throw new Exception("Canvas queue actor not properly created"));
|
||||
});
|
||||
|
||||
|
||||
builder.Services.AddScoped<CoursePlanner>();
|
||||
builder.Services.AddScoped<AssignmentEditorContext>();
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
loadingTerms = true;
|
||||
terms = await canvas.GetCurrentTermsFor();
|
||||
loadingTerms = false;
|
||||
directoriesNotUsed = fileStorageManager.GetEmptyDirectories();
|
||||
directoriesNotUsed = await fileStorageManager.GetEmptyDirectories();
|
||||
}
|
||||
|
||||
private async Task SaveNewCourse()
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Akka" Version="1.5.20" />
|
||||
<PackageReference Include="Akka.DependencyInjection" Version="1.5.20" />
|
||||
<PackageReference Include="Markdig" Version="0.31.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="8.0.3" />
|
||||
@@ -16,4 +18,7 @@
|
||||
<PackageReference Include="YamlDotNet" Version="13.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
9
Management/Services/Actors/CanvasQueue.cs
Normal file
9
Management/Services/Actors/CanvasQueue.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Akka.Actor;
|
||||
|
||||
using Management.Services.Canvas;
|
||||
|
||||
public class CanvasQueue(IActorRef canvasQueueActor)
|
||||
{
|
||||
private readonly IActorRef canvasQueueActor = canvasQueueActor;
|
||||
|
||||
}
|
||||
18
Management/Services/Actors/CanvasQueueActor.cs
Normal file
18
Management/Services/Actors/CanvasQueueActor.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Akka.Actor;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
public class CanvasQueueActor : ReceiveActor
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IServiceScope scope;
|
||||
private readonly ILogger<CanvasQueueActor> logger;
|
||||
|
||||
public CanvasQueueActor(IServiceProvider serviceProviderArg)
|
||||
{
|
||||
serviceProvider = serviceProviderArg;
|
||||
scope = serviceProvider.CreateScope();
|
||||
logger = scope.ServiceProvider.GetRequiredService<ILogger<CanvasQueueActor>>();
|
||||
|
||||
}
|
||||
}
|
||||
61
Management/Services/Actors/LocalStorageActor.cs
Normal file
61
Management/Services/Actors/LocalStorageActor.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Akka.Actor;
|
||||
|
||||
using LocalModels;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
public class LocalStorageActor : ReceiveActor
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IServiceScope scope;
|
||||
private readonly ILogger<CanvasQueueActor> logger;
|
||||
private readonly FileStorageManager storage;
|
||||
|
||||
private DateTime? cacheTime { get; set; } = null;
|
||||
private IEnumerable<LocalCourse>? cachedCourses { get; set; } = null;
|
||||
private readonly int cacheSeconds = 2;
|
||||
|
||||
public LocalStorageActor(IServiceProvider serviceProviderArg)
|
||||
{
|
||||
serviceProvider = serviceProviderArg;
|
||||
scope = serviceProvider.CreateScope();
|
||||
logger = scope.ServiceProvider.GetRequiredService<ILogger<CanvasQueueActor>>();
|
||||
storage = scope.ServiceProvider.GetRequiredService<FileStorageManager>();
|
||||
|
||||
Receive<EmptyDirectoryAsk>(m =>
|
||||
{
|
||||
storage
|
||||
.GetEmptyDirectories()
|
||||
.PipeTo(Sender);
|
||||
});
|
||||
|
||||
ReceiveAsync<SavedCoursesAsk>(async m =>
|
||||
{
|
||||
var secondsFromLastLoad = (DateTime.Now - cacheTime)?.Seconds;
|
||||
|
||||
if (cachedCourses != null && secondsFromLastLoad < cacheSeconds)
|
||||
{
|
||||
logger.LogInformation("returning cached courses from file");
|
||||
Sender.Tell(cachedCourses);
|
||||
return;
|
||||
}
|
||||
|
||||
cachedCourses = await storage.LoadSavedCourses();
|
||||
cacheTime = DateTime.Now;
|
||||
Sender.Tell(cachedCourses);
|
||||
});
|
||||
|
||||
ReceiveAsync<SaveCoursesRequest>(async m =>
|
||||
{
|
||||
cacheTime = null;
|
||||
cachedCourses = null;
|
||||
await storage.SaveCourseAsync(m.Course, m.PreviouslyStoredCourse);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record EmptyDirectoryAsk();
|
||||
public record SavedCoursesAsk();
|
||||
|
||||
public record SaveCoursesRequest(LocalCourse Course, LocalCourse? PreviouslyStoredCourse);
|
||||
public record SaveCoursesResponseSuccess();
|
||||
23
Management/Services/Actors/LocalStorageCache.cs
Normal file
23
Management/Services/Actors/LocalStorageCache.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Akka.Actor;
|
||||
|
||||
using LocalModels;
|
||||
|
||||
public class LocalStorageCache(IActorRef storageActor) : IFileStorageManager
|
||||
{
|
||||
private readonly IActorRef storageActor = storageActor;
|
||||
|
||||
public async Task<IEnumerable<string>> GetEmptyDirectories()
|
||||
{
|
||||
return await storageActor.Ask<IEnumerable<string>>(new EmptyDirectoryAsk());
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<LocalCourse>> LoadSavedCourses()
|
||||
{
|
||||
return await storageActor.Ask<IEnumerable<LocalCourse>>(new SavedCoursesAsk());
|
||||
}
|
||||
|
||||
public async Task SaveCourseAsync(LocalCourse course, LocalCourse? previouslyStoredCourse)
|
||||
{
|
||||
await storageActor.Ask<SaveCoursesResponseSuccess>(new SaveCoursesRequest(course, previouslyStoredCourse));
|
||||
}
|
||||
}
|
||||
60
Management/Services/AkkaService.cs
Normal file
60
Management/Services/AkkaService.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
using Akka.Actor;
|
||||
using Akka.DependencyInjection;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Management.Services;
|
||||
|
||||
|
||||
public class AkkaService(
|
||||
IServiceProvider serviceProvider,
|
||||
IHostApplicationLifetime appLifetime,
|
||||
IConfiguration configuration
|
||||
) : IHostedService
|
||||
{
|
||||
private ActorSystem? actorSystem;
|
||||
private readonly IConfiguration configuration = configuration;
|
||||
private readonly IServiceProvider serviceProvider = serviceProvider;
|
||||
private readonly IHostApplicationLifetime applicationLifetime = appLifetime;
|
||||
public IActorRef? CanvasQueueActor { get; private set; }
|
||||
public IActorRef? StorageActor { get; private set; }
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var bootstrap = BootstrapSetup.Create();
|
||||
var dependencyInjectionSetup = DependencyResolverSetup.Create(serviceProvider);
|
||||
|
||||
var mergedSystemSetup = bootstrap.And(dependencyInjectionSetup);
|
||||
|
||||
actorSystem = ActorSystem.Create("canavas-management-actor-system", mergedSystemSetup);
|
||||
|
||||
var canvasQueueProps = DependencyResolver.For(actorSystem).Props<CanvasQueueActor>();
|
||||
CanvasQueueActor = actorSystem.ActorOf(canvasQueueProps, "canvasQueue");
|
||||
var localStorageProps = DependencyResolver.For(actorSystem).Props<LocalStorageActor>();
|
||||
StorageActor = actorSystem.ActorOf(localStorageProps, "localStorage");
|
||||
|
||||
// crash if the actor system crashes, awaiting never returns...
|
||||
actorSystem.WhenTerminated.ContinueWith(tr =>
|
||||
{
|
||||
applicationLifetime.StopApplication();
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
|
||||
// public void Tell(object message)
|
||||
// {
|
||||
// userSessionSupervisor?.Tell(message);
|
||||
// }
|
||||
|
||||
// public Task<T> Ask<T>(object message)
|
||||
// {
|
||||
// return userSessionSupervisor.Ask<T>(message);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using CanvasModel.Courses;
|
||||
using CanvasModel.EnrollmentTerms;
|
||||
using CanvasModel.Modules;
|
||||
using CanvasModel.Pages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using RestSharp;
|
||||
|
||||
namespace Management.Services.Canvas;
|
||||
@@ -35,7 +34,7 @@ public class CanvasService(
|
||||
ICanvasQuizService Quizzes,
|
||||
ICanvasCoursePageService Pages,
|
||||
MyLogger<ICanvasService> logger
|
||||
):ICanvasService
|
||||
) : ICanvasService
|
||||
{
|
||||
private readonly IWebRequestor webRequestor = webRequestor;
|
||||
private readonly CanvasServiceUtils utils = utils;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using LocalModels;
|
||||
using Management.Services;
|
||||
|
||||
public class FileStorageManager : IFileStorageManager
|
||||
public class FileStorageManager
|
||||
{
|
||||
private readonly MyLogger<FileStorageManager> logger;
|
||||
private readonly CourseMarkdownLoader _courseMarkdownLoader;
|
||||
@@ -39,7 +39,7 @@ public class FileStorageManager : IFileStorageManager
|
||||
return await _courseMarkdownLoader.LoadSavedCourses();
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetEmptyDirectories()
|
||||
public async Task<IEnumerable<string>> GetEmptyDirectories()
|
||||
{
|
||||
if (!Directory.Exists(_basePath))
|
||||
throw new DirectoryNotFoundException($"Cannot get empty directories, {_basePath} does not exist");
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using LocalModels;
|
||||
// using System.Diagnostics.CodeAnalysis;
|
||||
// using LocalModels;
|
||||
|
||||
public class FileStorageManagerCached : IFileStorageManager
|
||||
{
|
||||
private readonly FileStorageManager manager;
|
||||
// public class FileStorageManagerCached : IFileStorageManager
|
||||
// {
|
||||
// private readonly FileStorageManager manager;
|
||||
|
||||
private readonly object cacheLock = new object(); // Lock object for synchronization
|
||||
// private readonly object cacheLock = new object(); // Lock object for synchronization
|
||||
|
||||
|
||||
private DateTime? cacheTime { get; set; } = null;
|
||||
private IEnumerable<LocalCourse>? cachedCourses { get; set; } = null;
|
||||
private ILogger<FileStorageManagerCached> logger { get; }
|
||||
// private DateTime? cacheTime { get; set; } = null;
|
||||
// private IEnumerable<LocalCourse>? cachedCourses { get; set; } = null;
|
||||
// private ILogger<FileStorageManagerCached> logger { get; }
|
||||
|
||||
private readonly int cacheSeconds = 2;
|
||||
public FileStorageManagerCached(FileStorageManager manager, ILogger<FileStorageManagerCached> logger)
|
||||
{
|
||||
this.manager = manager;
|
||||
this.logger = logger;
|
||||
}
|
||||
public IEnumerable<string> GetEmptyDirectories()
|
||||
{
|
||||
return manager.GetEmptyDirectories();
|
||||
}
|
||||
// private readonly int cacheSeconds = 2;
|
||||
// public FileStorageManagerCached(FileStorageManager manager, ILogger<FileStorageManagerCached> logger)
|
||||
// {
|
||||
// this.manager = manager;
|
||||
// this.logger = logger;
|
||||
// }
|
||||
// public Task<IEnumerable<string>> GetEmptyDirectories()
|
||||
// {
|
||||
// return manager.GetEmptyDirectories();
|
||||
// }
|
||||
|
||||
public async Task<IEnumerable<LocalCourse>> LoadSavedCourses()
|
||||
{
|
||||
// public async Task<IEnumerable<LocalCourse>> LoadSavedCourses()
|
||||
// {
|
||||
|
||||
var secondsFromLastLoad = (DateTime.Now - cacheTime)?.Seconds;
|
||||
// var secondsFromLastLoad = (DateTime.Now - cacheTime)?.Seconds;
|
||||
|
||||
if (cachedCourses != null && secondsFromLastLoad < cacheSeconds)
|
||||
{
|
||||
logger.LogInformation("returning cached courses from file");
|
||||
return cachedCourses;
|
||||
}
|
||||
// if (cachedCourses != null && secondsFromLastLoad < cacheSeconds)
|
||||
// {
|
||||
// logger.LogInformation("returning cached courses from file");
|
||||
// return cachedCourses;
|
||||
// }
|
||||
|
||||
cachedCourses = await manager.LoadSavedCourses();
|
||||
cacheTime = DateTime.Now;
|
||||
return cachedCourses;
|
||||
}
|
||||
// cachedCourses = await manager.LoadSavedCourses();
|
||||
// cacheTime = DateTime.Now;
|
||||
// return cachedCourses;
|
||||
// }
|
||||
|
||||
public async Task SaveCourseAsync(LocalCourse course, LocalCourse? previouslyStoredCourse)
|
||||
{
|
||||
// race condition...
|
||||
cacheTime = null;
|
||||
cachedCourses = null;
|
||||
await manager.SaveCourseAsync(course, previouslyStoredCourse);
|
||||
}
|
||||
}
|
||||
// public async Task SaveCourseAsync(LocalCourse course, LocalCourse? previouslyStoredCourse)
|
||||
// {
|
||||
// // race condition...
|
||||
// cacheTime = null;
|
||||
// cachedCourses = null;
|
||||
// await manager.SaveCourseAsync(course, previouslyStoredCourse);
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -4,5 +4,5 @@ public interface IFileStorageManager
|
||||
{
|
||||
Task SaveCourseAsync(LocalCourse course, LocalCourse? previouslyStoredCourse);
|
||||
Task<IEnumerable<LocalCourse>> LoadSavedCourses();
|
||||
IEnumerable<string> GetEmptyDirectories();
|
||||
Task<IEnumerable<string>> GetEmptyDirectories();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user