问:
How to fail gracefully if custom configuration settings are not present/valid during ASP.NET Core 2 application startup (hosted in a Windows Service)?
I'm implementing a Web API using ASP.NET Core 2 (targeting .NET Framework 4.6.1) which is hosted in a Windows Service.

I've started with the example in Host an ASP.NET Core app in a Windows Service, but am having trouble implementing the following additional requirements:

When the Windows Service (or possibly the Web API it hosts) starts or restarts, I want to read some configuration (which happens to be in the Registry, but could be anywhere).

If this configuration is missing or invalid then the Web API/Windows Service should not start (or should stop if has already started), should log some error message and, ideally, signal some failure to the Service Control Manager (e.g. ERROR_BAD_CONFIGURATION = 1610).

If the configuration is present and valid, the Windows Service should start, start the Web API, and the configuration settings should be available to the Web API's Controllers (via Dependency Injection).

It isn't clear to me where in the Windows Service/Web application the logic to read & validate the custom config should go.

Depending on where I put the logic, if the config is invalid, there needs to be a graceful way to halt further start-up progress and to shutdown anything already started.

I can't see any obvious hooks for this in the ASP.NET, or Windows Services frameworks.

I've considered putting the read & validate logic in the following locations, but each comes with some problem(s):

In Main(), before calling IWebHost.RunAsService()

In a notification method of CustomWebHostService (maybe OnStarting()?)

During the initialisation of the Web API's Startup class (Configure() or ConfigureServices())

Can anyone shed any light onto how this can be done?

Option 1: In Main() before IWebHost.RunAsService()

This seems to be the cleanest way to fail fast, since if the config is missing/bad, then the Windows Service won't even be started.

However, this means that when the Service Control Manager starts the hosting executable, we won't register with it (via IWebHost.RunAsService()) so the SCM returns the error:

[SC] StartService FAILED 1053:

The service did not respond to the start or control request in a timely fashion.
```

<p>Ideally, the Service Control Manager should be aware of the reason for failure to start-up, and could then log this to the Event Log.<br>
I don't think this is possible unless we register with the Service Control Manager, which brings us to Option 2.</p>

<h1>Option 2: During the Windows Service startup</h1>

<p>In a previous incarnation of the Web API (in WCF) I subclassed <code>ServiceBase</code>, acquired and validated config in <code>ServiceBaseSubclass.OnStart()</code> and, if the config was invalid, set <code>this.ExitCode</code> and called <code>Stop()</code> as per the suggestion in What is the proper way for a Windows service to fail?. Like this:</p>

<pre class="lang-cs prettyprint-override"><code>partial class WebServicesHost : ServiceBase
{
    private ServiceHost _webServicesServiceHost;

    // From https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx
    private const int ErrorBadConfiguration = 1610;

    protected override void OnStart(string[] args)
    {
      base.OnStart(args);

      var customConfig = ReadAndValidateCustomConfig();
      if (customConfig != null)
      {
        var webService = new WebService(customConfig);
        _webServicesServiceHost = new ServiceHost(webService);
        _webServicesServiceHost.Open();
      }
      else
      {
        // Configuration is bad, stop the service
        ExitCode = ErrorBadConfiguration;
        Stop();
      }
    }
}
</code>```

When you then used the Service Control Manager to start and query the Windows Service, it correctly reported the failure:

C:\> sc start MyService

SERVICE_NAME: MyService
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 10764
        FLAGS              :

C:\> sc query MyService

SERVICE_NAME: MyService
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 1  STOPPED            <-- Service is stopped
        WIN32_EXIT_CODE    : 1610  (0x64a)         <-- and reports the reason for stopping
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
```

<p>In ASP.NET Core 2, if I subclass <code>WebHostService</code> (as described in Host an ASP.NET Core app in a Windows Service), then there only appear to be hooks for notification of the Windows Service's startup workflow progress (e.g. <code>OnStarting()</code> or <code>OnStarted()</code>), but no mention of how to stop the service safely.  </p>

<p>Looking at the <code>WebHostService</code> source and decompiling <code>ServiceBase</code> makes me think that it would be a very bad idea to call <code>ServiceBase.Stop()</code> from <code>CustomWebHostService.OnStarting()</code> since I think this leads to using a disposed object.</p>

<pre class="lang-cs prettyprint-override"><code>class CustomWebHostService : WebHostService
{
  // From https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx
  private const int ErrorBadConfiguration = 1610;

  public CustomWebHostService(IWebHost host) : base(host)
  {
  }

  protected override void OnStarting(string[] args)
  {
    base.OnStarting(args);

    var customConfig = ReadAndValidateCustomConfig();
    if (customConfig == null)
    {
      ExitCode = ErrorBadConfiguration;
      Stop();
    }
  }
}
</code>```

// Code from https://github.com/aspnet/Hosting/blob/2.0.1/src/Microsoft.AspNetCore.Hosting.WindowsServices/WebHostService.cs
public class WebHostService : ServiceBase
{
  protected sealed override void OnStart(string[] args)
  {
    OnStarting(args);

    _host
      .Services
      .GetRequiredService<IApplicationLifetime>()
      .ApplicationStopped
      .Register(() =>
      {
        if (!_stopRequestedByWindows)
        {
          Stop();
        }
      });

    _host.Start();

    OnStarted();
  }

  protected sealed override void OnStop()
  {
    _stopRequestedByWindows = true;
    OnStopping();
    _host?.Dispose();
    OnStopped();
  }
```

<p>Specifically, <code>CustomWebHostService.OnStarting()</code> would call <code>ServiceBase.Stop()</code> which, in turn, would call <code>WebHostService.OnStop()</code> which disposes <code>this._host</code>. Then the second statement in <code>WebServiceHost.OnStart()</code> is executed, using <code>this._host</code> after it has been disposed.</p>

<p>Confusingly, this approach actually appears to "work" since <code>CustomWebHostService.OnStarted()</code> doesn't end up getting called in my experiments. However, I suspect this is because an exception is thrown beforehand. This doesn't seem like something that should be relied upon, so doesn't feel like a particularly robust solution.</p>

<p>What is the proper way for a Windows service to fail during its startup suggests a different way, by deferring the <code>ServiceBase.Stop()</code> call (i.e. letting the Windows Service start, then stopping it the config turned out to be bad) but this appears to allow the Web API to begin starting-up before sweeping the legs out from under it by stopping the Windows Service at some arbitrary time in the future.</p>

<p>I think I'd rather not start the <strong>Web API</strong> if the Windows Service can tell that it shouldn't start, or get the Web API start-up to read the config and shut itself down (see Option 3).</p>

<p>Also, it is still not clear how the <code>customConfig</code> instance could be made available to the ASP.NET Core 2 Web Service classes.</p>

<h1>Option 3: During the initialisation of the Web Service's Startup class</h1>

<p>This would seem to be the best location for reading the configuration since the config logically belongs to the Web Service, and is not related to hosting.</p>

<p>I discovered the <code>IApplicationLifetime</code> interface has a <code>StopApplication()</code> method (see IApplicationLifetime section of Hosting in ASP.NET Core). This seems ideal.</p>

<pre class="lang-cs prettyprint-override"><code>public class Program
{
  public static void Main(string[] args)
  {
    if (Debugger.IsAttached)
    {
      BuildWebHost(args).Run();
    }
    else
    {
      BuildWebHost(args).RunAsCustomService();
    }
  }

  public static IWebHost BuildWebHost(string[] args) =>
      WebHost.CreateDefaultBuilder(args)
          .UseStartup<Startup>()
          .UseUrls("http://*:5000")
          .Build();
}

public class Startup
{
  public Startup(IConfiguration configuration)
  {
    Configuration = configuration;
  }

  public IConfiguration Configuration { get; }

  // This method gets called by the runtime. Use this method to add services to the container.
  public void ConfigureServices(IServiceCollection services)
  {
    services.AddMvc();
  }

  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime, IHostingEnvironment env)
  {
    appLifetime.ApplicationStarted.Register(OnStarted);
    appLifetime.ApplicationStopping.Register(OnStopping);
    appLifetime.ApplicationStopped.Register(OnStopped);

    var customConfig = ReadAndValidateCustomConfig();
    if (customConfig != null)
    {
      // TODO: Somehow make config available to MVC controllers

      app.UseMvc();
    }
    else
    {
      appLifetime.StopApplication();
    }
  }

  private void OnStarted()
  {
    // Perform post-startup activities here
    Console.WriteLine("OnStarted");
  }

  private void OnStopping()
  {
    // Perform on-stopping activities here
    Console.WriteLine("OnStopping");
  }

  private void OnStopped()
  {
    // Perform post-stopped activities here
    Console.WriteLine("OnStopped");
  }
}
</code>```

This "works" when debugging in Visual Studio (i.e. the process starts stand-alone and serves the Web API if the config is good, or shuts down cleanly if the config is bad),
although the log messages appear in a slightly odd order which makes me suspicious:

OnStopping
OnStarted
Hosting environment: Development
Content root path: [redacted]
Now listening on: http://[::]:5000
Application started. Press Ctrl+C to shut down.
OnStopped
```

When starting as a Windows Service where the config is invalid, the Service remains running, but the Web API always responds with 404 (Not Found).

Presumably, this means that the Web API has shut down, but the Windows Service hasn't been able to notice this, so hasn't shut itself down.

Looking again at the IApplication documentation, I notice it says:

The IApplicationLifetime interface allows you to perform post-startup and shutdown activities.

This suggests that I really shouldn't be calling StopApplication() during the start-up sequence. However, I can't see a way of deferring the call until after the application has started.

If that is not possible, is there another way to signal to ASP.NET Core 2 that the Startup.Configure() function has failed and the application should shutdown?

Conclusion

Any suggestions on a good way to achieve the above requirements would be welcomed, as well as pointing out that I've grossly misunderstood Windows Services and/or ASP.NET Core 2! :-)

答:
In a Web API service hosted in an HTTP.sys Windows service, I read configuration in the Window service's OnStart method.  You could add an else statement to if (File.Exists(configurationFile)), log, then throw an exception to halt startup.

```<code>using System;
using System.IO;
using System.ServiceProcess;
using Cotg.Core2.Contract;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json.Linq;

namespace Company.Test.Service
{
    public class WindowsService : ServiceBase
    {
        public static AppSettings AppSettings;
        public static ICoreLogger Logger;
        private IWebHost _webHost;

