<commit_before>﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;
using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using Ninject;
using Ninject.Modules;
using Sonneville.Fidelity.Shell.Configuration;
using Sonneville.Fidelity.WebDriver.Configuration;
using Sonneville.Utilities.Persistence.v2;

namespace Sonneville.Fidelity.Shell.AppStartup.NinjectModules
{
    public class ConfigModule : NinjectModule
    {
        public override void Load()
        {
            var workingDirectory = GetWorkingDirectory();
            
            ConfigureLog4Net(workingDirectory);
            Bind<ILog>().ToProvider<LogProvider>();

            Rebind<IDataStore>().To<JsonDataStore>().InSingletonScope();
            var configPath = Path.Combine(
                workingDirectory,
                "FidelityWebDriver.Demo.json"
            );
            Bind<string>().ToConstant(configPath)
                .WhenInjectedExactlyInto<JsonDataStore>();

            Rebind<FidelityConfiguration>().ToMethod(context => DataStore.Get<FidelityConfiguration>());
            Rebind<SeleniumConfiguration>().ToMethod(context => DataStore.Get<SeleniumConfiguration>());
        }

        private IDataStore DataStore => KernelInstance.Get<JsonDataStore>();

        private static string GetWorkingDirectory()
        {
            return Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                GetAssemblyAttribute<AssemblyCompanyAttribute>().Company,
                GetAssemblyAttribute<AssemblyTitleAttribute>().Title
            );
        }

        private static void ConfigureLog4Net(string workingDirectory)
        {
            var localDataPath = workingDirectory;
            var layout = ConfigurePatternLayout();
            var rollingFileAppender = ConfigureRollingFileAppender(layout, localDataPath);
            var consoleAppender = ConfigureConsoleAppender(layout);

            var hierarchy = (Hierarchy) LogManager.GetRepository();
            hierarchy.Root.AddAppender(rollingFileAppender);
            hierarchy.Root.AddAppender(consoleAppender);
            hierarchy.Root.Level = Level.All;
            hierarchy.Configured = true;
        }

        private static T GetAssemblyAttribute<T>()
        {
            return Assembly.GetExecutingAssembly()
                .GetCustomAttributes(typeof(T), false)
                .Cast<T>()
                .Single();
        }

        private static PatternLayout ConfigurePatternLayout()
        {
            var patternLayout = new PatternLayout
            {
                ConversionPattern = "%date [%thread] %-5level %logger - %message%newline"
            };
            patternLayout.ActivateOptions();
            return patternLayout;
        }

        private static RollingFileAppender ConfigureRollingFileAppender(ILayout layout, string loggingDirectory)
        {
            var appender = new RollingFileAppender
            {
                Name = "Default logger",
                AppendToFile = true,
                File = Path.Combine(loggingDirectory, $"Demo-{DateTime.Today:yyyyMMdd}.log"),
                Layout = layout,
                MaxSizeRollBackups = 5,
                MaximumFileSize = "10MB",
                RollingStyle = RollingFileAppender.RollingMode.Size,
                StaticLogFileName = true,
                ImmediateFlush = true,
                Threshold = Level.All,
            };
            appender.ActivateOptions();
            return appender;
        }

        private static IAppender ConfigureConsoleAppender(ILayout layout)
        {
            var appender = new ConsoleAppender
            {
                Name = "Console appender",
                Layout = layout,
                Target = Console.Error.ToString(),
                Threshold = Level.Warn,
            };
            appender.ActivateOptions();
            return appender;
        }
    }
}<commit_msg>Cleaned up ConfigModule * Extracted all logic from Load method * Extracted Activate helper functions<commit_after>﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;
using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using Ninject;
using Ninject.Modules;
using Sonneville.Fidelity.Shell.Configuration;
using Sonneville.Fidelity.WebDriver.Configuration;
using Sonneville.Utilities.Persistence.v2;

namespace Sonneville.Fidelity.Shell.AppStartup.NinjectModules
{
    public class ConfigModule : NinjectModule
    {
        public override void Load()
        {
            var workingDirectory = GetWorkingDirectory();
            ConfigureLog4Net(workingDirectory);
            ConfigureLocalDataStore(workingDirectory);
        }

        private static string GetWorkingDirectory()
        {
            return Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                GetAssemblyAttribute<AssemblyCompanyAttribute>().Company,
                GetAssemblyAttribute<AssemblyTitleAttribute>().Title
            );
        }

        private void ConfigureLog4Net(string workingDirectory)
        {
            var layout = ConfigurePatternLayout();
            var rollingFileAppender = ConfigureRollingFileAppender(layout, workingDirectory);
            var consoleAppender = ConfigureConsoleAppender(layout);

            var hierarchy = (Hierarchy) LogManager.GetRepository();
            hierarchy.Root.AddAppender(rollingFileAppender);
            hierarchy.Root.AddAppender(consoleAppender);
            hierarchy.Root.Level = Level.All;
            hierarchy.Configured = true;
        
            Bind<ILog>().ToProvider<LogProvider>();
        }

        private void ConfigureLocalDataStore(string workingDirectory)
        {
            Rebind<IDataStore>().To<JsonDataStore>().InSingletonScope();
            var configPath = Path.Combine(
                workingDirectory,
                "FidelityWebDriver.Demo.json"
            );
            Bind<string>().ToConstant(configPath)
                .WhenInjectedExactlyInto<JsonDataStore>();

            var dataStore = KernelInstance.Get<IDataStore>();
            Rebind<FidelityConfiguration>().ToMethod(context => dataStore.Get<FidelityConfiguration>());
            Rebind<SeleniumConfiguration>().ToMethod(context => dataStore.Get<SeleniumConfiguration>());
        }

        private static T GetAssemblyAttribute<T>()
        {
            return Assembly.GetExecutingAssembly()
                .GetCustomAttributes(typeof(T), false)
                .Cast<T>()
                .Single();
        }

        private static ILayout ConfigurePatternLayout()
        {
            return ActivateLayout(new PatternLayout
            {
                ConversionPattern = "%date [%thread] %-5level %logger - %message%newline"
            });
        }

        private static IAppender ConfigureRollingFileAppender(ILayout layout, string loggingDirectory)
        {
            return ActivateAppender(new RollingFileAppender
            {
                Name = "Default logger",
                AppendToFile = true,
                File = Path.Combine(loggingDirectory, $"Demo-{DateTime.Today:yyyyMMdd}.log"),
                Layout = layout,
                MaxSizeRollBackups = 5,
                MaximumFileSize = "10MB",
                RollingStyle = RollingFileAppender.RollingMode.Size,
                StaticLogFileName = true,
                ImmediateFlush = true,
                Threshold = Level.All,
            });
        }

        private static IAppender ConfigureConsoleAppender(ILayout layout)
        {
            return ActivateAppender(new ConsoleAppender
            {
                Name = "Console appender",
                Layout = layout,
                Target = Console.Error.ToString(),
                Threshold = Level.Warn,
            });
        }

        private static IAppender ActivateAppender(AppenderSkeleton appender)
        {
            appender.ActivateOptions();
            return appender;
        }

        private static ILayout ActivateLayout(LayoutSkeleton layout)
        {
            layout.ActivateOptions();
            return layout;
        }
    }
}
{'fraction_non_alphanumeric': 0.08254043767840152, 'fraction_numerical': 0.0028544243577545195, 'mean_word_length': 2.072341980270369, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6614963', 'n_tokens_mistral': 2111, 'n_tokens_neox': 2013, 'n_words': 376}