public async override Task <OptimizerResult> Minimize(double[] parameters)
        {
            if (CancellationToken.IsCancellationRequested)
            {
                throw new TaskCanceledException();
            }

            if (_minimize == null)
            {
                var assembly = await _cSharpCompiler.CreateAssembly(Code);

                _minimize = _cSharpCompiler.GetDelegate(assembly);
            }

            var cost = await _minimize(parameters);

            await Task.Run(() =>
            {
                ActivityLogger.Add(Guid.NewGuid().ToString(), Keys, parameters, cost);
                //ActivityLogger.Add("Parameters:", parameters);
                //ActivityLogger.Add("Cost:", cost);
                //ActivityLogger.StateHasChanged();
            });

            return(new OptimizerResult(parameters, cost));
        }
        public async override Task <OptimizerResult> Minimize(double[] parameters)
        {
            if (CancellationToken.IsCancellationRequested)
            {
                throw new TaskCanceledException();
            }

            if (_minimize == null)
            {
                var assembly = await _cSharpCompiler.CreateAssembly(Code);

                var worker = await _workerFactory.CreateAsync();

                _backgroundService = await worker.CreateBackgroundServiceAsync <MinimizeFacade>();

                _minimize = _cSharpCompiler.GetDelegate(assembly);
            }

            var cost = await _backgroundService.RunAsync(r => r.Minimize(_minimize, parameters)).Result;

            await Task.Run(() =>
            {
                ActivityLogger.Add(Guid.NewGuid().ToString(), Keys, parameters, cost);
                //ActivityLogger.Add("Parameters:", parameters);
                //ActivityLogger.Add("Cost:", cost);
                //ActivityLogger.StateHasChanged();
            });

            return(new OptimizerResult(parameters, cost));
        }
        public async override Task <OptimizerResult> Minimize(double[] parameters)
        {
            if (CancellationToken.IsCancellationRequested)
            {
                throw new TaskCanceledException();
            }

            //Console.WriteLine("before:" + _code);
            _allResults = new Dictionary <string, double?>();

            var regex   = new Regex(@".*function\s+([\d\w]+)\s*\(([\w\d,\s]+)\)");
            var matches = regex.Matches(Code)[0].Groups;

            var appending = new StringBuilder(Code);

            appending.Append("\r\n");
            appending.Append(matches[1].Value);
            appending.Append("(");

            //todo: validate number of params
            var split = matches[2].Value.Split(',').Select(s => s.Trim());

            for (int i = 0; i < parameters.Count(); i++)
            {
                var item = parameters[i];
                appending.Append(item.ToString("N15").TrimEnd('0'));
                if (i < parameters.Count() - 1)
                {
                    appending.Append(",");
                }
            }
            appending.Append(");");

            var formatted = appending.ToString();
            //Console.WriteLine("after:" + formatted);


            var settings = new EvalContextSettings();

            settings.SerializableTypes.Add(typeof(DotNetObjectReference <JavascriptOptimizer>));
            dynamic context = new EvalContext(_jSRuntime, settings);

            string key = null;

            if (_blazorClientConfiguration.EnableOptimizerWorker)
            {
                //todo: support dotnet callback
                //(context as EvalContext).Expression = () => context.WorkerInterop.setWorkerCallback(DotNetObjectReference.Create(this), nameof(this.SetResult));
                //await (context as EvalContext).InvokeAsync<dynamic>();
                //(context as EvalContext).Reset();
                //(context as EvalContext).Expression = () => context.WorkerInterop.runWorker(formatted);
                //await (context as EvalContext).InvokeAsync<dynamic>();


                if (_blazorClientConfiguration.EnableOptimizerMultithreading)
                {
                    key = string.Join(",", parameters);
                    if (_allResults.ContainsKey(key))
                    {
                        return(new OptimizerResult(parameters, _allResults[key].Value));
                    }

                    await _jSRuntime.InvokeVoidAsync("WorkerPoolInterop.runWorker", DotNetObjectReference.Create(this), nameof(this.AddResult), formatted, key);

                    while (!_allResults.ContainsKey(key))
                    {
                        await Task.Delay(10);
                    }
                    ;
                }
                else
                {
                    await _jSRuntime.InvokeVoidAsync("WorkerInterop.setWorkerCallback", DotNetObjectReference.Create(this), nameof(this.SetResult));

                    await _jSRuntime.InvokeVoidAsync("WorkerInterop.runWorker", formatted);

                    while (_cost == null)
                    {
                        await Task.Delay(10);
                    }
                    ;
                }
            }
            else
            {
                _cost = await(context as EvalContext).InvokeAsync <double>(formatted);
            }

            await Task.Run(() =>
            {
                ActivityLogger.Add(Guid.NewGuid().ToString(), Keys, parameters, _cost ?? _allResults[key].Value);
                //ActivityLogger.Add("Parameters:", parameters);
                //ActivityLogger.Add("Cost:", _cost.Value);
                //ActivityLogger.StateHasChanged();
            });

            return(new OptimizerResult(parameters, _cost ?? _allResults[key].Value));
        }
        protected async Task OptimizeClick()
        {
            await Wait.Show();

            _stopWatch.Reset();
            _stopWatch.Start();

            IterationResult result = null;

            try
            {
                //Console.WriteLine(MinimizeFunctionCode.Code);

                OptimizerBase optimizer = null;
                if (MinimizeFunctionCode.Language == "javascript")
                {
                    optimizer = (JavascriptOptimizer)ServiceProvider.GetService(typeof(JavascriptOptimizer));
                }
                else if (MinimizeFunctionCode.Language == "csharp")
                {
                    optimizer = (CSharpThreadedOptimizer)ServiceProvider.GetService(typeof(CSharpThreadedOptimizer));
                }

                if (_config == null)
                {
                    ToastService.ShowError("No config was uploaded or created.");
                    await Wait.Hide();

                    return;
                }
                else
                {
                    var fitness = string.IsNullOrEmpty(_config.Fitness?.OptimizerTypeName) ? _config.FitnessTypeName : _config.Fitness.OptimizerTypeName;
                    ActivityLogger.ResetLog();
                    ActivityLogger.Add("Starting " + fitness);
                    optimizer.Initialize(MinimizeFunctionCode.Code, ActivityLogger);

                    TokenSource = new CancellationTokenSource();

                    var task = Task.Run(() => optimizer.Start(_config, TokenSource.Token), TokenSource.Token);

                    try
                    {
                        result = await task;
                    }
                    catch (TaskCanceledException)
                    {
                        CodeEditorBase.TokenSource = null;
                        await Wait.Hide();

                        ToastService.ShowInfo("Optimization was cancelled.");
                        TokenSource = null;
                        return;
                    }

                    TokenSource = null;

                    // Console.WriteLine(ActivityLogger.Log);

                    await JSRuntime.InvokeVoidAsync("ClientStorage.storeChartData", ActivityLogger.Log);

                    //todo: backticks
                    //dynamic context = new EvalContext(JSRuntime);
                    //(context as EvalContext).Expression = () => context.ClientStorage.storeChartData(ActivityLogger.Log);
                    //await (context as EvalContext).InvokeAsync<dynamic>();

                    ToastService.ShowSuccess("Chart data was saved.");
                }
            }
            catch (Exception ex)
            {
                await Wait.Hide();

                ToastService.ShowError(ex.Message);
                throw ex;
            }
            finally
            {
                await Wait.Hide();
            }

            _stopWatch.Stop();
            ToastService.ShowSuccess("Best Cost: " + result.Cost.ToString("N"));
            ToastService.ShowSuccess("Best Parameters: " + string.Join(",", result.ParameterSet.Select(s => s.ToString("N"))));
            ActivityLogger.Add("Best Cost: ", result.Cost);
            ActivityLogger.Add("Best Parameters: ", result.ParameterSet);
            ActivityLogger.Add("Total Time (s): ", _stopWatch.ElapsedMilliseconds / 1000);
        }