        protected override void OnStart(string[] Args)
        {
            // Parse configuration file.
            string contentRoot = AppDomain.CurrentDomain.BaseDirectory;
            const string environmentalVariableName = "ASPNETCORE_ENVIRONMENT";
            string environment = Environment.GetEnvironmentVariable(environmentalVariableName) ?? EnvironmentNames.Development;
            string configurationFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AppSettings.json");
            if (File.Exists(configurationFile))
            {
                JObject configuration = JObject.Parse(File.ReadAllText(configurationFile));
                AppSettings = configuration.GetValue(environment).ToObject<AppSettings>();
            }
            // Create logger.
            Logger = new ConcurrentDatabaseLogger(Environment.MachineName, AppSettings.AppName, AppSettings.ProcessName, AppSettings.AppLogsDatabase);
            // Create Http.sys web host.
            Logger.Log("Creating web host using HTTP.sys.");
            _webHost = WebHost.CreateDefaultBuilder(Args)
                .UseStartup<WebApiStartup>()
                .UseContentRoot(contentRoot)
                .UseHttpSys(Options =>
                {
                    Options.Authentication.Schemes = AppSettings.AuthenticationSchema;
                    Options.Authentication.AllowAnonymous = AppSettings.AllowAnonymous;
                    Options.MaxConnections = AppSettings.MaxConnections;
                    Options.MaxRequestBodySize = AppSettings.MaxRequestBodySize;
                    // Allow external access to service by opening TCP port via an Inbound Rule in Windows Firewall.
                    // To run service using a non-administrator account, grant the user access to URL via netsh.
                    //   Use an exact URL: netsh http add urlacl url=http://servername:9092/ user=domain\user.
                    //   Do not use a wildcard URL: netsh http add urlacl url=http://+:9092/ user=domain\user.
                    Options.UrlPrefixes.Add(AppSettings.Url);
                })
                .Build();
            _webHost.Start();
            Logger.Log($"Web host started.  Listening on {AppSettings.Url}.");
        }

