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); }
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); } }