protected Match(MatchConfiguration conf) { Configuration = ObjectCopier.Clone(conf); Initdata = conf.Initdata; BeginTime = DateTime.Now; if (ActiveMatch != null) { throw new Exception(StringResources.NO_PARALLEL_MATCHES); } ActiveMatch = this; }
public LocalMatch(MatchConfiguration conf) : base(conf) { Browser = BotzoneProtocol.CurrentBrowser; Runners = conf.Select(x => { var runner = new LocalProgramRunner(); if (x.Type == PlayerType.LocalAI) { runner.ProgramPath = x.ID; } return(runner); }).ToArray(); Scores = new double[conf.Count]; DisplayLogs = new List <dynamic>(); Logs = new List <ILogItem>(); }
public BotzoneMatch(MatchConfiguration conf, string matchID) : base(conf) { MatchID = matchID; for (int i = 0; i < conf.Count; i++) { if (conf[i].Type != PlayerType.BotzoneBot) { MySlot = i; } } MyConf = Configuration[MySlot]; Runner = new LocalProgramRunner { ProgramPath = conf[MySlot].ID }; }
internal static async Task <string> RequestMatch(this MatchConfiguration conf) { if (!conf.IsValid) { return(null); } string matchID = null; do { Logger.Log(LogLevel.Info, "尝试向 Botzone 发起对局请求……"); var req = new HttpRequestMessage(HttpMethod.Get, Credentials.BotzoneRunMatchURL()); req.Headers.Add("X-Game", conf.Game.Name); req.Headers.Add("X-Initdata", conf.Initdata is string?conf.Initdata: JsonConvert.SerializeObject(conf.Initdata)); req.Headers.Add("X-UseSimpleIO", LocalProgramRunner.IsSimpleIO ? "true" : "false"); req.Headers.Add("X-Timelimit", Properties.Settings.Default.TimeLimit.TotalSeconds.ToString()); for (int i = 0; i < conf.Count; i++) { req.Headers.Add("X-Player-" + i, conf[i].Type == PlayerType.BotzoneBot ? conf[i].ID : "me"); } var res = await client.SendAsync(req); matchID = await res.Content.ReadAsStringAsync(); if (CheckResponse(res, matchID)) { break; } Logger.Log(LogLevel.InfoTip, "5秒后重试……"); await Task.Delay(5000); } while (true); Logger.Log(LogLevel.OK, "成功创建了新对局:" + matchID); return(matchID); }
/// <summary> /// 控制台模式程序入口。 /// </summary> private void ConsoleMain(string[] args) { string outputMatchCollectionPath = null, outputLogPath = null, lastOption = ""; Action <string> next = null; List <string> requiredArguments = new List <string>(); MatchConfiguration conf; Match[] matches = null; Logger = new ConsoleLogger(); try { // 解析参数 foreach (var arg in args.Skip(1)) { switch (arg) { case "-h": Console.WriteLine(StringResources.TITLE + " " + Assembly.GetEntryAssembly().GetName().Version); Console.WriteLine(String.Format(StringResources.CONSOLE_HELP, args[0])); return; case "-o": if (next != null) { throw new FormatException( String.Format(StringResources.CONSOLE_MISSING_ARGUMENT, lastOption)); } next = file => { if (File.Exists(file)) { try { using (var s = File.Open(file, FileMode.Open)) { var f = new BinaryFormatter(); matches = f.Deserialize(s) as Match[]; } } catch (Exception e) { throw new FormatException( StringResources.BAD_MATCH_COLLECTION_FORMAT + ": " + e.Message); } } outputMatchCollectionPath = file; }; break; case "-l": if (next != null) { throw new FormatException( String.Format(StringResources.CONSOLE_MISSING_ARGUMENT, lastOption)); } next = file => outputLogPath = file; break; case "-u": if (next != null) { throw new FormatException( String.Format(StringResources.CONSOLE_MISSING_ARGUMENT, lastOption)); } next = url => BotzoneProtocol.Credentials.BotzoneCopiedURL = url; break; case "--simple-io": LocalProgramRunner.IsSimpleIO = true; break; default: if (next != null) { next(arg); next = null; } else { requiredArguments.Add(arg); } break; } lastOption = arg; } if (next != null) { throw new FormatException( String.Format(StringResources.CONSOLE_MISSING_ARGUMENT, lastOption)); } if (requiredArguments.Count < 2) { throw new FormatException(StringResources.CONSOLE_BAD_FORMAT); } // 生成对局配置 conf = new MatchConfiguration { Game = new Game { Name = requiredArguments[0], PlayerCount = requiredArguments.Count - 1 } }; for (int i = 0; i < conf.Count; i++) { string arg = requiredArguments[i + 1]; if (File.Exists(arg)) { conf[i].Type = PlayerType.LocalAI; } else if (arg.Length == 24 && arg.All(c => c >= '0' && c <= '9' || c >= 'a' && c <= 'f')) { conf[i].Type = PlayerType.BotzoneBot; } else { throw new FormatException( String.Format(StringResources.CONSOLE_BAD_ID, arg)); } conf[i].ID = arg; } if (!conf.IsValid) { throw new FormatException(conf.ValidationString); } } catch (FormatException e) { Logger.Log(LogLevel.Error, e.Message); Console.WriteLine(String.Format(StringResources.CONSOLE_HELP, args[0])); return; } if (conf.IsLocalMatch) { Logger.Log(LogLevel.Info, StringResources.CONSOLE_LOCALMATCH); Cef.Initialize(new CefSettings { Locale = CultureInfo.CurrentCulture.Name }); var tcs = new TaskCompletionSource <object>(); var b = new CefSharp.OffScreen.ChromiumWebBrowser(); BotzoneProtocol.CurrentBrowser = b; b.BrowserInitialized += delegate { tcs.SetResult(null); }; tcs.Task.Wait(); } else { Logger.Log(LogLevel.Info, StringResources.CONSOLE_BOTZONEMATCH); if (!BotzoneProtocol.Credentials.IsValid) { Logger.Log(LogLevel.Error, StringResources.CONSOLE_BAD_LOCALAI_URL); Console.WriteLine(String.Format(StringResources.CONSOLE_HELP, args[0])); return; } } try { // 创建并开始对局 var matchTask = conf.CreateMatch(); matchTask.Wait(); var match = matchTask.Result; Console.CancelKeyPress += delegate { match.AbortMatch().Wait(); }; match.RunMatch().Wait(); string logJson = JsonConvert.SerializeObject(match.Logs); if (outputLogPath != null) { using (var sw = new StreamWriter(outputLogPath)) { sw.WriteLine(logJson); } } if (outputMatchCollectionPath != null) { using (var s = File.Open(outputMatchCollectionPath, FileMode.Create)) { var tempMatches = new Match[matches?.Length ?? 0]; matches?.CopyTo(tempMatches, 0); tempMatches[tempMatches.Length - 1] = match; var f = new BinaryFormatter(); f.Serialize(s, tempMatches); } } Console.WriteLine(logJson); Console.WriteLine( (match.Status == MatchStatus.Finished ? "finished " : "aborted ") + String.Join(" ", match.Scores)); } catch (Exception e) { Logger.Log(LogLevel.Error, e.Message); Console.WriteLine("error"); } finally { Cef.Shutdown(); } }