        protected override void OnStop()
        {
            _webHost?.StopAsync(TimeSpan.FromSeconds(60));
        }
    }
}
</code>```

I don't bother with ASP.NET Core's ConfigBuilder since I need a strongly-typed configuration class in the Windows service startup before the ASP.NET Configure & ConfigureServices methods are called.  I just register my AppSettings class with ASP.NET Core's dependency injection so it's available to any controllers that need it.

```<code>public void ConfigureServices(IServiceCollection Services)
{
    Services.AddMvc();
    // Configure dependency injection.
    Services.AddSingleton(typeof(AppSettings), WindowsService.AppSettings);
    Services.AddSingleton(typeof(ICoreLogger), WindowsService.Logger);
}
</code>```

AppSettings.json has entries for all environments:

```<code>{
  "Dev": {
    "Key1": "Value1",
    "Key2": "Value2"
  },
  "Test": {
    "Key1": "Value1",
    "Key2": "Value2"
  },
  "Prod": {
    "Key1": "Value1",
    "Key2": "Value2"
  }
}
</code>```

Body:
I'm implementing a Web API using ASP.NET Core 2 (targeting .NET Framework 4.6.1) which is hosted in a Windows Service.

I've started with the example in Host an ASP.NET Core app in a Windows Service, but am having trouble implementing the following additional requirements:

When the Windows Service (or possibly the Web API it hosts) starts or restarts, I want to read some configuration (which happens to be in the Registry, but could be anywhere).

If this configuration is missing or invalid then the Web API/Windows Service should not start (or should stop if has already started), should log some error message and, ideally, signal some failure to the Service Control Manager (e.g. ERROR_BAD_CONFIGURATION = 1610).

If the configuration is present and valid, the Windows Service should start, start the Web API, and the configuration settings should be available to the Web API's Controllers (via Dependency Injection).

It isn't clear to me where in the Windows Service/Web application the logic to read & validate the custom config should go.

Depending on where I put the logic, if the config is invalid, there needs to be a graceful way to halt further start-up progress and to shutdown anything already started.

I can't see any obvious hooks for this in the ASP.NET, or Windows Services frameworks.

I've considered putting the read & validate logic in the following locations, but each comes with some problem(s):

In Main(), before calling IWebHost.RunAsService()

In a notification method of CustomWebHostService (maybe OnStarting()?)

During the initialisation of the Web API's Startup class (Configure() or ConfigureServices())

Can anyone shed any light onto how this can be done?

Option 1: In Main() before IWebHost.RunAsService()

This seems to be the cleanest way to fail fast, since if the config is missing/bad, then the Windows Service won't even be started.

However, this means that when the Service Control Manager starts the hosting executable, we won't register with it (via IWebHost.RunAsService()) so the SCM returns the error:

[SC] StartService FAILED 1053:

The service did not respond to the start or control request in a timely fashion.

Ideally, the Service Control Manager should be aware of the reason for failure to start-up, and could then log this to the Event Log.

I don't think this is possible unless we register with the Service Control Manager, which brings us to Option 2.

Option 2: During the Windows Service startup

In a previous incarnation of the Web API (in WCF) I subclassed ServiceBase, acquired and validated config in ServiceBaseSubclass.OnStart() and, if the config was invalid, set this.ExitCode and called Stop() as per the suggestion in What is the proper way for a Windows service to fail?. Like this:

partial class WebServicesHost : ServiceBase
{
    private ServiceHost _webServicesServiceHost;

    // From https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx
    private const int ErrorBadConfiguration = 1610;

    protected override void OnStart(string[] args)
    {
      base.OnStart(args);

      var customConfig = ReadAndValidateCustomConfig();
      if (customConfig != null)
      {
        var webService = new WebService(customConfig);
        _webServicesServiceHost = new ServiceHost(webService);
        _webServicesServiceHost.Open();
      }
      else
      {
        // Configuration is bad, stop the service
        ExitCode = ErrorBadConfiguration;
        Stop();
      }
    }
}

When you then used the Service Control Manager to start and query the Windows Service, it correctly reported the failure:

C:\> sc start MyService

SERVICE_NAME: MyService
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 10764
        FLAGS              :

C:\> sc query MyService

SERVICE_NAME: MyService
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 1  STOPPED            <-- Service is stopped
        WIN32_EXIT_CODE    : 1610  (0x64a)         <-- and reports the reason for stopping
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

In ASP.NET Core 2, if I subclass WebHostService (as described in Host an ASP.NET Core app in a Windows Service), then there only appear to be hooks for notification of the Windows Service's startup workflow progress (e.g. OnStarting() or OnStarted()), but no mention of how to stop the service safely.

Looking at the WebHostService source and decompiling ServiceBase makes me think that it would be a very bad idea to call ServiceBase.Stop() from CustomWebHostService.OnStarting() since I think this leads to using a disposed object.

class CustomWebHostService : WebHostService
{
  // From https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx
  private const int ErrorBadConfiguration = 1610;

  public CustomWebHostService(IWebHost host) : base(host)
  {
  }

  protected override void OnStarting(string[] args)
  {
    base.OnStarting(args);

    var customConfig = ReadAndValidateCustomConfig();
    if (customConfig == null)
    {
      ExitCode = ErrorBadConfiguration;
      Stop();
    }
  }
}

// Code from https://github.com/aspnet/Hosting/blob/2.0.1/src/Microsoft.AspNetCore.Hosting.WindowsServices/WebHostService.cs
public class WebHostService : ServiceBase
{
  protected sealed override void OnStart(string[] args)
  {
    OnStarting(args);

    _host
      .Services
      .GetRequiredService<IApplicationLifetime>()
      .ApplicationStopped
      .Register(() =>
      {
        if (!_stopRequestedByWindows)
        {
          Stop();
        }
      });

    _host.Start();

    OnStarted();
  }

  protected sealed override void OnStop()
  {
    _stopRequestedByWindows = true;
    OnStopping();
    _host?.Dispose();
    OnStopped();
  }

Specifically, CustomWebHostService.OnStarting() would call ServiceBase.Stop() which, in turn, would call WebHostService.OnStop() which disposes this._host. Then the second statement in WebServiceHost.OnStart() is executed, using this._host after it has been disposed.

Confusingly, this approach actually appears to "work" since CustomWebHostService.OnStarted() doesn't end up getting called in my experiments. However, I suspect this is because an exception is thrown beforehand. This doesn't seem like something that should be relied upon, so doesn't feel like a particularly robust solution.

What is the proper way for a Windows service to fail during its startup suggests a different way, by deferring the ServiceBase.Stop() call (i.e. letting the Windows Service start, then stopping it the config turned out to be bad) but this appears to allow the Web API to begin starting-up before sweeping the legs out from under it by stopping the Windows Service at some arbitrary time in the future.

I think I'd rather not start the Web API if the Windows Service can tell that it shouldn't start, or get the Web API start-up to read the config and shut itself down (see Option 3).

Also, it is still not clear how the customConfig instance could be made available to the ASP.NET Core 2 Web Service classes.

Option 3: During the initialisation of the Web Service's Startup class

This would seem to be the best location for reading the configuration since the config logically belongs to the Web Service, and is not related to hosting.

I discovered the IApplicationLifetime interface has a StopApplication() method (see IApplicationLifetime section of Hosting in ASP.NET Core). This seems ideal.

public class Program
{
  public static void Main(string[] args)
  {
    if (Debugger.IsAttached)
    {
      BuildWebHost(args).Run();
    }
    else
    {
      BuildWebHost(args).RunAsCustomService();
    }
  }

  public static IWebHost BuildWebHost(string[] args) =>
      WebHost.CreateDefaultBuilder(args)
          .UseStartup<Startup>()
          .UseUrls("http://*:5000")
          .Build();
}

public class Startup
{
  public Startup(IConfiguration configuration)
  {
    Configuration = configuration;
  }

  public IConfiguration Configuration { get; }

  // This method gets called by the runtime. Use this method to add services to the container.
  public void ConfigureServices(IServiceCollection services)
  {
    services.AddMvc();
  }

  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime, IHostingEnvironment env)
  {
    appLifetime.ApplicationStarted.Register(OnStarted);
    appLifetime.ApplicationStopping.Register(OnStopping);
    appLifetime.ApplicationStopped.Register(OnStopped);

    var customConfig = ReadAndValidateCustomConfig();
    if (customConfig != null)
    {
      // TODO: Somehow make config available to MVC controllers

      app.UseMvc();
    }
    else
    {
      appLifetime.StopApplication();
    }
  }

  private void OnStarted()
  {
    // Perform post-startup activities here
    Console.WriteLine("OnStarted");
  }

  private void OnStopping()
  {
    // Perform on-stopping activities here
    Console.WriteLine("OnStopping");
  }

  private void OnStopped()
  {
    // Perform post-stopped activities here
    Console.WriteLine("OnStopped");
  }
}

This "works" when debugging in Visual Studio (i.e. the process starts stand-alone and serves the Web API if the config is good, or shuts down cleanly if the config is bad),
although the log messages appear in a slightly odd order which makes me suspicious:

OnStopping
OnStarted
Hosting environment: Development
Content root path: [redacted]
Now listening on: http://[::]:5000
Application started. Press Ctrl+C to shut down.
OnStopped

When starting as a Windows Service where the config is invalid, the Service remains running, but the Web API always responds with 404 (Not Found).

Presumably, this means that the Web API has shut down, but the Windows Service hasn't been able to notice this, so hasn't shut itself down.

Looking again at the IApplication documentation, I notice it says:

The IApplicationLifetime interface allows you to perform post-startup and shutdown activities.

This suggests that I really shouldn't be calling StopApplication() during the start-up sequence. However, I can't see a way of deferring the call until after the application has started.

If that is not possible, is there another way to signal to ASP.NET Core 2 that the Startup.Configure() function has failed and the application should shutdown?

Conclusion

Any suggestions on a good way to achieve the above requirements would be welcomed, as well as pointing out that I've grossly misunderstood Windows Services and/or ASP.NET Core 2! :-)

Body:
In a Web API service hosted in an HTTP.sys Windows service, I read configuration in the Window service's OnStart method.  You could add an else statement to if (File.Exists(configurationFile)), log, then throw an exception to halt startup.

using System;
using System.IO;
using System.ServiceProcess;
using Cotg.Core2.Contract;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json.Linq;

namespace Company.Test.Service
{
    public class WindowsService : ServiceBase
    {
        public static AppSettings AppSettings;
        public static ICoreLogger Logger;
        private IWebHost _webHost;

        protected override void OnStart(string[] Args)
        {
            // Parse configuration file.
            string contentRoot = AppDomain.CurrentDomain.BaseDirectory;
            const string environmentalVariableName = "ASPNETCORE_ENVIRONMENT";
            string environment = Environment.GetEnvironmentVariable(environmentalVariableName) ?? EnvironmentNames.Development;
            string configurationFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AppSettings.json");
            if (File.Exists(configurationFile))
            {
                JObject configuration = JObject.Parse(File.ReadAllText(configurationFile));
                AppSettings = configuration.GetValue(environment).ToObject<AppSettings>();
            }
            // Create logger.
            Logger = new ConcurrentDatabaseLogger(Environment.MachineName, AppSettings.AppName, AppSettings.ProcessName, AppSettings.AppLogsDatabase);
            // Create Http.sys web host.
            Logger.Log("Creating web host using HTTP.sys.");
            _webHost = WebHost.CreateDefaultBuilder(Args)
                .UseStartup<WebApiStartup>()
                .UseContentRoot(contentRoot)
                .UseHttpSys(Options =>
                {
                    Options.Authentication.Schemes = AppSettings.AuthenticationSchema;
                    Options.Authentication.AllowAnonymous = AppSettings.AllowAnonymous;
                    Options.MaxConnections = AppSettings.MaxConnections;
                    Options.MaxRequestBodySize = AppSettings.MaxRequestBodySize;
                    // Allow external access to service by opening TCP port via an Inbound Rule in Windows Firewall.
                    // To run service using a non-administrator account, grant the user access to URL via netsh.
                    //   Use an exact URL: netsh http add urlacl url=http://servername:9092/ user=domain\user.
                    //   Do not use a wildcard URL: netsh http add urlacl url=http://+:9092/ user=domain\user.
                    Options.UrlPrefixes.Add(AppSettings.Url);
                })
                .Build();
            _webHost.Start();
            Logger.Log($"Web host started.  Listening on {AppSettings.Url}.");
        }

        protected override void OnStop()
        {
            _webHost?.StopAsync(TimeSpan.FromSeconds(60));
        }
    }
}

I don't bother with ASP.NET Core's ConfigBuilder since I need a strongly-typed configuration class in the Windows service startup before the ASP.NET Configure & ConfigureServices methods are called.  I just register my AppSettings class with ASP.NET Core's dependency injection so it's available to any controllers that need it.

public void ConfigureServices(IServiceCollection Services)
{
    Services.AddMvc();
    // Configure dependency injection.
    Services.AddSingleton(typeof(AppSettings), WindowsService.AppSettings);
    Services.AddSingleton(typeof(ICoreLogger), WindowsService.Logger);
}

AppSettings.json has entries for all environments:

{
  "Dev": {
    "Key1": "Value1",
    "Key2": "Value2"
  },
  "Test": {
    "Key1": "Value1",
    "Key2": "Value2"
  },
  "Prod": {
    "Key1": "Value1",
    "Key2": "Value2"
  }
}


来源: stackexchange

问:
Gson error: Reflection is not allowed on private java.lang.String java.util.regex.Pattern.pattern
I'm using .fronJson of Gson,

```<code> List<MyPattern> MyPattern = gson.fromJson(jsonReader,
         new TypeToken<List<MyPattern>>() {}.getType() );
</code>```

but I got the error message below

java.lang.SecurityException: java.lang.IllegalAccessException: Reflection is not allowed on private java.lang.String java.util.regex.Pattern.pattern
      at com.google.appengine.runtime.Request.process-ea4f755134111bd0(Request.java)
      at java.lang.reflect.Field.setAccessible(Field.java:197)
      at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:157)

Here's my class MyPattern.

```<code>public class MyPattern {
    public String category;
    public Pattern regex;

    public void setCategory(String category) {
        this.category = category;
    }

    public String getCategory() {
        return category;
    }

    public void setRegex(String regex) {
        this.regex = Pattern.compile(regex);
    }

    public Pattern getRegex() {
        return regex;
    }

    @Override
    public String toString() {
        return "key: " + this.category + ", pattern: " + this.regex;
    }
}
</code>```

Just wondering is this error caused by Pattern.compile()? It works if I change public Pattern regex;
to
public String regex; with

public void setRegex(String regex) {
        this.regex = regex;
    }. But wondering why Pattern doesn't work and it there a way to solve it and keep using Pattern.

答:
It looks like the SecurityException was thrown because of some sandbox restrictions enforced by Google App Engine (see this post)

To get around this I would recommend the following setup:

```<code>public class MyPattern {
    public String category;
    public String regex;
    public Pattern pattern;

    public Pattern getPattern() {
        if(pattern == null) {
            pattern = Pattern.compile(regex);
        }
        return pattern;
    }
}
</code>```

I haven't tested it on Google App Engine but you'll most likely have to do something along those lines

ContentLicense: CC BY-SA 3.0

Body:
I'm using .fronJson of Gson,

 List<MyPattern> MyPattern = gson.fromJson(jsonReader,
         new TypeToken<List<MyPattern>>() {}.getType() );

but I got the error message below

java.lang.SecurityException: java.lang.IllegalAccessException: Reflection is not allowed on private java.lang.String java.util.regex.Pattern.pattern
      at com.google.appengine.runtime.Request.process-ea4f755134111bd0(Request.java)
      at java.lang.reflect.Field.setAccessible(Field.java:197)
      at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:157)

Here's my class MyPattern.

public class MyPattern {
    public String category;
    public Pattern regex;

    public void setCategory(String category) {
        this.category = category;
    }

    public String getCategory() {
        return category;
    }

    public void setRegex(String regex) {
        this.regex = Pattern.compile(regex);
    }

    public Pattern getRegex() {
        return regex;
    }

    @Override
    public String toString() {
        return "key: " + this.category + ", pattern: " + this.regex;
    }
}

Just wondering is this error caused by Pattern.compile()? It works if I change public Pattern regex;
to
public String regex; with

public void setRegex(String regex) {
        this.regex = regex;
    }. But wondering why Pattern doesn't work and it there a way to solve it and keep using Pattern.

Body:
It looks like the SecurityException was thrown because of some sandbox restrictions enforced by Google App Engine (see this post)

To get around this I would recommend the following setup:

public class MyPattern {
    public String category;
    public String regex;
    public Pattern pattern;

    public Pattern getPattern() {
        if(pattern == null) {
            pattern = Pattern.compile(regex);
        }
        return pattern;
    }
}

I haven't tested it on Google App Engine but you'll most likely have to do something along those lines


问:
Animate lines in a donut chart using a canvas
Basically I try to animate the lines in a donut chart (see example), so that each of them is counted up with document.ready. I tried to adopt the solution from here and here

As you can see, the countUp solution is already working well, but it needs to be connected to the chart, so that it is drawn on page load.

My knowledge regarding canvas isn´t amazing. I would be very happy, if anybody could help. Here is the code: https://jsfiddle.net/9oyoh67x/10/

```<code>$(document).ready(function () {
var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            console.log(ctx);
            ctx.lineWidth = 19;
            ctx.lineCap = 'round';
            ctx.shadowBlur = 10;
            donutChart();
            function degtoRad(degree) {
                var factor = Math.PI / 180; // = 1 deg = 0.01745 rad
                return degree * factor; // for 360 = 6.28 = 360°
            }

            /*function move() {
                var elem = document.getElementById("canvas");
                var width = 0;
                var id = setInterval(countUp, 1000); }
            */

            $(function () {
                var countUp = setInterval(function () { donutChart }, 40);
                function count($this) {
                    var current = parseInt($this.html(), 10);
                    $this.html(++current);
                    if (current !== $this.data('count')) {
                        setTimeout(function () { count($this) }, 50);
                    }
                }
                $(".testspan1").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
                 $(".testspan2").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
                 $(".testspan3").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
                 $(".testspan4").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
            });

            function donutChart() {
                var factor_calc = Math.PI / 180;
                var record = $('.testspan1').text(); // equal to 100% or 360°
                var average = $('.testspan2').text();
                var income = $('.testspan2').text();
                var target = $('.testspan3').text();

                // Record
                ctx.strokeStyle = 'rgba(115, 100, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 200, degtoRad(270), degtoRad(270 + (record / record) * 360));
                ctx.stroke();

                // Average
                ctx.strokeStyle = 'rgba(125, 131, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 170, degtoRad(270), degtoRad(270 + (average / record) * 360));
                ctx.stroke();

                //Income
                ctx.strokeStyle = 'rgba(75, 181, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 140, degtoRad(270), degtoRad(270 + (income / record) * 360));
                ctx.stroke();

                // Target
                ctx.strokeStyle = 'rgba(26, 221, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 110, degtoRad(270), degtoRad(270 + (target / record) * 360));
                ctx.stroke();

                // Record
                ctx.font = "25px Philosopher";
                ctx.fillStyle = 'rgba(115, 100, 164, 1)';
                ctx.fillText(record, 220, 200);

                //Average
                ctx.font = "25px Philosopher";
                ctx.fillStyle = 'rgba(125, 131, 164, 1)';
                ctx.fillText(average, 220, 230);

                //Income
                ctx.font = "30px Philosopher";
                ctx.fillStyle = 'rgba(75, 181, 164, 1)';
                ctx.fillText(income, 220, 260);

                // Target
                ctx.font = "35px Philosopher";
                ctx.fillStyle = 'rgba(26, 221, 164, 1)';
                ctx.fillText(target, 220, 290);

                // Euro
                ctx.font = "60px Philosopher";
                ctx.fillStyle = 'rgba(26, 221, 164, 1)';
                ctx.fillText('€', 280, 255);
            }

            var options = {
                useEasing: true,
                useGrouping: true,
                separator: ',',
                decimal: '',
                prefix: '',
                suffix: '€'

            };
        });
</code>```

HTML:

```<code>        <div class="canvasdiv">
        <canvas id="canvas" width="500" height="500"></canvas>
        <img id="myImage" />
        <span class='testspan1'>1250</span>
        <span class='testspan2'>250</span>
        <span class='testspan3'>450</span>
        <span class='testspan4'>130</span>
    </div>
</code>```

For people with similar problems, here are some further related links (using no canvas):

https://bl.ocks.org/mattkohl/9f3a283813cf0226311f41595582c9eb

https://codepen.io/hi-im-si/pen/uhxFn

https://jsfiddle.net/z60sxotr/1/

https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_setinterval_progressbar

答:
I made it. Here is my solution (https://jsfiddle.net/9oyoh67x/12/):</p>

```<code>// requestAnimationFrame Shim
(function start() {
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    window.requestAnimationFrame = requestAnimationFrame;
})();

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
console.log(ctx);
ctx.lineWidth = 19;
ctx.lineCap = 'round';
ctx.shadowBlur = 10;
var record = 820; // equal to 100% or 360°
var record_count = (record / record * 100)
var average = (229 / record * 100);
var income = (490 / record * 100);
var target = (750 / record * 100);
var counterClockwise = true;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
var startTime1 = null;
var startTime2 = null;
var startTime3 = null;
var startTime4 = null;
var duration = null;
var duration1 = null;
var duration2 = null;
var duration3 = null;
var duration4 = null;
var options = {
    useEasing: true,
    useGrouping: true,
    separator: ',',
    decimal: '0',
    prefix: '',
    suffix: ''
};

function animate_rec(time) {

    if (!startTime1) {
        startTime1 = time;
    }

    var delta1 = Math.min(1, (time - startTime1) / duration1);
    var curPerc = ((2 * Math.PI) / 100) * (record_count * delta1);
    console.log(curPerc)
    var innerNumRec = (record * delta1);
    //console.log(innerNumRec);

    ctx.strokeStyle = 'rgba(115, 100, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 200, -quart, curPerc - quart);
    ctx.stroke();

    if (delta1 < 1) {
        requestAnimationFrame(animate_rec);
        ctx.clearRect(215, 180, 50, 30);
    } else {
        startTime1 = null;
        ctx.clearRect(215, 180, 50, 30);
    }

    // Record
    ctx.font = "25px Philosopher";
    ctx.fillStyle = 'rgba(115, 100, 164, 1)';
    ctx.fillText(Math.round(innerNumRec), 220, 200);
}

var startAnim_rec = function () {
    duration1 = 3000;
    requestAnimationFrame(animate_rec);
};

function animate_avg(time) {

    if (!startTime2) {
        startTime2 = time;
    }

    var delta2 = Math.min(1, (time - startTime2) / duration2);
    var curPerc = ((2 * Math.PI) / 100) * (average * delta2);
    var innerNumAvg = ((average * record / 100) * delta2);
    console.log(innerNumAvg);

    ctx.strokeStyle = 'rgba(125, 131, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 170, -quart, curPerc - quart);
    ctx.stroke();

    if (delta2 < 1) {
        requestAnimationFrame(animate_avg);
        ctx.clearRect(215, 210, 70, 50);
    } else {
        startTime2 = null;
        ctx.clearRect(215, 210, 70, 50);
    }

    // Average
    ctx.font = "30px Philosopher";
    ctx.fillStyle = 'rgba(125, 131, 164, 1)';
    ctx.fillText(Math.round(innerNumAvg), 220, 230);

}

var startAnim_avg = function () {
    duration2 = 3200;
    requestAnimationFrame(animate_avg);
};

function animate_inc(time) {

    if (!startTime3) {
        startTime3 = time;
    }

    var delta3 = Math.min(1, (time - startTime3) / duration3);
    var curPerc = ((2 * Math.PI) / 100) * (income * delta3);
    var innerNumInc = ((income * record / 100) * delta3);
    console.log(innerNumInc);

    ctx.strokeStyle = 'rgba(75, 181, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 140, -quart, curPerc - quart);
    ctx.stroke();

    if (delta3 < 1) {
        requestAnimationFrame(animate_inc);
        ctx.clearRect(215, 230, 70, 50);
    } else {
        startTime3 = null;
        ctx.clearRect(215, 230, 70, 50);
    }

    // Income
    ctx.font = "35px Philosopher";
    ctx.fillStyle = 'rgba(75, 181, 164, 1)';
    ctx.fillText(Math.round(innerNumInc), 220, 260);
}

var startAnim_inc = function () {
    duration3 = 3400;
    requestAnimationFrame(animate_inc);
};

function animate_tar(time) {
    if (!startTime4) {
        startTime4 = time;
    }

    var delta4 = Math.min(1, (time - startTime4) / duration4);
    var curPerc = ((2 * Math.PI) / 100) * (target * delta4);
    var innerNumTar = ((target * record / 100) * delta4);
    console.log(innerNumTar);

    ctx.strokeStyle = 'rgba(26, 221, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 110, -quart, curPerc - quart);
    ctx.stroke();

    if (delta4 < 1) {
        requestAnimationFrame(animate_tar);
        ctx.clearRect(220, 260, 70, 50);
    } else {
        startTime4 = null;
        ctx.clearRect(220, 260, 70, 50);
    }

    // Target
    ctx.font = "40px Philosopher";
    ctx.fillStyle = 'rgba(26, 221, 164, 1)';
    ctx.fillText(Math.round(innerNumTar), 220, 290);
}

var startAnim_tar = function () {
    duration4 = 3600;
    requestAnimationFrame(animate_tar);
};

startAnim_rec();
startAnim_avg();
startAnim_inc();
startAnim_tar();

// Euro
ctx.font = "60px Philosopher";
ctx.fillStyle = 'rgba(26, 221, 164, 1)';
ctx.fillText('€', 280, 255);});
</code>```

Body:
Basically I try to animate the lines in a donut chart (see example), so that each of them is counted up with document.ready. I tried to adopt the solution from here and here

As you can see, the countUp solution is already working well, but it needs to be connected to the chart, so that it is drawn on page load.

My knowledge regarding canvas isn´t amazing. I would be very happy, if anybody could help. Here is the code: https://jsfiddle.net/9oyoh67x/10/

$(document).ready(function () {
var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            console.log(ctx);
            ctx.lineWidth = 19;
            ctx.lineCap = 'round';
            ctx.shadowBlur = 10;
            donutChart();
            function degtoRad(degree) {
                var factor = Math.PI / 180; // = 1 deg = 0.01745 rad
                return degree * factor; // for 360 = 6.28 = 360°
            }

            /*function move() {
                var elem = document.getElementById("canvas");
                var width = 0;
                var id = setInterval(countUp, 1000); }
            */

            $(function () {
                var countUp = setInterval(function () { donutChart }, 40);
                function count($this) {
                    var current = parseInt($this.html(), 10);
                    $this.html(++current);
                    if (current !== $this.data('count')) {
                        setTimeout(function () { count($this) }, 50);
                    }
                }
                $(".testspan1").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
                 $(".testspan2").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
                 $(".testspan3").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
                 $(".testspan4").each(function () {
                    $(this).data('count', parseInt($(this).html(), 10));
                    $(this).html('0');
                    count($(this));
                });
            });

            function donutChart() {
                var factor_calc = Math.PI / 180;
                var record = $('.testspan1').text(); // equal to 100% or 360°
                var average = $('.testspan2').text();
                var income = $('.testspan2').text();
                var target = $('.testspan3').text();

                // Record
                ctx.strokeStyle = 'rgba(115, 100, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 200, degtoRad(270), degtoRad(270 + (record / record) * 360));
                ctx.stroke();

                // Average
                ctx.strokeStyle = 'rgba(125, 131, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 170, degtoRad(270), degtoRad(270 + (average / record) * 360));
                ctx.stroke();

                //Income
                ctx.strokeStyle = 'rgba(75, 181, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 140, degtoRad(270), degtoRad(270 + (income / record) * 360));
                ctx.stroke();

                // Target
                ctx.strokeStyle = 'rgba(26, 221, 164, 1)';
                ctx.beginPath();
                ctx.arc(250, 250, 110, degtoRad(270), degtoRad(270 + (target / record) * 360));
                ctx.stroke();

                // Record
                ctx.font = "25px Philosopher";
                ctx.fillStyle = 'rgba(115, 100, 164, 1)';
                ctx.fillText(record, 220, 200);

                //Average
                ctx.font = "25px Philosopher";
                ctx.fillStyle = 'rgba(125, 131, 164, 1)';
                ctx.fillText(average, 220, 230);

                //Income
                ctx.font = "30px Philosopher";
                ctx.fillStyle = 'rgba(75, 181, 164, 1)';
                ctx.fillText(income, 220, 260);

                // Target
                ctx.font = "35px Philosopher";
                ctx.fillStyle = 'rgba(26, 221, 164, 1)';
                ctx.fillText(target, 220, 290);

                // Euro
                ctx.font = "60px Philosopher";
                ctx.fillStyle = 'rgba(26, 221, 164, 1)';
                ctx.fillText('€', 280, 255);
            }

            var options = {
                useEasing: true,
                useGrouping: true,
                separator: ',',
                decimal: '',
                prefix: '',
                suffix: '€'

            };
        });

HTML:

        <canvas id="canvas" width="500" height="500"></canvas>

        1250
        250
        450
        130

For people with similar problems, here are some further related links (using no canvas):

https://bl.ocks.org/mattkohl/9f3a283813cf0226311f41595582c9eb

https://codepen.io/hi-im-si/pen/uhxFn

https://jsfiddle.net/z60sxotr/1/

https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_setinterval_progressbar

Body:
I made it. Here is my solution (https://jsfiddle.net/9oyoh67x/12/):

// requestAnimationFrame Shim
(function start() {
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    window.requestAnimationFrame = requestAnimationFrame;
})();

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
console.log(ctx);
ctx.lineWidth = 19;
ctx.lineCap = 'round';
ctx.shadowBlur = 10;
var record = 820; // equal to 100% or 360°
var record_count = (record / record * 100)
var average = (229 / record * 100);
var income = (490 / record * 100);
var target = (750 / record * 100);
var counterClockwise = true;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
var startTime1 = null;
var startTime2 = null;
var startTime3 = null;
var startTime4 = null;
var duration = null;
var duration1 = null;
var duration2 = null;
var duration3 = null;
var duration4 = null;
var options = {
    useEasing: true,
    useGrouping: true,
    separator: ',',
    decimal: '0',
    prefix: '',
    suffix: ''
};

function animate_rec(time) {

    if (!startTime1) {
        startTime1 = time;
    }

    var delta1 = Math.min(1, (time - startTime1) / duration1);
    var curPerc = ((2 * Math.PI) / 100) * (record_count * delta1);
    console.log(curPerc)
    var innerNumRec = (record * delta1);
    //console.log(innerNumRec);

    ctx.strokeStyle = 'rgba(115, 100, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 200, -quart, curPerc - quart);
    ctx.stroke();

    if (delta1 < 1) {
        requestAnimationFrame(animate_rec);
        ctx.clearRect(215, 180, 50, 30);
    } else {
        startTime1 = null;
        ctx.clearRect(215, 180, 50, 30);
    }

    // Record
    ctx.font = "25px Philosopher";
    ctx.fillStyle = 'rgba(115, 100, 164, 1)';
    ctx.fillText(Math.round(innerNumRec), 220, 200);
}

var startAnim_rec = function () {
    duration1 = 3000;
    requestAnimationFrame(animate_rec);
};

function animate_avg(time) {

    if (!startTime2) {
        startTime2 = time;
    }

    var delta2 = Math.min(1, (time - startTime2) / duration2);
    var curPerc = ((2 * Math.PI) / 100) * (average * delta2);
    var innerNumAvg = ((average * record / 100) * delta2);
    console.log(innerNumAvg);

    ctx.strokeStyle = 'rgba(125, 131, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 170, -quart, curPerc - quart);
    ctx.stroke();

    if (delta2 < 1) {
        requestAnimationFrame(animate_avg);
        ctx.clearRect(215, 210, 70, 50);
    } else {
        startTime2 = null;
        ctx.clearRect(215, 210, 70, 50);
    }

    // Average
    ctx.font = "30px Philosopher";
    ctx.fillStyle = 'rgba(125, 131, 164, 1)';
    ctx.fillText(Math.round(innerNumAvg), 220, 230);

}

var startAnim_avg = function () {
    duration2 = 3200;
    requestAnimationFrame(animate_avg);
};

function animate_inc(time) {

    if (!startTime3) {
        startTime3 = time;
    }

    var delta3 = Math.min(1, (time - startTime3) / duration3);
    var curPerc = ((2 * Math.PI) / 100) * (income * delta3);
    var innerNumInc = ((income * record / 100) * delta3);
    console.log(innerNumInc);

    ctx.strokeStyle = 'rgba(75, 181, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 140, -quart, curPerc - quart);
    ctx.stroke();

    if (delta3 < 1) {
        requestAnimationFrame(animate_inc);
        ctx.clearRect(215, 230, 70, 50);
    } else {
        startTime3 = null;
        ctx.clearRect(215, 230, 70, 50);
    }

    // Income
    ctx.font = "35px Philosopher";
    ctx.fillStyle = 'rgba(75, 181, 164, 1)';
    ctx.fillText(Math.round(innerNumInc), 220, 260);
}

var startAnim_inc = function () {
    duration3 = 3400;
    requestAnimationFrame(animate_inc);
};

function animate_tar(time) {
    if (!startTime4) {
        startTime4 = time;
    }

    var delta4 = Math.min(1, (time - startTime4) / duration4);
    var curPerc = ((2 * Math.PI) / 100) * (target * delta4);
    var innerNumTar = ((target * record / 100) * delta4);
    console.log(innerNumTar);

    ctx.strokeStyle = 'rgba(26, 221, 164, 1)';
    ctx.beginPath();
    ctx.arc(250, 250, 110, -quart, curPerc - quart);
    ctx.stroke();

    if (delta4 < 1) {
        requestAnimationFrame(animate_tar);
        ctx.clearRect(220, 260, 70, 50);
    } else {
        startTime4 = null;
        ctx.clearRect(220, 260, 70, 50);
    }

    // Target
    ctx.font = "40px Philosopher";
    ctx.fillStyle = 'rgba(26, 221, 164, 1)';
    ctx.fillText(Math.round(innerNumTar), 220, 290);
}

var startAnim_tar = function () {
    duration4 = 3600;
    requestAnimationFrame(animate_tar);
};

startAnim_rec();
startAnim_avg();
startAnim_inc();
startAnim_tar();

// Euro
ctx.font = "60px Philosopher";
ctx.fillStyle = 'rgba(26, 221, 164, 1)';
ctx.fillText('€', 280, 255);});


问:
svg bbox() always returns a value where x and y are 0 when they shouldn't be
I'm using SVG.js to draw shapes. One of the shapes needs to be a circle with a radius line so so get that behavior, I'm using an ellipse and a line inside of a "g" element.

The trouble is, whenever I reference that g element and try to get the bbox, I always get a value like this:

```<code>{
 x: 0,
 y: 0,
 width: widthOfBox,
 height: heightOfBox,
 cx: widthOfBox/2,
 cy: heightOfBox/2
}
</code>```

x and y should NOT be 0.

Below is the element in question that is clearly not at (0,0) but seems to be reporting that it is.

```<code><g id="MLG1008" stroke="#000000" stroke-width="2" fill="#000000" transform="translate(100 200)" width="993.3559281546569" height="993.3559281546569" x="12.963409423828125" y="-290.0365905761719">
    <ellipse id="MLEllipse1009" rx="496.67796407732845" ry="496.67796407732845" cx="496.67796407732845" cy="496.67796407732845" stroke="#000000" stroke-width="2"></ellipse>
    <line id="MLLine1010" x1="496.67796407732845" y1="496.67796407732845" x2="801.6779640773284" y2="888.6779640773284" stroke="#000000" stroke-width="2"></line>
