public ChangeSet(Dictionary <string, object> changes)
        {
            var changeSet          = new List <Tuple <SettingDescriptor, object> >();
            var isProblemAttribute = false;

            foreach (var change in changes)
            {
                try
                {
                    var name  = change.Key;
                    var value = change.Value;

                    // Setting name cannot be null or empty...
                    if (string.IsNullOrEmpty(name))
                    {
                        QBCLog.Error("Name may not be null or empty");
                        isProblemAttribute = true;
                        continue;
                    }

                    // Check that setting exists...
                    var settingDescriptor = RecognizedSettings.FirstOrDefault(s => s.Name == name);
                    if (settingDescriptor == null)
                    {
                        QBCLog.Error("Unable to locate setting for '{0}'.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Is changing attribute allowed?
                    if (settingDescriptor.IsAccessDisallowed)
                    {
                        QBCLog.Error("Accessing attribute '{0}' is not allowed.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Check that setting doesn't already exist in the changeset...
                    if (changeSet.Any(t => t.Item1.Name == name))
                    {
                        QBCLog.Error("Setting '{0}' already exists in the changeset.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // If user specified 'original' value, go look it up and substitute it for 'value'...
                    if ((value is string) && ((string)value == "original"))
                    {
                        object originalValue;

                        if (!OriginalConfiguration.TryGetValue(settingDescriptor.Name, out originalValue))
                        {
                            // A missing 'original configuration' is a maintenance issue, not a user error...
                            QBCLog.MaintenanceError("For setting '{0}', there is no original configuration value.",
                                                    settingDescriptor.Name);
                            isProblemAttribute = true;
                            continue;
                        }

                        value = originalValue;
                    }

                    // Check that setting is an appropriate type...
                    var newValue = settingDescriptor.ToCongruentObject(value);

                    if (!settingDescriptor.ConstraintChecker.IsWithinConstraints(newValue))
                    {
                        QBCLog.Error("For setting '{0}', the provided value '{1}' is not within the required constraints of {2}.",
                                     name, value, settingDescriptor.ConstraintChecker.Description);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Setting change is acceptable...
                    changeSet.Add(Tuple.Create(settingDescriptor, value));
                }

                catch (Exception ex)
                {
                    QBCLog.Exception(ex, "MAINTENANCE ERROR: Error processing attribute '{0}.'", change.Key);
                    isProblemAttribute = true;
                }
            }

            // If problem encountered with any change, we're unable to build the ChangeSet...
            if (isProblemAttribute)
            {
                _changeSet = null;
                throw new ArgumentException("Problems encountered with provided argument");
            }

            Count      = changeSet.Count;
            _changeSet = new ReadOnlyCollection <Tuple <SettingDescriptor, object> >(changeSet);
        }
Exemple #2
0
 internal Microsoft.CodeAnalysis.ChangeSignature.SignatureChange ToInternal()
 {
     return(new Microsoft.CodeAnalysis.ChangeSignature.SignatureChange(OriginalConfiguration.ToInternal(), UpdatedConfiguration.ToInternal()));
 }
        /// <summary>
        /// 实现了一个 Controller 逻辑
        /// </summary>
        /// <returns></returns>
        public override async Task RunMatch()
        {
            Logger.Log(LogLevel.Info, "正在从 Botzone 载入 Judge 程序...");
            Status = MatchStatus.Waiting;
            BrowserJSObject.Instance.JudgeTask = new TaskCompletionSource <string>();

            // 将人类玩家的位置插入网页中
            BotzoneCefRequestHandler.MatchInjectFilter = new CefSharp.Filters.FindReplaceResponseFilter(
                "<!-- INJECT_FINISHED_MATCH_LOGS_HERE -->",
                $@"
<script>
	playerSlotID = {OriginalConfiguration.FirstOrDefault(conf => conf.Type == PlayerType.LocalHuman)?.SlotID ?? -1};
</script>
");
            Browser.Load(BotzoneProtocol.Credentials.BotzoneLocalMatchURL(OriginalConfiguration.Game.Name));

            for (int i = 0; i < OriginalConfiguration.Count; i++)
            {
                SetIsSimpleIO(i, OriginalConfiguration[i].Type == PlayerType.LocalAI);
            }

            await BrowserJSObject.Instance.JudgeTask.Task;

            SetStatus("waiting");
            Status = MatchStatus.Running;
            Logger.Log(LogLevel.OK, "Judge 程序加载成功,开始本地对局");
            foreach (var conf in OriginalConfiguration)
            {
                conf.LogContent = "";
            }

            // 开始对局!
            while (true)
            {
                Logger.Log(LogLevel.Info, $"回合{Logs.Count / 2} - Judge 开始执行");
                BrowserJSObject.Instance.JudgeTask = new TaskCompletionSource <string>();

                // Judge 请求处理
                var judgeItem = new JudgeLogItem();
                Debug.Print($@"Botzone.emulated_gio.sendToJudge({
					JsonConvert.SerializeObject(new
					{
						log = Logs,
						initdata = Initdata
					})
				});"                );
                SendToJudge();
                Logs.Add(judgeItem);
                try
                {
                    var judgeRaw = await BrowserJSObject.Instance.JudgeTask.Task;
                    var output   = JsonConvert.DeserializeObject <JudgeOutput>(judgeRaw);
                    judgeItem.output  = output;
                    judgeItem.verdict = "OK";
                    if (Logs.Count == 1 && output.initdata != null &&
                        !(output.initdata is string && output.initdata.Length == 0))
                    {
                        Initdata = output.initdata;
                    }
                    AddFullLogItem(judgeItem);
                }
                catch (Exception ex)
                {
                    judgeItem.response = ex.Message;
                    judgeItem.verdict  = "RE";
                    AddFullLogItem(judgeItem);
                    Logger.Log(LogLevel.No, "Judge 崩溃或载入失败,游戏中止");
                    await OnFinish(true);

                    return;
                }

                // Judge 返回处理
                EmitEvent("match.newlog", judgeItem.output.display ?? "");
                DisplayLogs.Add(judgeItem.output.display);
                if (judgeItem.output.command == "finish")
                {
                    // 判定游戏结束
                    foreach (var pair in judgeItem.output.content)
                    {
                        Scores[int.Parse(pair.Key)] =
                            pair.Value is string?double.Parse(pair.Value) : (pair.Value ?? 0);
                    }
                    Logger.Log(LogLevel.OK, $"Judge 判定游戏结束,比分:{String.Join(", ", Scores)}");
                    await OnFinish(false);

                    return;
                }

                // 玩家请求与返回处理
                var humanID = -1;
                foreach (var pair in judgeItem.output.content)
                {
                    int id = int.Parse(pair.Key);
                    if (OriginalConfiguration[id].Type == PlayerType.LocalHuman)
                    {
                        humanID = id;
                        Logger.Log(LogLevel.InfoTip, $"Judge 向{id}号玩家(人类)发起请求");

                        // 人类玩家
                        BrowserJSObject.Instance.HumanTask = new TaskCompletionSource <string>();
                        EmitEvent("match.playerturn");
                        EmitEvent("match.newrequest", pair.Value);
                    }
                }

                var botItem = new BotLogItem();
                Logs.Add(botItem);
                foreach (var pair in judgeItem.output.content)
                {
                    int id   = int.Parse(pair.Key);
                    var conf = OriginalConfiguration[id];
                    if (conf.Type != PlayerType.LocalHuman)
                    {
                        // 本地 AI
                        var runner = Runners[id];
                        conf.LogContent += ">>> REQUEST" + Environment.NewLine;
                        if (LocalProgramRunner.IsSimpleIO)
                        {
                            JavascriptResponse req = await TransformRequestToSimpleIO(pair.Value);

                            Debug.Assert(req.Success);
                            runner.Requests.Add(req.Result);
                            conf.LogContent += req.Result + Environment.NewLine;
                            Logger.Log(LogLevel.InfoTip, $"Judge 向{id}号玩家(本地AI)发起请求:{req.Result}");
                        }
                        else
                        {
                            runner.Requests.Add(pair.Value);
                            var val = JsonConvert.SerializeObject(pair.Value);
                            conf.LogContent += val + Environment.NewLine;
                            Logger.Log(LogLevel.InfoTip, $"Judge 向{id}号玩家(本地AI)发起请求:{val}");
                        }
                        ProgramLogItem resp = null;
                        try
                        {
                            if (Status == MatchStatus.Aborted)
                            {
                                return;
                            }
                            resp = await runner.RunForResponse();

                            if (LocalProgramRunner.IsSimpleIO)
                            {
                                JavascriptResponse req = await TransformSimpleIOToResponse(resp.raw);

                                Debug.Assert(req.Success);
                                resp.response = req.Result;
                            }
                            Logger.Log(LogLevel.OK, $"{id}号玩家(本地AI)给出了反馈:{resp.raw ?? JsonConvert.SerializeObject(resp.response)}");
                        }
                        catch (TimeoutException)
                        {
                            resp = new ProgramLogItem
                            {
                                verdict = "TLE"
                            };
                            Logger.Log(LogLevel.Warning, $"{id}号玩家(本地AI)超时了……");
                        }
                        catch (RuntimeException e)
                        {
                            resp = new ProgramLogItem
                            {
                                verdict  = "RE",
                                response = e.Message
                            };
                            Logger.Log(LogLevel.Warning, $"{id}号玩家(本地AI)崩溃了:{e.Message}");
                        }
                        catch (Exception e)
                        {
                            resp = new ProgramLogItem
                            {
                                verdict  = "RE",
                                response = e.Message
                            };
                            Logger.Log(LogLevel.No, $"{id}号玩家(本地AI)无法正常启动:{e.Message}");
                        }
                        finally
                        {
                            botItem.Add(pair.Key, resp);
                            conf.LogContent += "<<< RESPONSE" + Environment.NewLine +
                                               (resp.raw ?? JsonConvert.SerializeObject(resp.response)) + Environment.NewLine;
                        }
                    }
                }
                if (humanID != -1)
                {
                    var resp = new ProgramLogItem();
                    var raw  = await BrowserJSObject.Instance.HumanTask.Task;
                    try
                    {
                        resp.response = JsonConvert.DeserializeObject(raw);
                    }
                    catch
                    {
                        resp.response = raw;
                    }
                    resp.verdict = "OK";
                    botItem.Add(humanID.ToString(), resp);
                    Logger.Log(LogLevel.OK, $"{humanID}号玩家(人类)给出了反馈");
                }
                AddFullLogItem(botItem);
            }
        }