diff --git a/.github/workflows/upload_COS.yml b/.github/workflows/upload_COS.yml
index 71f2fc8..e39ee87 100644
--- a/.github/workflows/upload_COS.yml
+++ b/.github/workflows/upload_COS.yml
@@ -7,7 +7,7 @@ name: "upload_COS"
on:
push:
- branches: [ main, dev ]
+ branches: [ main ]
jobs:
client_build:
@@ -137,7 +137,6 @@ jobs:
- name: Remove Files
run: |
rm ./THUAI6/hash.json
-
rm ./THUAI6/win/win64/PresentationCore.dll
rm ./THUAI6/win/win64/PresentationFramework.dll
diff --git a/CAPI/cmd/RunServer.cmd b/CAPI/cmd/RunServer.cmd
index aa5213e..93b8129 100644
--- a/CAPI/cmd/RunServer.cmd
+++ b/CAPI/cmd/RunServer.cmd
@@ -1,5 +1,5 @@
@echo off
-.\win64\Server.exe --port 8888 --studentCount 1 --trickerCount 1 --gameTimeInSecond 600 --fileName video
+.\win64\Server.exe --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 600 --fileName video
pause
diff --git a/CAPI/shell/RunCpp.sh b/CAPI/shell/RunCpp.sh
index 911466a..8bb9f29 100644
--- a/CAPI/shell/RunCpp.sh
+++ b/CAPI/shell/RunCpp.sh
@@ -3,4 +3,5 @@
./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 0 -d -o &
./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 1 -d -o &
./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 2 -d -o &
-./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 3 -d -o &
\ No newline at end of file
+./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 3 -d -o &
+./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 4 -d -o &
\ No newline at end of file
diff --git a/CAPI/shell/RunPython.sh b/CAPI/shell/RunPython.sh
index ead4676..39e2268 100644
--- a/CAPI/shell/RunPython.sh
+++ b/CAPI/shell/RunPython.sh
@@ -3,4 +3,5 @@
python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 0 -d -o &
python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 1 -d -o &
python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 2 -d -o &
-python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 3 -d -o &
\ No newline at end of file
+python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 3 -d -o &
+python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 4 -d -o &
\ No newline at end of file
diff --git a/docs/使用文档.md b/docs/使用文档.md
index 100891f..a7b7354 100644
--- a/docs/使用文档.md
+++ b/docs/使用文档.md
@@ -90,6 +90,7 @@ start python .\CAPI\python\PyAPI\main.py -I 127.0.0.1 -P 8888 -p 0 -d -o -w
`-P`为服务器端口,一般为8888
`-p`为玩家id,一般学生为0~3,捣蛋鬼为4
+- 请注意学生序号要从0开始,如果学生数量为n,不应当出现id大于等于n的学生
`-d`为保存Debug日志文件(在`/logs/`下)
@@ -116,6 +117,7 @@ start python .\CAPI\python\PyAPI\main.py -I 127.0.0.1 -P 8888 -p 0 -d -o -w
`--characterID`为玩家id
- 学生取值为0,1,2,3,捣蛋鬼取值为4,characterID > 2023则是观战模式
+- 请注意学生序号要从0开始,如果学生数量为n,不应当出现id大于等于n的学生
- 应当使`RunGUIClient.cmd`与 `RunPython.cmd`(或`RunCpp.cmd`)中学生、捣蛋鬼数量之和符合`RunServer.cmd`的要求
- 如果不启动`RunPython.cmd`(或`RunCpp.cmd`),则`RunGUIClient.cmd`中学生、捣蛋鬼数量应当符合`RunServer.cmd`的要求
diff --git a/installer/Installer/MainWindow.xaml b/installer/Installer/MainWindow.xaml
index bf58112..c29b75d 100644
--- a/installer/Installer/MainWindow.xaml
+++ b/installer/Installer/MainWindow.xaml
@@ -40,7 +40,8 @@
-
+
+
diff --git a/installer/Installer/Model.cs b/installer/Installer/Model.cs
index b9a429a..e5ef7e2 100644
--- a/installer/Installer/Model.cs
+++ b/installer/Installer/Model.cs
@@ -35,6 +35,9 @@ using static System.Net.WebRequestMethods;
using File = System.IO.File;
using System.Linq;
using Installer;
+using starter.viewmodel.settings;
+using System.Security.Permissions;
+using System.Windows.Media;
namespace starter.viewmodel.settings
{
@@ -63,6 +66,7 @@ namespace starter.viewmodel.settings
UploadReady = false;
LoginFailed = false;
launchLanguage = LaunchLanguage.cpp;
+ usingOS = ReadUsingOS();
}
///
@@ -113,7 +117,7 @@ namespace starter.viewmodel.settings
///
public Status checkUpdate()
{
- UpdateInfo updateInfo = Tencent_cos_download.Check();
+ UpdateInfo updateInfo = Tencent_cos_download.Check(usingOS);
if (updateInfo.newFileCount == -1)
{
if (updateInfo.changedFileCount == -1)
@@ -143,19 +147,19 @@ namespace starter.viewmodel.settings
public bool RememberUser()
{
int result = 0;
- result |= Web.WriteUserEmail(Username);
- result |= Web.WriteUserPassword(Password);
+ result |= Web.WriteJson("email", Username);
+ result |= Web.WriteJson("password", Password);
return result == 0;
}
public bool RecallUser()
{
- Username = Web.ReadUserEmail();
+ Username = Web.ReadJson("email");
if (Username == null || Username.Equals(""))
{
Username = "";
return false;
}
- Password = Web.ReadUserPassword();
+ Password = Web.ReadJson("password");
if (Password == null || Username.Equals(""))
{
Password = "";
@@ -166,14 +170,21 @@ namespace starter.viewmodel.settings
public bool ForgetUser()
{
int result = 0;
- result |= Web.WriteUserEmail("");
- result |= Web.WriteUserPassword("");
+ result |= Web.WriteJson("email", "");
+ result |= Web.WriteJson("password", "");
return result == 0;
}
public bool Update()
{
- return Tencent_cos_download.Update();
+ try
+ {
+ return Tencent_cos_download.Update();
+ }
+ catch
+ {
+ return false;
+ }
}
public int Uninst()
{
@@ -214,6 +225,35 @@ namespace starter.viewmodel.settings
return -9;
return await web.UploadFiles(client, CodeRoute, Language, PlayerNum);
}
+ public bool WriteUsingOS()
+ {
+ string OS = "";
+ switch (usingOS)
+ {
+ case UsingOS.Win:
+ OS = "win";
+ break;
+ case UsingOS.Linux:
+ OS = "linux";
+ break;
+ case UsingOS.OSX:
+ OS = "osx";
+ break;
+ }
+ return Web.WriteJson("OS", OS) == 0;
+ }
+ public UsingOS ReadUsingOS()
+ {
+ string OS = Web.ReadJson("OS");
+ if (OS == null)
+ return UsingOS.Win;
+ else if (OS.Equals("linux"))
+ return UsingOS.Linux;
+ else if (OS.Equals("osx"))
+ return UsingOS.OSX;
+ else
+ return UsingOS.Win;
+ }
///
/// Route of files
///
@@ -306,6 +346,11 @@ namespace starter.viewmodel.settings
{
get; set;
}
+ public enum UsingOS { Win, Linux, OSX };
+ public UsingOS usingOS
+ {
+ get; set;
+ }
}
}
namespace Downloader
@@ -494,6 +539,10 @@ namespace Downloader
{
throw serverEx;
}
+ catch
+ {
+ MessageBox.Show($"下载{download_dir}时出现未知问题,请反馈");
+ }
}
public static void GetNewHash()
@@ -533,7 +582,16 @@ namespace Downloader
}
}
- public static UpdateInfo Check()
+ public static bool IsUserFile(string filename)
+ {
+ if (filename.Substring(filename.Length - 3, 3).Equals(".sh") || filename.Substring(filename.Length - 4, 4).Equals(".cmd"))
+ return true;
+ if (filename.Equals("AI.cpp") || filename.Equals("AI.py"))
+ return true;
+ return false;
+ }
+
+ public static UpdateInfo Check(SettingsModel.UsingOS OS)
{
string json, MD5, jsonName;
int newFile = 0, updateFile = 0;
@@ -577,27 +635,43 @@ namespace Downloader
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
Dictionary jsonDict = JsonConvert.DeserializeObject>(json);
+ string updatingFolder = "";
+ switch (OS)
+ {
+ case SettingsModel.UsingOS.Win:
+ updatingFolder = "THUAI6/win";
+ break;
+ case SettingsModel.UsingOS.Linux:
+ updatingFolder = "THUAI6/lin";
+ break;
+ case SettingsModel.UsingOS.OSX:
+ updatingFolder = "THUAI6/osx";
+ break;
+ }
foreach (KeyValuePair pair in jsonDict)
{
- MD5 = GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key));
- if (MD5.Length == 0) // 文档不存在
- newFileName.Add(pair.Key);
- else if (MD5.Equals("conflict"))
+ if (pair.Key.Length > 10 && (pair.Key.Substring(0, 10).Equals(updatingFolder)) || pair.Key.Substring(pair.Key.Length - 4, 4).Equals(".pdf"))
{
- if (pair.Key.Equals("THUAI6/win/CAPI/cpp/.vs/CAPI/v17/Browse.VC.db"))
+ MD5 = GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key.TrimStart(new char[] { '.', '/' })));
+ if (MD5.Length == 0) // 文档不存在
+ newFileName.Add(pair.Key);
+ else if (MD5.Equals("conflict"))
{
- MessageBox.Show($"visual studio未关闭:\n" +
- $"对于visual studio 2022,可以更新,更新会覆盖visual studio中已经打开的选手包;\n" +
- $"若使用其他版本的visual studio是继续更新出现问题,请汇报;\n" +
- $"若您自行修改了选手包,请注意备份;\n" +
- $"若关闭visual studio后仍弹出,请汇报。\n\n",
- "visual studio未关闭", MessageBoxButton.OK, MessageBoxImage.Information);
+ if (pair.Key.Equals("THUAI6/win/CAPI/cpp/.vs/CAPI/v17/Browse.VC.db"))
+ {
+ MessageBox.Show($"visual studio未关闭:\n" +
+ $"对于visual studio 2022,可以更新,更新会覆盖visual studio中已经打开的选手包;\n" +
+ $"若使用其他版本的visual studio是继续更新出现问题,请汇报;\n" +
+ $"若您自行修改了选手包,请注意备份;\n" +
+ $"若关闭visual studio后仍弹出,请汇报。\n\n",
+ "visual studio未关闭", MessageBoxButton.OK, MessageBoxImage.Information);
+ }
+ else
+ MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
}
- else
- MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
+ else if (!MD5.Equals(pair.Value) && !IsUserFile(System.IO.Path.GetFileName(pair.Key))) // MD5不匹配
+ updateFileName.Add(pair.Key);
}
- else if (MD5 != pair.Value && System.IO.Path.GetFileName(pair.Key) != "AI.cpp" && System.IO.Path.GetFileName(pair.Key) != "AI.py") // MD5不匹配
- updateFileName.Add(pair.Key);
}
newFile = newFileName.Count;
@@ -648,8 +722,6 @@ namespace Downloader
Download();
if (updateFailed.Count == 0)
return true;
- else
- Check();
}
return false;
}
@@ -667,7 +739,7 @@ namespace Downloader
foreach (string filename in newFileName)
{
//Console.WriteLine(newFile + 1 + "/" + totalnew + ":开始下载" + filename);
- Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename);
+ Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
//Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
newFile++;
}
@@ -677,12 +749,23 @@ namespace Downloader
try
{
File.Delete(System.IO.Path.Combine(@Data.FilePath, filename));
- Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename);
+ Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
}
catch (System.IO.IOException)
{
updateFailed = updateFailed.Append(filename).ToList();
}
+ catch
+ {
+ if (filename.Substring(filename.Length - 4, 4).Equals(".pdf"))
+ {
+ MessageBox.Show($"由于曾经发生过的访问冲突,下载器无法更新{filename}\n"
+ + $"请手动删除{filename},然后再试一次。");
+ }
+ else
+ MessageBox.Show($"更新{filename}时遇到未知问题,请反馈");
+ updateFailed = updateFailed.Append(filename).ToList();
+ }
//Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
updateFile++;
}
@@ -692,19 +775,20 @@ namespace Downloader
catch (CosClientException clientEx)
{
// 请求失败
- MessageBox.Show("网络错误");
+ MessageBox.Show("连接错误:" + clientEx.ToString());
Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
return;
}
catch (CosServerException serverEx)
{
// 请求失败
- MessageBox.Show("网络错误");
+ MessageBox.Show("连接错误:" + serverEx.ToString());
Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
return;
}
catch (Exception)
{
+ MessageBox.Show("未知错误且无法定位到出错文件,请反馈");
throw;
}
}
@@ -840,7 +924,7 @@ namespace Downloader
using StreamWriter sw = new StreamWriter(fs2);
fs2.SetLength(0);
sw.Write(JsonConvert.SerializeObject(dict));
- Check();
+ Check(SettingsModel.UsingOS.Win);
Download();
if (File.Exists(Data.FilePath + "/THUAI6/AI.cpp"))
{
@@ -1126,7 +1210,7 @@ namespace Downloader
{
if (Data.FilePath != null && Directory.Exists(Data.FilePath))
{
- Check();
+ Check(SettingsModel.UsingOS.Win);
break;
}
else
@@ -1201,7 +1285,7 @@ namespace Downloader
string keyHead = "Installer/";
Tencent_cos_download downloader = new Tencent_cos_download();
string hashName = "installerHash.json";
- string dir = Directory.GetCurrentDirectory();
+ string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
int result = 0;
try
{
@@ -1243,7 +1327,7 @@ namespace Downloader
else
{
result = 1;
- awaitUpdate.Append(pair.Key);
+ awaitUpdate = awaitUpdate.Append(pair.Key).ToList();
}
}
}
@@ -1255,6 +1339,37 @@ namespace Downloader
File.WriteAllText(@System.IO.Path.Combine(dir, "updateList.json"), Contentjson);
return result;
}
+
+ static public bool SelfUpdateDismissed()
+ {
+ string json;
+ string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
+ if (!File.Exists(System.IO.Path.Combine(dir, "updateList.json")))
+ return false;
+ using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, "updateList.json")))
+ json = r.ReadToEnd();
+ json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
+ List jsonList;
+ if (json != null)
+ jsonList = JsonConvert.DeserializeObject>(json);
+ else
+ return false;
+ if (jsonList != null && jsonList.Contains("Dismiss"))
+ {
+ listJsonClear(System.IO.Path.Combine(dir, "updateList.json"));
+ return true;
+ }
+ return false;
+ }
+
+ static private void listJsonClear(string directory)
+ {
+ List list = new List();
+ list.Add("None");
+ StreamWriter sw = new StreamWriter(directory, false);
+ sw.WriteLine(JsonConvert.SerializeObject(list));
+ sw.Close();
+ }
}
}
}
@@ -1499,7 +1614,7 @@ namespace WebConnect
}
}
- public static int WriteUserEmail(string email)
+ public static int WriteJson(string key, string data)
{
try
{
@@ -1513,13 +1628,13 @@ namespace WebConnect
}
Dictionary dict = new Dictionary();
dict = JsonConvert.DeserializeObject>(json);
- if (!dict.ContainsKey("email"))
+ if (!dict.ContainsKey(key))
{
- dict.Add("email", email);
+ dict.Add(key, data);
}
else
{
- dict["email"] = email;
+ dict[key] = data;
}
sr.Close();
fs.Close();
@@ -1536,44 +1651,7 @@ namespace WebConnect
}
}
- public static int WriteUserPassword(string password)
- {
- try
- {
- string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
- FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite);
- StreamReader sr = new StreamReader(fs);
- string json = sr.ReadToEnd();
- if (json == null || json == "")
- {
- json += @"{""THUAI6""" + ":" + @"""2023""}";
- }
- Dictionary dict = new Dictionary();
- dict = JsonConvert.DeserializeObject>(json);
- if (!dict.ContainsKey("password"))
- {
- dict.Add("password", password);
- }
- else
- {
- dict["password"] = password;
- }
- sr.Close();
- fs.Close();
- FileStream fs2 = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite);
- StreamWriter sw = new StreamWriter(fs2);
- sw.WriteLine(JsonConvert.SerializeObject(dict));
- sw.Close();
- fs2.Close();
- return 0;//成功
- }
- catch
- {
- return -1;//失败,THUAI6.json 文件不存在或者已被占用
- }
- }
-
- public static string ReadUserPassword()
+ public static string ReadJson(string key)
{
try
{
@@ -1587,7 +1665,9 @@ namespace WebConnect
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = JsonConvert.DeserializeObject>(json);
- return dict["password"];
+ fs.Close();
+ sr.Close();
+ return dict[key];
}
catch
@@ -1596,27 +1676,6 @@ namespace WebConnect
}
}
- public static string ReadUserEmail()
- {
- try
- {
- string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
- FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read);
- StreamReader sr = new StreamReader(fs);
- string json = sr.ReadToEnd();
- Dictionary dict = new Dictionary();
- if (json == null || json == "")
- {
- json += @"{""THUAI6""" + ":" + @"""2023""}";
- }
- dict = JsonConvert.DeserializeObject>(json);
- return dict["email"];
- }
- catch
- {
- return null;
- }
- }
public bool ReadToken() // 读取token
{
try
diff --git a/installer/Installer/ViewModel.cs b/installer/Installer/ViewModel.cs
index 472b63f..ca84add 100644
--- a/installer/Installer/ViewModel.cs
+++ b/installer/Installer/ViewModel.cs
@@ -33,22 +33,23 @@ namespace starter.viewmodel.settings
public SettingsViewModel()
{
- Program.Tencent_cos_download.UpdateHash();
+ //Program.Tencent_cos_download.UpdateHash();
Status = SettingsModel.Status.working;
-
- switch (Program.Tencent_cos_download.CheckSelfVersion())
+ string CurrentDirectory = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
+ //MessageBox.Show("更新器工作正常");
+ if (!Program.Tencent_cos_download.SelfUpdateDismissed())
{
- case 1:
- if (MessageBoxResult.Yes == MessageBox.Show("下载器需要更新,是否现在更新", "需要更新", MessageBoxButton.YesNo))
- {
- Process.Start(Path.Combine(Directory.GetCurrentDirectory(), "InstallerUpdater.exe"));
+ switch (Program.Tencent_cos_download.CheckSelfVersion())
+ {
+ case 1:
+ Process.Start(System.IO.Path.Combine(CurrentDirectory, "InstallerUpdater.exe"));
Environment.Exit(0);
- }
- break;
- case -1:
- MessageBox.Show("下载器更新检查出错,将继续启动现有下载器");
- break;
+ break;
+ case -1:
+ MessageBox.Show("下载器更新检查出错,将继续启动现有下载器");
+ break;
+ }
}
//实例化BackgroundWorker
@@ -78,6 +79,7 @@ namespace starter.viewmodel.settings
else
RememberMe = false;
this.RaisePropertyChanged("RememberMe");
+ this.RaisePropertyChanged("SwitchOSBtnCont");
//在启动时立刻检查更新,确保选手启动最新版选手包
//若有更新,将启动键改为更新键;
//相应地,使用login界面启动;
@@ -139,6 +141,7 @@ namespace starter.viewmodel.settings
}
MessageBox.Show($"以下文件因被占用而未能成功更新:\n{updateFailList}请关闭它们,并再试一次");
Program.ResetUpdateFailedInfo();
+ obj.checkUpdate();
Status = SettingsModel.Status.successful;
this.RaisePropertyChanged("UpdateBtnCont");
this.RaisePropertyChanged("UpdateInfo");
@@ -303,6 +306,23 @@ namespace starter.viewmodel.settings
return ans;
}
}
+ public string SwitchOSBtnCont
+ {
+ get
+ {
+ switch (obj.usingOS)
+ {
+ case SettingsModel.UsingOS.Win:
+ return "当前系统:Windows";
+ case SettingsModel.UsingOS.Linux:
+ return "当前系统:Linux";
+ case SettingsModel.UsingOS.OSX:
+ return "当前系统:macOS";
+ default:
+ return "当前系统:无效的名称";
+ }
+ }
+ }
public int PlayerNum
{
get
@@ -1030,6 +1050,40 @@ namespace starter.viewmodel.settings
return clickReadCommand;
}
}
+ private BaseCommand clickSwitchOSCommand;
+ public BaseCommand ClickSwitchOSCommand
+ {
+ get
+ {
+ if (clickSwitchOSCommand == null)
+ {
+ clickSwitchOSCommand = new BaseCommand(new Action