</g>
</code>```

Is there a way to define the values that bbox should have? Or a way to set the values that bbox() looks at?

答: Because your <g> positioned relative to <svg>. You need to use transform="translate(x, y)" to change the element position.

Body:
I'm using SVG.js to draw shapes. One of the shapes needs to be a circle with a radius line so so get that behavior, I'm using an ellipse and a line inside of a "g" element.

The trouble is, whenever I reference that g element and try to get the bbox, I always get a value like this:

{
 x: 0,
 y: 0,
 width: widthOfBox,
 height: heightOfBox,
 cx: widthOfBox/2,
 cy: heightOfBox/2
}

x and y should NOT be 0.

Below is the element in question that is clearly not at (0,0) but seems to be reporting that it is.

<g id="MLG1008" stroke="#000000" stroke-width="2" fill="#000000" transform="translate(100 200)" width="993.3559281546569" height="993.3559281546569" x="12.963409423828125" y="-290.0365905761719">
    <ellipse id="MLEllipse1009" rx="496.67796407732845" ry="496.67796407732845" cx="496.67796407732845" cy="496.67796407732845" stroke="#000000" stroke-width="2"></ellipse>
    <line id="MLLine1010" x1="496.67796407732845" y1="496.67796407732845" x2="801.6779640773284" y2="888.6779640773284" stroke="#000000" stroke-width="2"></line>
</g>

Is there a way to define the values that bbox should have? Or a way to set the values that bbox() looks at?


问:
batch requests with credentials using React Apollo

How do you batch requests with credentials? I'm using an http-only JWT cookie and HttpLink allows me to pass a credentials: 'include' option which will forward the cookie through to my graphene server. When I try to switch to BatchHttpLink, it no longer accepts that option for configuration. Looking through the source, it doesn't appear there's an easy way to configure this. Anyone know how to handle this?

Here's how I was doing it without batching:

```<code>window['app-react'].GRAPHQL_URL = window['app-react'].GRAPHQL_URL || 'http://backend.app.local/graphiql'
const httpLink = new HttpLink({
  uri: window['app-react'].GRAPHQL_URL,
  credentials: 'include'
})
const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
})
</code>```

Here's how I wish it worked:

```<code>const batchHttpLink = new BatchHttpLink({
  uri: window['joor-react'].GRAPHQL_URL,
  credentials: 'include'
})
const client = new ApolloClient({
  link: batchHttpLink,
  cache: new InMemoryCache(),
})
</code>```

When I do it this way though, the JWT cookie isn't passed in the header.

答:
Right now apollo-link-batch-http is behind in its API compared to apollo-link-http. Here is a note from the docs (as of 2017-12-07)

Note: This package will be updated to remove the dependency on apollo-fetch an use the same options / API as the http-link

Using BatchHttpLink with apollo-fetch

The current API of apollo-link-batch-http requires a custom apollo-fetch if you want to make customizations to things like credentials. Here's a couple of options.

Provide a customFetch to createApolloFetch and define credentials in the fetch options.

Use apollo-fetch middleware

```<code>fetch.batchUse(({ options }, next) => {
  options.credentials = 'include';
  next();
});
</code>```

Body:
How do you batch requests with credentials? I'm using an http-only JWT cookie and HttpLink allows me to pass a credentials: 'include' option which will forward the cookie through to my graphene server. When I try to switch to BatchHttpLink, it no longer accepts that option for configuration. Looking through the source, it doesn't appear there's an easy way to configure this. Anyone know how to handle this?

Here's how I was doing it without batching:

window['app-react'].GRAPHQL_URL = window['app-react'].GRAPHQL_URL || 'http://backend.app.local/graphiql'
const httpLink = new HttpLink({
  uri: window['app-react'].GRAPHQL_URL,
  credentials: 'include'
})
const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
})

Here's how I wish it worked:

const batchHttpLink = new BatchHttpLink({
  uri: window['joor-react'].GRAPHQL_URL,
  credentials: 'include'
})
const client = new ApolloClient({
  link: batchHttpLink,
  cache: new InMemoryCache(),
})

When I do it this way though, the JWT cookie isn't passed in the header.

Body:
Right now apollo-link-batch-http is behind in its API compared to apollo-link-http. Here is a note from the docs (as of 2017-12-07)

Note: This package will be updated to remove the dependency on apollo-fetch an use the same options / API as the http-link

Using BatchHttpLink with apollo-fetch

The current API of apollo-link-batch-http requires a custom apollo-fetch if you want to make customizations to things like credentials. Here's a couple of options.

Provide a customFetch to createApolloFetch and define credentials in the fetch options.

Use apollo-fetch middleware

fetch.batchUse(({ options }, next) => {
  options.credentials = 'include';
  next();
});


问:
TwiML Answering Machine Detection for Masked Calling
I'm using Twilio to connect my "users" with my on-call "staff", but I want to use masked calling as the staff are remote and I need to track how long the calls lasted, so don't want them having each others numbers.

This is all working perfectly using TwiML, but I have the issue that my staff may not answer a call, and the user will be sent to their answering machine. My server will then detect the call was longer than 0 seconds, and will charge the user even though they only got through to the answering machine... So the Answering Machine Detection sounds like what I need: https://www.twilio.com/docs/api/voice/answering-machine-detection

However this doesn't give any examples for use with TwiML.
It would seem based off this question that it is not usable? (Using Answering machine detection on Twiml)

So is there any update since the linked answer? Or is it possible for me to do the masked calls without TwiML? Does the response.SetOption method provide anything useful for this or will I have to live without Answering Machine Detection?

At present my code that generates the TwiML for the TwiML App is like this:

```<code>   public static string TwiMLDial(string maskedNumber, string to, string callCompleteURL)
    {
        var response = new Twilio.TwiML.VoiceResponse();
        var dial = new Twilio.TwiML.Voice.Dial(action: new Uri(callCompleteURL), callerId: maskedNumber);
        dial.Number(to);
        response.Gather();
        response.Dial(dial);
        return response.ToString();
    }
