private void btnSelectBots_Click()

in #U5b9e#U8df5#U9879#U76ee/2019_MSC_#U9ec4#U91d1#U70b9/#U5fae#U8f6f#U9ec4#U91d1#U70b9#U7a0b#U5e8f#U5de5#U5177/OfflineGame/GameMaster/LocalManager/LocalManager/MainForm.cs [72:185]


        private void btnSelectBots_Click(object sender, EventArgs e)
        {
            // 默认选中内置的三个测试Bot
            var selectedPath = Application.StartupPath + "\\SampleBots";

            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.SelectedPath = selectedPath;
            var dialogResult = dialog.ShowDialog();
            if (!dialogResult.Equals(DialogResult.OK))
            {
                return;
            }

            if (string.IsNullOrEmpty(dialog.SelectedPath))
            {
                return;
            }

            Reset();

            selectedPath = dialog.SelectedPath;

            // Bot从1开始编号,找到有效的Bot,加入到Bot列表中
            int index = 1;
            var dirs = Directory.GetDirectories(selectedPath);
            foreach (var dir in dirs)
            {
                bool isSupportPython = Bot.IsSupportPython();
                bool isSupportJulia = Bot.IsSupportJulia();

                var exeFiles = Directory.GetFiles(dir, "*.exe");
                if (exeFiles.Length == 0)
                {
                    var getNumbersPyFile = Path.Combine(dir, "get_numbers.py");
                    var getNumbersJuliaFile = Path.Combine(dir, "get_numbers.jl");
                    if (isSupportPython && File.Exists(getNumbersPyFile))
                    {
                        botList.Add(new Bot(getNumbersPyFile, index++) { ActionLog = Log });
                    }
                    else if (isSupportJulia && File.Exists(getNumbersJuliaFile))
                    {
                        botList.Add(new Bot(getNumbersJuliaFile, index++) { ActionLog = Log });
                    }
                    else
                    {
                        Log($"警告:跳过 \"{dir}\" 没有找到exe{(isSupportPython ? "或者get_numbers.py" : "")}{(isSupportJulia ? "或者get_numbers.jl" : "")}");
                    }
                    continue;
                }
                else if (exeFiles.Length == 1)
                {
                    botList.Add(new Bot(exeFiles.First(), index++) { ActionLog = Log });
                    continue;
                }
                else if (exeFiles.Length > 1)
                {
                    Log($"警告:跳过 \"{dir}\" 找到多个exe");
                    continue;
                }
            }

            // 将Bot编号及Bot路径输出在日志窗口
            var botListString = string.Join("\r\n", botList.Select(bot => $"{bot.Index} --> {bot.FilePath}"));
            Log("找到如下Bot:\r\n" + botListString);

            // 初始化比赛数据表
            dtHistory = new DataTable("history");
            dtHistory.Columns.Add(new DataColumn("回合编号", typeof(int)));
            dtHistory.Columns.Add(new DataColumn("黄金点", typeof(double)));
            for (int i = 1; i <= botList.Count; i++)
            {
                dtHistory.Columns.Add(new DataColumn($"Bot{i.ToString("D3")}_1", typeof(double)));
                dtHistory.Columns.Add(new DataColumn($"Bot{i.ToString("D3")}_2", typeof(double)));
            }
            historyView.DataSource = dtHistory.DefaultView;

            // 初始化得分表
            dtScoreHistory = new DataTable("scoreHistory");
            dtScoreHistory.Columns.Add(new DataColumn("Bot编号", typeof(int)));
            dtScoreHistory.Columns.Add(new DataColumn("得分", typeof(int)));
            for (int i = 0; i < botList.Count; i++)
            {
                var dr = dtScoreHistory.NewRow();
                dr["Bot编号"] = botList[i].Index;
                dr["得分"] = 0;
                dtScoreHistory.Rows.Add(dr);
            }
            dvScoreHistory = new DataView(dtScoreHistory);
            dvScoreHistory.Sort = "得分 DESC";
            scoreView.DataSource = dvScoreHistory;

            // 得分图
            chartScore.DataSource = dtScoreHistory;
            chartScore.Series.Add("得分");
            chartScore.Series[0].XValueMember = "Bot编号";
            chartScore.Series[0].YValueMembers = "得分";
            chartScore.ChartAreas[0].AxisX.Title = "Bot编号";
            chartScore.ChartAreas[0].AxisY.Title = "得分";
            chartScore.DataBind();

            // 黄金点走势图
            chartGoldenNumber.DataSource = dtHistory;
            chartGoldenNumber.Series.Add("黄金点");
            chartGoldenNumber.Series[0].ChartType = SeriesChartType.Spline;
            chartGoldenNumber.Series[0].XValueMember = "回合编号";
            chartGoldenNumber.Series[0].YValueMembers = "黄金点";
            chartGoldenNumber.ChartAreas[0].AxisX.Title = "回合编号";
            chartGoldenNumber.ChartAreas[0].AxisY.Title = "黄金点";
            chartGoldenNumber.DataBind();

            btnPlayMultiRound.Enabled = true;
            btnStop.Enabled = true;
            btnExport.Enabled = true;
        }