public ActionResult RunAnalysis(string first_id, string second_id)
        {
            CompareCommandOptions opts = new CompareCommandOptions();

            opts.FirstRunId  = first_id;
            opts.SecondRunId = second_id;
            foreach (BaseCompare c in AttackSurfaceAnalyzerCLI.GetComparators())
            {
                // The GUI *should* prevent us from getting here. But this is extra protection.
                // We won't start new collections while existing ones are ongoing.
                if (c.IsRunning() == RUN_STATUS.RUNNING)
                {
                    return(Json("Comparators already running!"));
                }
            }


            using (var cmd = new SqliteCommand(SQL_CHECK_IF_COMPARISON_PREVIOUSLY_COMPLETED, DatabaseManager.Connection, DatabaseManager.Transaction))
            {
                cmd.Parameters.AddWithValue("@base_run_id", opts.FirstRunId);
                cmd.Parameters.AddWithValue("@compare_run_id", opts.SecondRunId);
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        return(Json("Using cached comparison calculations."));
                    }
                }
            }

            Task.Factory.StartNew <Dictionary <string, object> >(() => AttackSurfaceAnalyzerCLI.CompareRuns(opts));

            return(Json("Started Analysis"));
        }
        public ActionResult GetComparators()
        {
            Dictionary <string, RUN_STATUS> dict = new Dictionary <string, RUN_STATUS>();

            foreach (BaseCompare c in AttackSurfaceAnalyzerCLI.GetComparators())
            {
                var fullString = c.GetType().ToString();
                var splits     = fullString.Split('.');
                dict.Add(splits[splits.Count() - 1], c.IsRunning());
            }

            //@TODO: Also return the RunId
            return(Json(JsonConvert.SerializeObject(dict)));
        }