</code>```

答:
Twilio developer evangelist here.

You're right, you can't use the Answering Machine detection from TwiML. As an alternative, what you could do is put the dialling user straight into a queue (using <Enqueue>) and then dial your staff using the REST API and Answering machine detection. If the staff answer the call, connect them to the dialler by <Dial>ling the <Queue>.

Let me know if that helps at all.

Body:
I'm using Twilio to connect my "users" with my on-call "staff", but I want to use masked calling as the staff are remote and I need to track how long the calls lasted, so don't want them having each others numbers.

This is all working perfectly using TwiML, but I have the issue that my staff may not answer a call, and the user will be sent to their answering machine. My server will then detect the call was longer than 0 seconds, and will charge the user even though they only got through to the answering machine... So the Answering Machine Detection sounds like what I need: https://www.twilio.com/docs/api/voice/answering-machine-detection

However this doesn't give any examples for use with TwiML.
It would seem based off this question that it is not usable? (Using Answering machine detection on Twiml)

So is there any update since the linked answer? Or is it possible for me to do the masked calls without TwiML? Does the response.SetOption method provide anything useful for this or will I have to live without Answering Machine Detection?

At present my code that generates the TwiML for the TwiML App is like this:

   public static string TwiMLDial(string maskedNumber, string to, string callCompleteURL)
    {
        var response = new Twilio.TwiML.VoiceResponse();
        var dial = new Twilio.TwiML.Voice.Dial(action: new Uri(callCompleteURL), callerId: maskedNumber);
        dial.Number(to);
        response.Gather();
        response.Dial(dial);
        return response.ToString();
    }


问:
When should I be using `sparse`?
I've been looking through Matlab's sparse documentation trying to find whether there are any guidelines for when it makes sense to use a sparse representation rather than a full representation.

For example, I have a matrix data with around 30% nonzero entries. I can check the memory used.

```<code>whos data
  Name             Size                 Bytes  Class     Attributes

  data      84143929x11            4394073488  double    sparse
</code>```

```<code>data = full(data);
whos data
  Name             Size                 Bytes  Class     Attributes

  data      84143929x11            7404665752  double
</code>```

Here, I'm clearly saving memory, but would this be true of any matrix with 30% nonzero entries? What about 50% nonzero entries? Is there a rule of thumb for at what percentage I should switch to a full matrix?

What about computationally? Is it as a rule slower or faster to do a matrix multiplication with a sparse matrix? Sparse Matrix Operations says that

The computational complexity of sparse operations is proportional to
  nnz, the number of nonzero elements in the matrix. Computational
  complexity also depends linearly on the row size m and column size n
  of the matrix, but is independent of the product m*n, the total number
  of zero and nonzero elements.

This is difficult to compare to a full matrix without knowing more details.

Scipy's sparse matrix library explains pros and cons of each sparse format. For example for the csc_matrix

Advantages of the CSC format

efficient arithmetic operations CSC + CSC, CSC * CSC, etc.

efficient column slicing

fast matrix vector products (CSR, BSR may be faster)

Disadvantages of the CSC format

slow row slicing operations (consider CSR)

changes to the sparsity structure are expensive (consider LIL or DOK)

Does similar information about Matlab's sparse implementation exist? If so where can I find it?

答:
If you have a matrix of a fixed dimension, then the best way to establish a reliable answer is just trial and error. However, if you do not know the dimensions of your matrices/vectors, then the rules of thumb are

Your sparse vectors should have effectively constant number of nonzero entries

which for matrices will imply

Your N x N sparse matrix should have <= c * N nonzero entries, where c is a constant "much less" than N.

Let's give a pseudo-theoretical explanation to this rule. We shall consider a fairly easy task of making a scalar (or dot) product of two vectors with double valued coordinates. Now, if you have two dense vectors of the same length N, your code will look like

```<code>//define vectors vector, wector as double arrays of length N
double sum = 0;
for (int i = 0; i < N; i++)
{
    sum += vector[i] * wector[i];
}
</code>```

this amounts in N additions, N multiplications and N conditinal branches (cycle operations). The most costly operation here is the conditional branch, so costly, that we may neglect multiplications and the more so additions. The reason why it is so expensive is explained in an answer to this question.

UPD: In fact, in a for cycle, you risk to choose a wrong branch only once, at the end of your cycle, since by definition the default branch to choose will be going into the cycle. This amounts in at most 1 pipeline restart per scalar product operation.

Let's now have a look at how sparse vectors are realized in BLAS. There, each vector is encoded by two arrays: one of values and one of corresponding indices, something like

```<code>1.7    -0.8    3.6
171     83     215
</code>```

(plus one integer telling the supposed length N). It is indicated in the BLAS documentation, that the ordering of indices plays no role here, so that the data

```<code>-0.8    3.6    1.7
 83     215    171
</code>```

encodes the same vector. This remark gives enough information to reconstruct the algorithm for scalar product. Given two sparse vectors encoded by the data int[] indices, double[] values and int[] jndices, double[] walues, one will calculate their scalar product in the lines of this "code":

```<code>double sum = 0;
for (int i = 0; i < indices.length; i++)
{
    for (int j = 0; j < jndices.length; j++)
    {
        if(indices[i] == jndices[j])
        {
            sum += values[indices[i]] * walues[jndices[j]];
        }
    }
}
</code>```

which gives us a total amount of indices.length * jndices.length * 2 + indices.length conditional branches. This means that just in order to cope with the dense algorithm, your vectors are to have at most sqrt(N) nonzero entries. The point here is the dependency on N is already nonlinear, so there is no point in asking whether you need 1% or 10% or 25% filling. 10% is perfect for vectors of length 10, still sort of OK for length 50 and already a total ruin for length 100.

UPD. In this code snippet, you have an if branch, and the probability to take the wrong path is 50%. Thus, a scalar product of two sparse vectors will amount in about 0.5 to 1 times the average number of nonzero entries per sparse vector) pipeline restarts, depending on how sparse your vectors are . The numbers are to be adjusted: in an if statement without else, the shortest instruction will be taken first, which is "do nothing", but still.

Note that the most efficient operation is a scalar product of a sparse and a dense vector. Given a sparse vector of indices and values and a dense vector dense, your code will look like

```<code>double sum = 0;
for (int i = 0; i < indices.length; i++)
{
    sum += values[indices[i]] * dense[indices[i]];
}
</code>```

i.e. you'll have indices.length conditional branches, which is good.

UPD. Once again, I bet you'll have at most one pipeline restart per operation. Note also that afaik in modern multicore processors both alternatives are performed in parallel on two different cores, so that in alternative branches you only need to wait for the longest one to finish.

Now, when multiplying matrix with a vector, you basically take #rows scalar products of vectors. Multiplying matrix with matrix amounts in taking #((nonzero) columns in the second matrix) of matrix by vector multiplications. You are welcome figure out the complexity by yourself.

And so here is where all the <s>black magic</s> deep theory of different matrix storing begins. You may store your sparse matrix as dense array of sparse rows, as a sparse array of dense rows or sparse array of sparse rows. Same goes for columns. All the funny abbreviations from Scipy cited in the question have to do with that.

You will "always" have an advantage in speed if you multiply a matrix built of sparse rows with a dense matrix, or a matrix of dense columns. You may want to store your sparse matrix data as dense vectors of diagonals - so in the case of convolution neural networks - and then you'll need completely different algorithms. You may want to make your matrix a block matrix - so does BLAS - and get a reasonable computation boost. You may want to store your data as two matrices - say, a diagonal and a sparse, which is the case for finite element method. You could make use of sparsity for general neural networks (like. fast forward, extreme learning machine or echo state network) if you always multiply a row stored matrix by a column vector, but avoid multiplying matrices. And, you will "always" get an advantage by using sparse matrices if you follow the rule of thumb - it holds for finite element and convolution networks, but fails for reservoir computing.

Title: When should I be using `sparse`?

Body:
I've been looking through Matlab's sparse documentation trying to find whether there are any guidelines for when it makes sense to use a sparse representation rather than a full representation.

For example, I have a matrix data with around 30% nonzero entries. I can check the memory used.

whos data
  Name             Size                 Bytes  Class     Attributes

  data      84143929x11            4394073488  double    sparse

data = full(data);
whos data
  Name             Size                 Bytes  Class     Attributes

  data      84143929x11            7404665752  double

Here, I'm clearly saving memory, but would this be true of any matrix with 30% nonzero entries? What about 50% nonzero entries? Is there a rule of thumb for at what percentage I should switch to a full matrix?

What about computationally? Is it as a rule slower or faster to do a matrix multiplication with a sparse matrix? Sparse Matrix Operations says that

The computational complexity of sparse operations is proportional to
  nnz, the number of nonzero elements in the matrix. Computational
  complexity also depends linearly on the row size m and column size n
  of the matrix, but is independent of the product m*n, the total number
  of zero and nonzero elements.

This is difficult to compare to a full matrix without knowing more details.

Scipy's sparse matrix library explains pros and cons of each sparse format. For example for the csc_matrix

Advantages of the CSC format

efficient arithmetic operations CSC + CSC, CSC * CSC, etc.

efficient column slicing

fast matrix vector products (CSR, BSR may be faster)

Disadvantages of the CSC format

slow row slicing operations (consider CSR)

changes to the sparsity structure are expensive (consider LIL or DOK)

Does similar information about Matlab's sparse implementation exist? If so where can I find it?

Body:
If you have a matrix of a fixed dimension, then the best way to establish a reliable answer is just trial and error. However, if you do not know the dimensions of your matrices/vectors, then the rules of thumb are

Your sparse vectors should have effectively constant number of nonzero entries

which for matrices will imply

Your N x N sparse matrix should have <= c * N nonzero entries, where c is a constant "much less" than N.

Let's give a pseudo-theoretical explanation to this rule. We shall consider a fairly easy task of making a scalar (or dot) product of two vectors with double valued coordinates. Now, if you have two dense vectors of the same length N, your code will look like

//define vectors vector, wector as double arrays of length N
double sum = 0;
for (int i = 0; i < N; i++)
{
    sum += vector[i] * wector[i];
}

this amounts in N additions, N multiplications and N conditinal branches (cycle operations). The most costly operation here is the conditional branch, so costly, that we may neglect multiplications and the more so additions. The reason why it is so expensive is explained in an answer to this question.

UPD: In fact, in a for cycle, you risk to choose a wrong branch only once, at the end of your cycle, since by definition the default branch to choose will be going into the cycle. This amounts in at most 1 pipeline restart per scalar product operation.

Let's now have a look at how sparse vectors are realized in BLAS. There, each vector is encoded by two arrays: one of values and one of corresponding indices, something like

1.7    -0.8    3.6
171     83     215

(plus one integer telling the supposed length N). It is indicated in the BLAS documentation, that the ordering of indices plays no role here, so that the data

-0.8    3.6    1.7
 83     215    171

encodes the same vector. This remark gives enough information to reconstruct the algorithm for scalar product. Given two sparse vectors encoded by the data int[] indices, double[] values and int[] jndices, double[] walues, one will calculate their scalar product in the lines of this "code":

double sum = 0;
for (int i = 0; i < indices.length; i++)
{
    for (int j = 0; j < jndices.length; j++)
    {
        if(indices[i] == jndices[j])
        {
            sum += values[indices[i]] * walues[jndices[j]];
        }
    }
}

which gives us a total amount of indices.length * jndices.length * 2 + indices.length conditional branches. This means that just in order to cope with the dense algorithm, your vectors are to have at most sqrt(N) nonzero entries. The point here is the dependency on N is already nonlinear, so there is no point in asking whether you need 1% or 10% or 25% filling. 10% is perfect for vectors of length 10, still sort of OK for length 50 and already a total ruin for length 100.

UPD. In this code snippet, you have an if branch, and the probability to take the wrong path is 50%. Thus, a scalar product of two sparse vectors will amount in about 0.5 to 1 times the average number of nonzero entries per sparse vector) pipeline restarts, depending on how sparse your vectors are . The numbers are to be adjusted: in an if statement without else, the shortest instruction will be taken first, which is "do nothing", but still.

Note that the most efficient operation is a scalar product of a sparse and a dense vector. Given a sparse vector of indices and values and a dense vector dense, your code will look like

double sum = 0;
for (int i = 0; i < indices.length; i++)
{
    sum += values[indices[i]] * dense[indices[i]];
}

i.e. you'll have indices.length conditional branches, which is good.

UPD. Once again, I bet you'll have at most one pipeline restart per operation. Note also that afaik in modern multicore processors both alternatives are performed in parallel on two different cores, so that in alternative branches you only need to wait for the longest one to finish.

Now, when multiplying matrix with a vector, you basically take #rows scalar products of vectors. Multiplying matrix with matrix amounts in taking #((nonzero) columns in the second matrix) of matrix by vector multiplications. You are welcome figure out the complexity by yourself.

And so here is where all the <s>black magic</s> deep theory of different matrix storing begins. You may store your sparse matrix as dense array of sparse rows, as a sparse array of dense rows or sparse array of sparse rows. Same goes for columns. All the funny abbreviations from Scipy cited in the question have to do with that.

You will "always" have an advantage in speed if you multiply a matrix built of sparse rows with a dense matrix, or a matrix of dense columns. You may want to store your sparse matrix data as dense vectors of diagonals - so in the case of convolution neural networks - and then you'll need completely different algorithms. You may want to make your matrix a block matrix - so does BLAS - and get a reasonable computation boost. You may want to store your data as two matrices - say, a diagonal and a sparse, which is the case for finite element method. You could make use of sparsity for general neural networks (like. fast forward, extreme learning machine or echo state network) if you always multiply a row stored matrix by a column vector, but avoid multiplying matrices. And, you will "always" get an advantage by using sparse matrices if you follow the rule of thumb - it holds for finite element and convolution networks, but fails for reservoir computing.


问:
Stub Mongoose find method
I'm trying to stub the find or exec functions to test the following function:

```<code>function getOpenTickets() {
    return Ticket.find({})
        .populate('assignees', ['fullName', 'firstName', 'email', 'notificationSettings.dailyEmail'])
        .populate('property', 'name')
        .populate('type', 'title')
        .populate({path: 'unit', model: 'Unit', select: 'title'})
        .sort('created')
        .lean()
        .exec();
}
</code>```

I found several posts about stubbing mongoose methods but none of them worked for me, here is what I have:

```<code>it('should test getOpenTickets', async() => {
    findStub = sinon.stub(Ticket, 'find');
    var result = await utils.__get__('getOpenTickets')();
    findStub.restore();
});
</code>```

But I get:

```<code>Cannot read property 'populate' of undefined
</code>```

so I tried replacing it with a fake object:

```<code>var fakeFind = {
    args: {
        populate: [],
        sort: null,
        lean: null
    },
    populate: function (a) {
        this.args.populate.push(a)
    },
    sort: function (a) {
        this.args.sort = a;
    },
    lean: function () {
        this.args.lean = true
    },
    exec: function () {
        return Promise.resolve(this.args);
    }
}
</code>```

And

```<code>findStub = sinon.stub(Ticket, 'find').callsFake(fakeFind);
</code>```

And the result is:

```<code>TypeError: this.fakeFn.apply is not a function
</code>```

I've also tried stubbing mongoose.Model, prototype, exec, and some other stuff with no luck.

Any ideas?

答:
Try to use sinon-mongoose https://github.com/underscopeio/sinon-mongoose

Here is an example:

require('sinon');
require('sinon-mongoose');

sinon.mock(Ticket)
  .expects('find')
  .chain('populate').withArgs(/* args */)
  .chain('sort').withArgs('create')
  .chain('lean')
  .chain('exec')
  .resolves('SOME_VALUE');```

Title: Stub Mongoose find method

Body:
I'm trying to stub the find or exec functions to test the following function:

function getOpenTickets() {
    return Ticket.find({})
        .populate('assignees', ['fullName', 'firstName', 'email', 'notificationSettings.dailyEmail'])
        .populate('property', 'name')
        .populate('type', 'title')
        .populate({path: 'unit', model: 'Unit', select: 'title'})
        .sort('created')
        .lean()
        .exec();
}

I found several posts about stubbing mongoose methods but none of them worked for me, here is what I have:

it('should test getOpenTickets', async() => {
    findStub = sinon.stub(Ticket, 'find');
    var result = await utils.__get__('getOpenTickets')();
    findStub.restore();
});

But I get:

Cannot read property 'populate' of undefined

so I tried replacing it with a fake object:

var fakeFind = {
    args: {
        populate: [],
        sort: null,
        lean: null
    },
    populate: function (a) {
        this.args.populate.push(a)
    },
    sort: function (a) {
        this.args.sort = a;
    },
    lean: function () {
        this.args.lean = true
    },
    exec: function () {
        return Promise.resolve(this.args);
    }
}

And

findStub = sinon.stub(Ticket, 'find').callsFake(fakeFind);

And the result is:

TypeError: this.fakeFn.apply is not a function

I've also tried stubbing mongoose.Model, prototype, exec, and some other stuff with no luck.

Any ideas?


问:
Change launchScreen color
My application supported multi-theme. I need to change the launch screen color after user changing the theme.

Is this possible? I tried to set the color in app delegate in application.didFinishLaunchingWithOptions but nothing changed.

答:
No, a launch screen is static and can't be changed in any way at runtime.

Keep in mind that the launch screen is shown before your app is actually running.

Title: Change launchScreen color


问:
Why does my COM Smart Pointer get deleted when returning from method
Why does my COM Smart Pointer try to delete when I return from func.  I would think that it's still in scope.  Is there a way to avoid this?

This is the definition in the .TLH file

```<code>_COM_SMARTPTR_TYPEDEF(IComItem, __uuidof(IComItem));
</code>```

```<code>static IComItemPtr m_pItem;

LPDISPATCH func()
{
    IComItemPtr  pItem = m_pItem;

    pItem = pItem->GetParent();  // Returns parent as IComItemPtr

    return pItem;   // Gets deleted here

}
</code>```

答:
You first assumption is incorrect.

```<code>static IComItemPtr m_pItem;

LPDISPATCH func()
{
    IComItemPtr  pItem = m_pItem;

    pItem = pItem->GetParent();

    return pItem;  // not here.

}   // Gets deleted here (this is where scope is closed).
</code>```

The return will convert pItem from IComItemPtr to LPDISPATCH (IDispatch*) before the destructor is then called. The result of this conversion will be placed in the destination.

Note: how the conversion happens will depend entirely on the exact definition of the types involved.

Body:
Why does my COM Smart Pointer try to delete when I return from func.  I would think that it's still in scope.  Is there a way to avoid this?

This is the definition in the .TLH file

_COM_SMARTPTR_TYPEDEF(IComItem, __uuidof(IComItem));

static IComItemPtr m_pItem;

LPDISPATCH func()
{
    IComItemPtr  pItem = m_pItem;

    pItem = pItem->GetParent();  // Returns parent as IComItemPtr

    return pItem;   // Gets deleted here

}

Body:
You first assumption is incorrect.

static IComItemPtr m_pItem;

LPDISPATCH func()
{
    IComItemPtr  pItem = m_pItem;

    pItem = pItem->GetParent();

    return pItem;  // not here.

}   // Gets deleted here (this is where scope is closed).

The return will convert pItem from IComItemPtr to LPDISPATCH (IDispatch*) before the destructor is then called. The result of this conversion will be placed in the destination.

Note: how the conversion happens will depend entirely on the exact definition of the types involved.


问:
Efficient way to join a cached spark dataframe with other and cache again
I have a large dataframe that has been cached like

```<code>val largeDf = someLargeDataframe.cache
</code>```

Now I need to union it with a tiny one and cached it again

```<code>val tinyDf = someTinyDataframe.cache
val newDataframe = largeDf.union(tinyDf).cached
tinyDf.unpersist()
largeDf.unpersist()
</code>```

It is very inefficient since it need to re-cached all the data again. Is there any efficient way to add a little amount of data to a large cached dataframe?

After reading Teodors's explanation, I know that I can't unpersist the old dataframe before I do some action on my new dataframe. But what if I need to do something like this?

```<code>def myProcess(df1: Dataframe, df2: Dataframe): Dataframe{
    val df1_trans = df1.map(....).cache
    val df2_trans = df2.map(....).cache

    doSomeAction(df1_trans, df2_trans)

    val finalDf = df1_trans.union(df2_trans).map(....).cache
    // df1_trans.unpersist()
    // df2_trans.unpersist()
    finalDf
}
</code>```

I want my df1_trans & df2_trans to be cached to improve the performance inside the function since they will be called more than once, but the dataframe I need to return in the end is also constructed by df1_trans & df2_trans, if I can't unpersist them before leaving the function, I can never find other place to do this, however, if I unpersist them, my finalDf will not benefit from cache.

What can I do in this situation? Thanks!

答:
I'm just trying to answer the part of the question that is still unanswered here. There is one way to unpersist the df1_trans and df2_trans from your myProcess() function .You can create a temp view of the DataFrames using df1_trans.createOrReplaceTempView(viewName) and df2_trans.createOrReplaceTempView(viewName). See the Dataset API for reference. Then, after you do some action on those two DataFrames and you are ready to unpersist, you can do so like this - sqlContext.table(viewName).unpersist, where viewName is the name you used to create the temp view.

Hope this helps!

Body:
I have a large dataframe that has been cached like

val largeDf = someLargeDataframe.cache

Now I need to union it with a tiny one and cached it again

val tinyDf = someTinyDataframe.cache
val newDataframe = largeDf.union(tinyDf).cached
tinyDf.unpersist()
largeDf.unpersist()

It is very inefficient since it need to re-cached all the data again. Is there any efficient way to add a little amount of data to a large cached dataframe?

After reading Teodors's explanation, I know that I can't unpersist the old dataframe before I do some action on my new dataframe. But what if I need to do something like this?

def myProcess(df1: Dataframe, df2: Dataframe): Dataframe{
    val df1_trans = df1.map(....).cache
    val df2_trans = df2.map(....).cache

    doSomeAction(df1_trans, df2_trans)

    val finalDf = df1_trans.union(df2_trans).map(....).cache
    // df1_trans.unpersist()
    // df2_trans.unpersist()
    finalDf
}

I want my df1_trans & df2_trans to be cached to improve the performance inside the function since they will be called more than once, but the dataframe I need to return in the end is also constructed by df1_trans & df2_trans, if I can't unpersist them before leaving the function, I can never find other place to do this, however, if I unpersist them, my finalDf will not benefit from cache.

What can I do in this situation? Thanks!


问:
Menu Not Available from WAMP Server 2 Tray Icon on Windows 7 Machine
I've downloaded and installed WAMP Server version 2.1d on my Windows 7 machine. When I select "start WAMP Server" from the Start menu, the tray icon appears, but has no functionality. When I hover, the tool tip tells me that 1 of 2 services has started, but the server is offline (which is probably a separate issue). I've run Windows update and installed an optional update for my graphics driver. What else could be preventing the WAMP Server menu from appearing when I right-click the tray icon?</p>

答:
If the tray icon appears and has white color then your wamp server has began. can also be checked by going to http://localhost.

Anyways i hope you are getting the normal options when you left click on the tray icon. Right clicking the tray icon gives options to change language(which i hope you don't need) , a link to your localhost(can be found at C:\wamp\scripts\refresh.php) and a link to wamp website.I am sure no functionality is affected by these options.

ContentLicense: CC BY-SA 2.5


问:
How to convert class to it's child in Python?
I have a class called class_A I do some work with it and store it with pickle.
I have another class class_B which is a child of class_A but has some additional methods and properties. I want to load data from my pickled file as class_B and work with it. How can I do it?

答:
More details around your exact use case are needed to be certain, but  one of these abstract approaches may work for you.

```<code>b = Class_B()
b.__dict__ = pickled_data
</code>```

Or

```<code>b = Class_B(**pickled_data)
</code>```

Or

```<code>a = Class_A()
b = Class_B()
b.__dict__ = a.__dict__
</code>```

I'd recommend crating a class method to do what you need.

```<code>b = B.from_a(class_a, *args, **kwargs)
</code>```

ContentLicense: CC BY-SA 4.0

Body:
More details around your exact use case are needed to be certain, but  one of these abstract approaches may work for you.

b = Class_B()
b.__dict__ = pickled_data

Or

b = Class_B(**pickled_data)

Or

a = Class_A()
b = Class_B()
b.__dict__ = a.__dict__

I'd recommend crating a class method to do what you need.

b = B.from_a(class_a, *args, **kwargs)


问:
Prevent list containing an image from breaking
I have the following lay-out on my website: List of products

This is actually the Woocommerce product list which is an unordered list.

The HTML of the list looks something like this:

```<code><div class="widget widget_woocommerce_ndbproducts">
  <ul class="product_list_widget">
    <li>
      <a href="https://www.slagerijrudi.be/product/broodje-ham/" title="Broodje Ham">
      <img src="//www.slagerijrudi.be/wp-content/plugins/woocommerce/assets/images/placeholder.png" alt="Placeholder" width="180" class="woocommerce-placeholder wp-post-image" height="180">Broodje Ham</a>
      <span class="woocommerce-Price-amount amount">
        <span class="woocommerce-Price-currencySymbol">€</span>
        2,85
      </span>
    </li>
    <li>...</li>
    <li>...</li>
  </ul>
</div>
</code>```

In order to have this list in 4 columns on desktop, I've added the following CSS:

```<code>@media screen and (min-width: 1025px) {
  .four-columns ul.product_list_widget {
      -moz-column-count: 4;
      -moz-column-gap: 20px;
      -webkit-column-count: 4;
      -webkit-column-gap: 20px;
      column-count: 4;
      column-gap: 20px;
  }
}
</code>```

However, as you can see by the red arrows in my screenshot, the
 item gets a line break, which is not desired as the picture & price/text are no longer together this way.

Any ideas on how to prevent this?
If you want to test: this is the link.

答:
You need to add the page-break-inside: avoid and break-inside: avoid (has greater browser support) to the li items, which then prevent breaking inside those elements:

```<code>ul.cart_list li,
ul.product_list_widget li,
.widget_product_categories li {
  page-break-inside: avoid;
  break-inside: avoid;
}
</code>```

Body:
I have the following lay-out on my website: List of products

This is actually the Woocommerce product list which is an unordered list.

The HTML of the list looks something like this:

      Broodje Ham

        €
        2,85

...

...

In order to have this list in 4 columns on desktop, I've added the following CSS:

@media screen and (min-width: 1025px) {
  .four-columns ul.product_list_widget {
      -moz-column-count: 4;
      -moz-column-gap: 20px;
      -webkit-column-count: 4;
      -webkit-column-gap: 20px;
      column-count: 4;
      column-gap: 20px;
  }
}

However, as you can see by the red arrows in my screenshot, the
 item gets a line break, which is not desired as the picture & price/text are no longer together this way.

Any ideas on how to prevent this?
If you want to test: this is the link.

Body:
You need to add the page-break-inside: avoid and break-inside: avoid (has greater browser support) to the li items, which then prevent breaking inside those elements:

ul.cart_list li,
ul.product_list_widget li,
.widget_product_categories li {
  page-break-inside: avoid;
  break-inside: avoid;
}


问:
Program re-writes over saved file data
So I have this program that I've written in Python 2.7 which takes user input of various employee information and writes it to a file. I put the main block of code into a function, because I want to be able to run it multiple times. The code I currently have is below:

```<code>def employeeInformation():
    # opens text file data will be stored in
    with open('employeeFile.txt', 'w') as dataFile:
        # gets user input for employee name
        employeeName = raw_input('Employee Name: ')
        # checks if the input is a string or not
        if not employeeName.isalpha():
            print('Invalid data entry')
        else:
            # if input is string, write data to file
            dataFile.write(employeeName + '\n')

            # gets user input for employee age
            employeeAge = raw_input('Employee Age: ')
            if not employeeAge.isdigit():
                print('Invalid data entry')
            else:
                # if input is number, write data to file
                dataFile.write(employeeAge + '\n')

                # gets user input for employee role
                employeeRole = raw_input('Employee Role: ')
                if not employeeRole.isalpha():
                    print('Invalid data entry')
                else:
                    # if input is string, write data to file
                    dataFile.write(employeeRole + '\n')

                    employeeSalary = raw_input('Employee Salary: ')
                    if not employeeSalary.isdigit():
                        print('Invalid data entry')
                    else:
                        # if input is number, write data to file
                        dataFile.write(employeeSalary + '\n')
                    dataFile.close()

employeeInformation()
employeeInformation()
employeeInformation()
</code>```

Whenever it runs however, it only saves on of the function runs in the file, so instead of there being 9 pieces of data in the text file, there are only 3, which are the last 3 I input into the program. I can't figure out why it seems to be overwriting the data each time the function runs, does anyone know whats wrong with this code?

答:
your problem is you are using the 'w' mode of an openfile.
just as you can open in mode 'r' for reading a file, you can use 'a' for appending to a file.

just change this line:

```<code>with open('employeeFile.txt', 'w') as dataFile:
</code>```

to

```<code>with open('employeeFile.txt', 'a') as dataFile:
</code>```

that should solve your problems!

Title: Program re-writes over saved file data

Body:
So I have this program that I've written in Python 2.7 which takes user input of various employee information and writes it to a file. I put the main block of code into a function, because I want to be able to run it multiple times. The code I currently have is below:

def employeeInformation():
    # opens text file data will be stored in
    with open('employeeFile.txt', 'w') as dataFile:
        # gets user input for employee name
        employeeName = raw_input('Employee Name: ')
        # checks if the input is a string or not
        if not employeeName.isalpha():
            print('Invalid data entry')
        else:
            # if input is string, write data to file
            dataFile.write(employeeName + '\n')

            # gets user input for employee age
            employeeAge = raw_input('Employee Age: ')
            if not employeeAge.isdigit():
                print('Invalid data entry')
            else:
                # if input is number, write data to file
                dataFile.write(employeeAge + '\n')

                # gets user input for employee role
                employeeRole = raw_input('Employee Role: ')
                if not employeeRole.isalpha():
                    print('Invalid data entry')
                else:
                    # if input is string, write data to file
                    dataFile.write(employeeRole + '\n')

                    employeeSalary = raw_input('Employee Salary: ')
                    if not employeeSalary.isdigit():
                        print('Invalid data entry')
                    else:
                        # if input is number, write data to file
                        dataFile.write(employeeSalary + '\n')
                    dataFile.close()

employeeInformation()
employeeInformation()
employeeInformation()

Whenever it runs however, it only saves on of the function runs in the file, so instead of there being 9 pieces of data in the text file, there are only 3, which are the last 3 I input into the program. I can't figure out why it seems to be overwriting the data each time the function runs, does anyone know whats wrong with this code?

Body:
your problem is you are using the 'w' mode of an openfile.
just as you can open in mode 'r' for reading a file, you can use 'a' for appending to a file.

just change this line:

with open('employeeFile.txt', 'w') as dataFile:

to

with open('employeeFile.txt', 'a') as dataFile:

that should solve your problems!