using COSXML.Auth;
using COSXML.CosException;
using COSXML.Model.Object;
using COSXML;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System;
using COSXML.Model.Bucket;
using System.Runtime.InteropServices;
using System.Text.Json.Nodes;
using System.Net.Http.Json;
using System.Text.Json;
using System.Xml.Schema;
using static Downloader.Program;
using System.Threading.Tasks;
using System.Net.Http;
using System.Windows;
using System.Windows.Shapes;
using System.Collections.Concurrent;
//using System.Windows.Forms;
using System.Threading;
using MessageBox = System.Windows.MessageBox;
using Downloader;
using COSXML.Transfer;
using WebConnect;
using System.IO.Compression;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.GZip;
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
{
///
/// Settings Window Model
///
public class SettingsModel
{
///
/// downloader function
///
private Data configData = new Data("");
private Tencent_cos_download cloud = new Tencent_cos_download();
private HttpClient client = new HttpClient();
private WebConnect.Web web = new WebConnect.Web();
public SettingsModel()
{
Route = Data.FilePath;
Username = "";
Password = "";
updates = "";
CodeRoute = "";
PlayerNum = "nSelect";
UploadReady = false;
LoginFailed = false;
launchLanguage = LaunchLanguage.cpp;
usingOS = ReadUsingOS();
}
///
/// save settings
///
public bool install()
{
if (Tencent_cos_download.CheckAlreadyDownload())
{
MessageBoxResult repeatOption = MessageBox.Show($"文件已存在于{Downloader.Program.Data.FilePath},是否移动到新位置?", "重复安装", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
// ask if abort install, with warning sign, defalut move instead of abort;
if (repeatOption == MessageBoxResult.No)
{
Route = Data.FilePath;
return false;
}
else
{
Downloader.Program.Tencent_cos_download.MoveProgram(Route);
return true;
}
}
else
{
Data.ResetFilepath(Route);
Tencent_cos_download.DownloadAll();
return true;
}
}
public int move()
{
int state = Tencent_cos_download.MoveProgram(Route);
if (state != 0)
Route = Data.FilePath;
return state;
}
///
///check for update
///
static bool ProfileAvailable
{
get; set;
}
///
/// 检查更新
///
///
public Status checkUpdate()
{
UpdateInfo updateInfo = Tencent_cos_download.Check(usingOS);
if (updateInfo.newFileCount == -1)
{
if (updateInfo.changedFileCount == -1)
{
return Status.error;
}
else
{
return Status.disconnected;
}
}
else
{
if (updateInfo.changedFileCount != 0 || updateInfo.newFileCount != 0)
{
Updates = $"{updateInfo.newFileCount}个新文件,{updateInfo.changedFileCount}个文件变化";
}
return Status.menu;
}
}
public async Task Login()
{
return await web.LoginToEEsast(client, Username, Password);
}
public bool RememberUser()
{
int result = 0;
result |= Web.WriteJson("email", Username);
result |= Web.WriteJson("password", Password);
return result == 0;
}
public bool RecallUser()
{
var username = Web.ReadJson("email");
if (username == null || username.Equals(""))
{
Username = "";
return false;
}
Username = username;
var password = Web.ReadJson("password");
if (password == null || password.Equals(""))
{
Password = "";
return false;
}
Password = password;
return true;
}
public bool ForgetUser()
{
int result = 0;
result |= Web.WriteJson("email", "");
result |= Web.WriteJson("password", "");
return result == 0;
}
public bool Update()
{
try
{
return Tencent_cos_download.Update();
}
catch
{
return false;
}
}
public int Uninst()
{
return Tencent_cos_download.DeleteAll();
}
public bool Launch()
{
if (Tencent_cos_download.CheckAlreadyDownload())
{
//Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
switch (RunProgram.RunInfo.mode)
{
case RunProgram.RunMode.ServerOnly:
RunProgram.StartServer(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
break;
case RunProgram.RunMode.ServerForDebugOnly:
RunProgram.StartServerForDebug(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
break;
case RunProgram.RunMode.GUIAttendGameOnly:
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.characterID,
false, RunProgram.RunInfo.occupation, RunProgram.RunInfo.type);
break;
case RunProgram.RunMode.GUIVisit:
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, 0, true, 1, 1);
break;
case RunProgram.RunMode.GUIAndAICpp:
RunProgram.StartServerForDebug(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunCpp(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.characterID,
false, RunProgram.RunInfo.occupation, RunProgram.RunInfo.type);
break;
case RunProgram.RunMode.GUIAndAIPython:
RunProgram.StartServerForDebug(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunPython(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.characterID,
false, RunProgram.RunInfo.occupation, RunProgram.RunInfo.type);
break;
case RunProgram.RunMode.ServerAndCpp:
RunProgram.StartServer(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunCpp(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
break;
case RunProgram.RunMode.ServerAndPython:
RunProgram.StartServer(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunPython(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
break;
case RunProgram.RunMode.ServerAndCppVisit:
RunProgram.StartServer(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunCpp(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.characterID, true, 0, 1);
break;
case RunProgram.RunMode.ServerAndPythonVisit:
RunProgram.StartServer(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunPython(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.characterID, true, 0, 1);
break;
case RunProgram.RunMode.ServerDebugAndCppVisit:
RunProgram.StartServerForDebug(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunCpp(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.characterID, true, 0, 1);
break;
case RunProgram.RunMode.ServerDebugAndPythonVisit:
RunProgram.StartServerForDebug(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.gameTimeSec, RunProgram.RunInfo.playbackFileName);
Task.Delay(100);
RunProgram.RunPython(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.studentCount,
RunProgram.RunInfo.trickerCount, RunProgram.RunInfo.saveDebugLog, RunProgram.RunInfo.showDebugLog,
RunProgram.RunInfo.warningOnly, RunProgram.RunInfo.playerId, RunProgram.RunInfo.filePath);
RunProgram.RunInfo.playerId = null;
RunProgram.RunInfo.filePath = null;
RunProgram.RunGUIClient(RunProgram.RunInfo.IP, RunProgram.RunInfo.port, RunProgram.RunInfo.characterID, true, 0, 1);
break;
}
return true;
}
else
{
MessageBox.Show($"文件还不存在,请安装主体文件", "文件不存在", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
return false;
}
}
public async Task Upload()
{
switch (CodeRoute.Substring(CodeRoute.LastIndexOf('.') + 1))
{
case "cpp":
case "h":
Language = "cpp";
break;
case "py":
Language = "python";
break;
default:
return -8;
}
if (PlayerNum.Equals("nSelect"))
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()
{
return Web.ReadJson("OS") switch
{
"linux" => UsingOS.Linux,
"osx" => UsingOS.OSX,
_ => UsingOS.Win,
};
}
///
/// Route of files
///
public string Route
{
get; set;
}
public string Username
{
get; set;
}
public string Password
{
get; set;
}
public string CodeRoute
{
get; set;
}
public string? Language
{
get; set;
}
public string PlayerNum
{
get; set;
}
///
/// 关于更新的屏幕显示信息
///
private string updates;
public string Updates
{
get
{
return updates;
}
set
{
updates = value;
}
}
///
/// 关于介绍的屏幕显示信息
///
public enum Status { newUser, menu, move, working, initializing, disconnected, error, successful, login, web, launch };
public Status status
{
get; set;
}
public bool Working
{
get; set;
}
///
/// if an update is planned
///
public bool UpdatePlanned
{
get
{
return Program.UpdatePlanned;
}
}
public bool CombatCompleted
{
get
{
return false;
}
}
public bool LoginFailed
{
get; set;
}
public bool UploadReady
{
get; set;
}
public bool RememberMe
{
get; set;
}
public enum LaunchLanguage { cpp, python };
public LaunchLanguage launchLanguage
{
get; set;
}
public enum UsingOS { Win, Linux, OSX };
public UsingOS usingOS
{
get; set;
}
}
}
namespace Downloader
{
class UserInfo
{
static public string _id = "";
static public string email = "";
}
class Program
{
static ConcurrentQueue newFileName = new ConcurrentQueue();
//static List newFileName = new List(); // 新文件名
static ConcurrentQueue updateFileName = new ConcurrentQueue(); // 更新文件名
static List updateFailed = new List(); //更新失败的文件名
static public List UpdateFailed
{
get { return updateFailed; }
}
static public void ResetUpdateFailedInfo()
{
updateFailed.Clear();
}
public static string ProgramName = "THUAI6"; // 要运行或下载的程序名称
public static string playerFolder = "player"; // 选手代码保存文件夹路径
public static string startName = "maintest.exe"; // 启动的程序名
public struct UpdateInfo // 更新信息,包括新版本版本号、更改文件数和新文件数
{
public string status;
public int changedFileCount;
public int newFileCount;
}
public static bool UpdatePlanned
{
get; set;
}
static int filenum = 0; // 总文件个数
public class Data
{
public static string path = ""; // 标记路径记录文件THUAI6.json的路径
public static string FilePath = ""; // 最后一级为THUAI6文件夹所在目录
public static string dataPath = ""; // C盘的文档文件夹
public Data(string path)
{
dataPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//dataPath = new DirectoryInfo(".").FullName;
Data.path = System.IO.Path.Combine(dataPath, "THUAI6.json");
if (File.Exists(Data.path))
{
Dictionary? dict;
using (StreamReader r = new StreamReader(Data.path))
{
string json = r.ReadToEnd();
if (json == null || json == "")
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.TryDeserializeJson>(json);
if (dict != null && dict.ContainsKey("installpath"))
{
FilePath = dict["installpath"].Replace('\\', '/');
} //读取安装路径
}
dict?.TryAdd("installpath", @path);
using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
using StreamWriter sw = new StreamWriter(fs);
sw.Write(JsonConvert.SerializeObject(dict));
sw.Flush();
}
else
{
FilePath = System.IO.Path.GetDirectoryName(@path)
?? throw new Exception("Failed to get the path of the file");
//将dat文件写入程序运行路径
string json;
Dictionary? dict;
using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
using (StreamReader r = new StreamReader(fs))
{
json = r.ReadToEnd();
if (json == null || json == "")
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.TryDeserializeJson>(json);
dict?.Add("installpath", path);
}
using FileStream fs2 = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
using StreamWriter sw = new StreamWriter(fs2);
sw.Write(JsonConvert.SerializeObject(dict));
sw.Flush();
}
}
public static void ResetFilepath(string newPath)
{
string json;
Dictionary? dict;
FilePath = newPath.Replace('\\', '/');
path = System.IO.Path.Combine(dataPath, "THUAI6.json");
using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
using (StreamReader r = new StreamReader(fs))
{
json = r.ReadToEnd();
if (json == null || json == "")
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.TryDeserializeJson>(json);
if (dict != null && dict.ContainsKey("installpath"))
{
dict["installpath"] = newPath;
}
else
{
dict?.Add("installpath", newPath);
}
if (dict == null || !dict.ContainsKey("download"))
{
dict?.Add("download", "true");
}
else
{
dict["download"] = "true";
}
}
using FileStream fs2 = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
using StreamWriter sw = new StreamWriter(fs2);
fs2.SetLength(0);
sw.Write(JsonConvert.SerializeObject(dict));
sw.Flush();
}
}
public class Tencent_cos_download
{
public void download(string download_dir, string key)
{
// download_dir标记根文件夹路径,key为相对根文件夹的路径(不带./)
// 初始化CosXmlConfig(提供配置SDK接口)
string appid = "1314234950"; // 设置腾讯云账户的账户标识(APPID)
string region = "ap-beijing"; // 设置一个默认的存储桶地域
CosXmlConfig config = new CosXmlConfig.Builder()
.IsHttps(true) // 设置默认 HTTPS 请求
.SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
.SetRegion(region) // 设置一个默认的存储桶地域
.SetDebugLog(true) // 显示日志
.Build(); // 创建 CosXmlConfig 对象
// 永久密钥访问凭证
string secretId = "***"; //"云 API 密钥 SecretId";
string secretKey = "***"; //"云 API 密钥 SecretKey";
long durationSecond = 1000; // 每次请求签名有效时长,单位为秒
QCloudCredentialProvider cosCredentialProvider = new DefaultQCloudCredentialProvider(
secretId, secretKey, durationSecond
);
// 初始化 CosXmlServer
CosXmlServer cosXml = new CosXmlServer(config, cosCredentialProvider);
// 创建存储桶
try
{
string bucket = "thuai6-1314234950"; // 格式:BucketName-APPID
string localDir = System.IO.Path.GetDirectoryName(download_dir) // 本地文件夹
?? throw new Exception("本地文件夹路径获取失败");
string localFileName = System.IO.Path.GetFileName(download_dir); // 指定本地保存的文件名
GetObjectRequest request = new GetObjectRequest(bucket, key, localDir, localFileName);
Dictionary test = request.GetRequestHeaders();
request.SetCosProgressCallback(delegate (long completed, long total)
{
//Console.WriteLine(String.Format("progress = {0:##.##}%", completed * 100.0 / total));
});
// 执行请求
GetObjectResult result = cosXml.GetObject(request);
// 请求成功
}
catch (CosClientException clientEx)
{
throw clientEx;
}
catch (CosServerException serverEx)
{
throw serverEx;
}
catch
{
MessageBox.Show($"下载{download_dir}时出现未知问题,请反馈");
}
}
public static void GetNewHash()
{
Tencent_cos_download Downloader = new Tencent_cos_download();
Downloader.download(System.IO.Path.Combine(Data.FilePath, "hash.json"), "hash.json");
}
public static string GetFileMd5Hash(string strFileFullPath)
{
FileStream? fst = null;
try
{
fst = new FileStream(strFileFullPath, FileMode.Open, FileAccess.Read);
byte[] data = MD5.Create().ComputeHash(fst);
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
fst.Close();
return sBuilder.ToString().ToLower();
}
catch (Exception)
{
if (fst != null)
fst.Close();
if (File.Exists(strFileFullPath))
return "conflict";
return "";
}
finally
{
}
}
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;
newFileName.Clear();
updateFileName.Clear();
jsonName = "hash.json";
UpdateInfo updateInfo;
Tencent_cos_download Downloader = new Tencent_cos_download();
try
{
// 如果json存在就删了重新下
if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
{
File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
}
else
{
Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
}
}
catch (CosClientException clientEx)
{
// 请求失败
updateInfo.status = "ClientEx: " + clientEx.ToString();
updateInfo.newFileCount = -1;
updateInfo.changedFileCount = 0;
return updateInfo;
}
catch (CosServerException serverEx)
{
// 请求失败
updateInfo.status = "ServerEx: " + serverEx.ToString();
updateInfo.newFileCount = -1;
updateInfo.changedFileCount = 0;
return updateInfo;
}
using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
var jsonDict = Utils.DeserializeJson1>(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)
{
if (pair.Key.Length > 10 && (pair.Key.Substring(0, 10).Equals(updatingFolder)) || pair.Key.Substring(pair.Key.Length - 4, 4).Equals(".pdf"))
{
MD5 = GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key.TrimStart(new char[] { '.', '/' })));
if (MD5.Length == 0) // 文档不存在
newFileName.Enqueue(pair.Key);
else if (MD5.Equals("conflict"))
{
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 if (!MD5.Equals(pair.Value) && !IsUserFile(System.IO.Path.GetFileName(pair.Key))) // MD5不匹配
updateFileName.Enqueue(pair.Key);
}
}
newFile = newFileName.Count;
updateFile = updateFileName.Count;
filenum = newFile + updateFile;
//Console.WriteLine("----------------------" + Environment.NewLine);
if (newFile + updateFile == 0)
{
updateInfo.status = "latest";
updateInfo.newFileCount = 0;
updateInfo.changedFileCount = 0;
newFileName.Clear();
updateFileName.Clear();
}
else
{
updateInfo.status = "old";
//TODO:获取版本号
updateInfo.newFileCount = newFile;
/*
foreach (string filename in newFileName)
{
Console.WriteLine(filename);
}
*/
updateInfo.changedFileCount = updateFile;
/*
foreach (string filename in updateFileName)
{
Console.WriteLine(filename);
}
Console.Write(Environment.NewLine + "是否下载新文件? y/n:");
if (Console.Read() != 'y')
Console.WriteLine("下载取消!");
else
Download();
*/
UpdatePlanned = true;
}
return updateInfo;
}
public static bool Update()
{
if (UpdatePlanned)
{
Download();
if (updateFailed.Count == 0)
return true;
}
return false;
}
private static void Download()
{
Tencent_cos_download Downloader = new Tencent_cos_download();
int newFile = 0, updateFile = 0;
int totalnew = newFileName.Count, totalupdate = updateFileName.Count;
filenum = totalnew + totalupdate;
updateFailed.Clear();
if (newFileName.Count > 0 || updateFileName.Count > 0)
{
try
{
int cnt = newFileName.Count;
if (cnt <= 20)
{
while (newFileName.TryDequeue(out var filename))
{
Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
//Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
Interlocked.Increment(ref newFile);
}
}
else
{
const int nthread = 8;
var thrds = new List();
for (int i = 0; i < nthread; i++)
{
var thrd = new Thread(() =>
{
while (newFileName.TryDequeue(out var filename))
{
Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
//Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
Interlocked.Increment(ref newFile);
}
});
thrd.Start();
thrds.Add(thrd);
}
foreach (var thrd in thrds)
{
thrd.Join();
}
}
// 读取 Interlocked.CompareExchange(ref newFile, 0, 0);
int upcnt = updateFileName.Count;
if (upcnt <= 20)
{
while (updateFileName.TryDequeue(out var filename))
{
try
{
File.Delete(System.IO.Path.Combine(@Data.FilePath, 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();
}
Interlocked.Increment(ref newFile);
}
}
else
{
const int nthread = 8;
var thrds = new List();
for (int i = 0; i < nthread; i++)
{
var thrd = new Thread(() =>
{
while (updateFileName.TryDequeue(out var filename))
{
try
{
File.Delete(System.IO.Path.Combine(@Data.FilePath, 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();
}
Interlocked.Increment(ref newFile);
}
});
thrd.Start();
thrds.Add(thrd);
}
foreach (var thrd in thrds)
{
thrd.Join();
}
}
if (updateFailed.Count == 0)
UpdatePlanned = false;
}
catch (CosClientException clientEx)
{
// 请求失败
MessageBox.Show("连接错误:" + clientEx.ToString());
Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
return;
}
catch (CosServerException serverEx)
{
// 请求失败
MessageBox.Show("连接错误:" + serverEx.ToString());
Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
return;
}
catch (Exception)
{
MessageBox.Show("未知错误且无法定位到出错文件,请反馈");
throw;
}
}
else
Console.WriteLine("当前平台已是最新版本!" + Environment.NewLine);
newFileName.Clear();
updateFileName.Clear();
}
public static bool CheckAlreadyDownload() // 检查是否已经下载
{
string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
if (!File.Exists(existpath)) // 文件不存在
{
using FileStream fs = new FileStream(existpath, FileMode.Create, FileAccess.ReadWrite);
return false;
}
else // 文件存在
{
using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.Read);
using StreamReader sr = new StreamReader(fs);
string json = sr.ReadToEnd();
if (json == null || json == "")
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
var dict = Utils.TryDeserializeJson>(json);
if (dict == null || !dict.ContainsKey("download") || "false" == dict["download"])
{
return false;
}
else if (dict["download"] == "true")
{
return true;
}
else
{
return false;
}
}
}
public static void DownloadAll() // 下载全部文件
{
string jsonName = "hash.json";
string json;
Tencent_cos_download Downloader = new Tencent_cos_download();
try
{
// 如果json存在就删了重新下
if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
{
File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
}
else
{
Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
}
}
catch (CosClientException clientEx)
{
// 请求失败
Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
return;
}
catch (CosServerException serverEx)
{
// 请求失败
Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
return;
}
using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
// var jsonDict = Utils.DeserializeJson>(json);
newFileName.Clear();
updateFileName.Clear();
newFileName.Enqueue("THUAI6.tar.gz");
Download();
Stream? inStream = null;
Stream? gzipStream = null;
TarArchive? tarArchive = null;
try
{
using (inStream = File.OpenRead(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz")))
{
using (gzipStream = new GZipInputStream(inStream))
{
tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
tarArchive.ExtractContents(Data.FilePath);
tarArchive.Close();
}
}
}
catch
{
//出错
}
finally
{
if (null != tarArchive) tarArchive.Close();
if (null != gzipStream) gzipStream.Close();
if (null != inStream) inStream.Close();
}
FileInfo fileInfo = new FileInfo(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz"));
fileInfo.Delete();
string json2;
Dictionary? dict;
string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
using (StreamReader r = new StreamReader(fs))
{
json2 = r.ReadToEnd();
if (json2 == null || json2 == "")
{
json2 += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.TryDeserializeJson>(json2);
if (dict == null || !dict.ContainsKey("download"))
{
dict?.Add("download", "true");
}
else
{
dict["download"] = "true";
}
}
using FileStream fs2 = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
using StreamWriter sw = new StreamWriter(fs2);
fs2.SetLength(0);
sw.Write(JsonConvert.SerializeObject(dict));
Check(SettingsModel.UsingOS.Win);
Download();
if (File.Exists(Data.FilePath + "/THUAI6/AI.cpp"))
{
FileInfo userCpp = new FileInfo((Data.FilePath + "/THUAI6/AI.cpp").Replace("/", "\\"));
userCpp.MoveTo(Data.FilePath + "/THUAI6/win/CAPI/cpp/API/src/AI.cpp", true);
}
if (File.Exists(Data.FilePath + "/THUAI6/AI.py"))
{
FileInfo userCpp = new FileInfo((Data.FilePath + "/THUAI6/AI.py").Replace("/", "\\"));
userCpp.MoveTo(Data.FilePath + "/THUAI6/win/CAPI/python/PyAPI/AI.cpp", true);
}
}
public static void Change_all_hash(string topDir, Dictionary jsonDict) // 更改HASH
{
DirectoryInfo theFolder = new DirectoryInfo(@topDir);
bool ifexist = false;
// 遍历文件
foreach (FileInfo NextFile in theFolder.GetFiles())
{
string filepath = topDir + @"/" + NextFile.Name; // 文件路径
//Console.WriteLine(filepath);
foreach (KeyValuePair pair in jsonDict)
{
if (System.IO.Path.Equals(filepath, System.IO.Path.Combine(Data.FilePath, pair.Key).Replace('\\', '/')))
{
ifexist = true;
string MD5 = GetFileMd5Hash(filepath);
jsonDict[pair.Key] = MD5;
}
}
if (!ifexist && NextFile.Name != "hash.json")
{
string MD5 = GetFileMd5Hash(filepath);
string relapath = filepath.Replace(Data.FilePath + '/', string.Empty);
jsonDict.Add(relapath, MD5);
}
ifexist = false;
}
// 遍历文件夹
foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
{
if (System.IO.Path.Equals(NextFolder.FullName, System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder))))
{
foreach (FileInfo NextFile in NextFolder.GetFiles())
{
if (NextFile.Name == "AI.cpp" || NextFile.Name == "AI.py")
{
string MD5 = GetFileMd5Hash(NextFile.FullName);
string relapath = NextFile.FullName.Replace('\\', '/').Replace(Data.FilePath + '/', string.Empty);
jsonDict.Add(relapath, MD5);
}
}
continue; // 如果是选手文件夹就忽略
}
Change_all_hash(NextFolder.FullName.Replace('\\', '/'), jsonDict);
}
}
public static void UpdateHash()
{
while (true)
{
if (Directory.Exists(Data.FilePath))
{
string json;
if (!File.Exists(System.IO.Path.Combine(Data.FilePath, "hash.json")))
{
Console.WriteLine("hash.json文件丢失!即将重新下载该文件!");
GetNewHash();
}
using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, "hash.json")))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("/", @"\\");
Dictionary jsonDict = Utils.DeserializeJson1>(json);
Change_all_hash(Data.FilePath, jsonDict);
OverwriteHash(jsonDict);
break;
}
else
{
Console.WriteLine("读取路径失败!请重新输入文件路径:");
Data.ResetFilepath(Console.ReadLine() ?? "");
}
}
}
public static int DeleteAll()
{
DirectoryInfo di = new DirectoryInfo(Data.FilePath + "/THUAI6");
//DirectoryInfo player = new DirectoryInfo(System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder)));
FileInfo[] allfile = di.GetFiles();
try
{
foreach (FileInfo file in allfile)
{
//if(file.Name == "AI.cpp" || file.Name == "AI.py")
//{
// string filename = System.IO.Path.GetFileName(file.FullName);
// file.MoveTo(System.IO.Path.Combine(Data.FilePath, filename));
// continue;
//}
file.Delete();
}
FileInfo userFileCpp = new FileInfo(Data.FilePath + "/THUAI6/win/CAPI/cpp/API/src/AI.cpp");
FileInfo userFilePy = new FileInfo(Data.FilePath + "/THUAI6/win/CAPI/python/PyAPI/AI.py");
userFileCpp.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", System.IO.Path.GetFileName(userFileCpp.FullName)));
userFilePy.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", System.IO.Path.GetFileName(userFilePy.FullName)));
foreach (DirectoryInfo subdi in di.GetDirectories())
{
subdi.Delete(true);
}
FileInfo hashFile = new FileInfo(Data.FilePath + "/hash.json");
hashFile.Delete();
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("权限不足,无法删除!");
return -2;
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
return -3;
}
catch (IOException)
{
Console.WriteLine("文件已经打开,请关闭后再删除");
return -1;
}
string json2;
Dictionary? dict;
string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
using (StreamReader r = new StreamReader(fs))
{
json2 = r.ReadToEnd();
if (json2 == null || json2 == "")
{
json2 += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.TryDeserializeJson>(json2);
if (dict == null || !dict.ContainsKey("download"))
{
dict?.Add("download", "false");
}
else
{
dict["download"] = "false";
}
}
using FileStream fs2 = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
using StreamWriter sw = new StreamWriter(fs2);
fs2.SetLength(0);
sw.Write(JsonConvert.SerializeObject(dict));
sw.Close();
fs2.Close();
try
{
File.Delete(Data.path);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("权限不足,无法删除!");
return -2;
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
return -3;
}
catch (IOException)
{
Console.WriteLine("文件已经打开,请关闭后再删除");
return -1;
}
return 0;
}
public static void OverwriteHash(Dictionary jsonDict)
{
string Contentjson = JsonConvert.SerializeObject(jsonDict);
Contentjson = Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/");
File.WriteAllText(@System.IO.Path.Combine(Data.FilePath, "hash.json"), Contentjson);
}
public static int MoveProgram(string newPath)
{
DirectoryInfo newdi = new DirectoryInfo(newPath + "/THUAI6");
DirectoryInfo olddi = new DirectoryInfo(Data.FilePath + "/THUAI6");
try
{
if (!Directory.Exists(newPath + "/THUAI6"))
Directory.CreateDirectory(newPath + "/THUAI6");
foreach (DirectoryInfo direct in olddi.GetDirectories())
{
direct.MoveTo(System.IO.Path.Combine(newPath + "/THUAI6", direct.Name));
}
foreach (FileInfo file in olddi.GetFiles())
{
file.MoveTo(System.IO.Path.Combine(newPath + "/THUAI6", file.Name));
}
olddi.Delete();
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("原路径未找到!请检查文件是否损坏");
if (newdi.GetDirectories().Length != 0)
{
foreach (DirectoryInfo newdirect in newdi.GetDirectories())
{
newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", newdirect.Name));
}
}
if (newdi.GetFiles().Length != 0)
{
foreach (FileInfo file in newdi.GetFiles())
{
file.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", file.Name));
}
}
Console.WriteLine("移动失败!");
if (newdi.Exists)
newdi.Delete();
return -2;
}
catch (IOException)
{
Console.WriteLine("文件已打开或者目标路径下有同名文件!");
if (newdi.GetDirectories().Length != 0)
{
foreach (DirectoryInfo newdirect in newdi.GetDirectories())
{
newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", newdirect.Name));
}
}
if (newdi.GetFiles().Length != 0)
{
foreach (FileInfo file in newdi.GetFiles())
{
file.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", file.Name));
}
}
if (newdi.Exists)
newdi.Delete();
Console.WriteLine("移动失败!");
return -1;
}
FileInfo hashFile = new FileInfo(Data.FilePath + "/hash.json");
hashFile.MoveTo(newPath + "/hash.json");
Data.ResetFilepath(newPath);
Console.WriteLine("更改路径成功!");
return 0;
}
public static async Task main(string[] args)
{
var client = new HttpClient();
var web = new WebConnect.Web();
Data date = new Data("");
while (true)
{
Console.WriteLine($"1. 更新hash.json 2. 检查更新 3.下载{ProgramName} 4.删除{ProgramName} 5.启动进程 6.移动{ProgramName}到其它路径");
string choose = Console.ReadLine() ?? "";
if (choose == "1")
{
if (!CheckAlreadyDownload())
{
Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
continue;
}
UpdateHash();
}
else if (choose == "2")
{
if (!CheckAlreadyDownload())
{
Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
continue;
}
while (true)
{
if (Data.FilePath != null && Directory.Exists(Data.FilePath))
{
Check(SettingsModel.UsingOS.Win);
break;
}
else
{
Console.WriteLine("读取路径失败!请重新输入文件路径:");
Data.ResetFilepath(Console.ReadLine() ?? "");
}
}
}
else if (choose == "3")
{
if (CheckAlreadyDownload())
{
Console.WriteLine($"已经将{ProgramName}下载到{Data.FilePath}!若要重新下载请先完成删除操作!");
}
else
{
string newpath;
Console.WriteLine("请输入下载路径:");
newpath = Console.ReadLine() ?? "";
Data.ResetFilepath(newpath);
DownloadAll();
}
}
else if (choose == "4")
{
DeleteAll();
}
else if (choose == "5")
{
if (CheckAlreadyDownload())
{
Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
}
else
{
Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
}
}
else if (choose == "6")
{
string newPath;
newPath = Console.ReadLine() ?? "";
MoveProgram(newPath);
}
else if (choose == "7")
{
Console.WriteLine("请输入email:");
string username = Console.ReadLine() ?? "";
Console.WriteLine("请输入密码:");
string password = Console.ReadLine() ?? "";
await web.LoginToEEsast(client, username, password);
}
else if (choose == "8")
{
await web.UserDetails(client);
}
else if (choose == "9")
{
await web.UploadFiles(client, "", "", "");
}
else if (choose == "exit")
{
return;
}
}
}
public static int CheckSelfVersion()
{
string keyHead = "Installer/";
Tencent_cos_download downloader = new Tencent_cos_download();
string hashName = "installerHash.json";
string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName)
?? throw new Exception("Failed to get current directory");
int result = 0;
try
{
if (File.Exists(System.IO.Path.Combine(dir, hashName)))
File.Delete(System.IO.Path.Combine(dir, hashName));
downloader.download(System.IO.Path.Combine(dir, hashName), hashName);
}
catch
{
return -1;
}
string json;
using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, hashName)))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
var jsonDict = Utils.TryDeserializeJson>(json);
string md5 = "";
List awaitUpdate = new List();
if (jsonDict != null)
{
foreach (KeyValuePair pair in jsonDict)
{
md5 = GetFileMd5Hash(System.IO.Path.Combine(dir, pair.Key));
if (md5.Length == 0) // 文档不存在
{
downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key);
}
else if (md5.Equals("conflict"))
{
MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
}
else if (md5 != pair.Value) // MD5不匹配
{
if (pair.Key.Substring(0, 12).Equals("InstallerUpd"))
{
File.Delete(System.IO.Path.Combine(dir, pair.Key));
downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key);
}
else
{
result = 1;
awaitUpdate = awaitUpdate.Append(pair.Key).ToList();
}
}
}
}
else
return -1;
string Contentjson = JsonConvert.SerializeObject(awaitUpdate);
Contentjson = Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/");
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)
?? throw new Exception("Failed to get directory!");
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 = Utils.TryDeserializeJson>(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();
}
}
public class RunProgram
{
public enum RunMode
{
ServerOnly, //只启动Server
ServerForDebugOnly, //只启动ServerForDebug
GUIAttendGameOnly, //只用GUIClient参与游戏
GUIVisit, //只用GUIClient观战
GUIAndAICpp, //用GUI参与游戏并且让cpp的AI同时参与
GUIAndAIPython, //用GUI参与游戏并且让python的AI同时参与
ServerAndCpp, //只运行Server和cpp,
ServerAndPython, //只运行Server和python
ServerAndCppVisit, //运行Server和Cpp并用GUI观战
ServerAndPythonVisit, //运行Server和python并用GUI观战
ServerDebugAndCpp, //运行ServerForDebug...
ServerDebugAndPython,
ServerDebugAndCppVisit,
ServerDebugAndPythonVisit,
}
public class RunInfo //UI需要在调用Launch函数前保证其中数据已经更新并有效
{
static public RunMode mode;
static public string? IP;
static public int port;
static public int studentCount;
static public int trickerCount;
static public int gameTimeSec;
static public string? playbackFileName;
static public int characterID;
static public int type;
static public bool saveDebugLog;
static public bool showDebugLog;
static public bool warningOnly;
static public bool visiting;
static public int occupation;
static public List? playerId = new List(); //两者长度必须与studentCount + trickerCount一致
static public List? filePath = new List();
}
///
/// 运行cmd命令
/// 会显示命令窗口
///
/// 指定应用程序的完整路径
/// 执行命令行参数
static bool RunCmd(string cmdExe, string cmdStr)
{
bool result = false;
try
{
using (Process myPro = new Process())
{
//指定启动进程是调用的应用程序和命令行参数
ProcessStartInfo psi = new ProcessStartInfo(cmdExe, cmdStr);
myPro.StartInfo = psi;
myPro.Start();
//myPro.WaitForExitAsync();
result = true;
}
}
catch
{
}
return result;
}
///
/// 启动Server
/// 会显示命令窗口
///
/// 指定Server运行的IPV4地址
/// 指定Server运行的端口
/// 指定学生人数
/// 指定捣蛋鬼人数
/// 指定游戏最大时长
/// 指定回放文件名称
public static int StartServer(string? IP, int port, int studentCount, int trickerCount, int gameTimeSec, string? playbackFileName)
{
if (System.Diagnostics.Process.GetProcessesByName("Server").ToList().Count > 0)
{
System.Diagnostics.Process.GetProcessesByName("Server")[0].Kill();
}
string cmdExe = $"{Data.FilePath}\\THUAI6\\win\\win64\\Server.exe";
string cmdPara = $"--ip {IP} --port {port} --studentCount {studentCount} --trickerCount {trickerCount}" +
$" --gameTimeInSecond {gameTimeSec} --fileName {playbackFileName}";
RunCmd(cmdExe, cmdPara);
return 0;
}
///
/// 启动Debug用的Server
/// 会显示命令窗口
///
/// 指定Server运行的IPV4地址
/// 指定Server运行的端口
/// 指定学生人数
/// 指定捣蛋鬼人数
/// 指定游戏最大时长
/// 指定回放文件名称
public static int StartServerForDebug(string? IP, int port, int studentCount, int trickerCount, int gameTimeSec, string? playbackFileName)
{
if (System.Diagnostics.Process.GetProcessesByName("Server").ToList().Count > 0)
{
System.Diagnostics.Process.GetProcessesByName("Server")[0].Kill();
}
string cmdExe = $"{Data.FilePath}\\THUAI6\\win\\win64\\Debug\\Server.exe";
string cmdPara = $"--ip {IP} --port {port} --studentCount {studentCount} --trickerCount {trickerCount} " +
$"--gameTimeInSecond {gameTimeSec} --fileName {playbackFileName}";
RunCmd(cmdExe, cmdPara);
return 0;
}
///
/// 启动cpp,在这之前要先启动Server,可能还需要一些延时
/// 会显示命令窗口
///
/// 指定Server运行的IPV4地址
/// 指定Server运行的端口
/// 指定学生人数
/// 指定捣蛋鬼人数
/// 是否保存Debug日志文件
/// 是否将日志输出到屏幕上
/// 在showDebugLog == true时,是否只输出警告或者报错(不影响日志保存)
/// 默认为空,如果不为空,playerIp将会按照顺序代替默认从0~3的IP
public static int RunCpp(string? IP, int port, int studentCount, int trickerCount, bool saveDebugLog,
bool showDebugLog, bool warningOnly, List? playerIp = null, List? filePath = null)
{
string cmdExe;
string cmdBase = $"-I {IP} -P {port} ";
for (int i = 0; i < studentCount; i++)
{
string cmdPara;
if (playerIp == null)
{
cmdPara = cmdBase + $" -p {i}";
}
else
{
cmdPara = cmdBase + $" -p {playerIp[i]}";
}
if (saveDebugLog)
{
cmdPara = cmdPara + " -d";
}
if (showDebugLog)
{
cmdPara = cmdPara + " -o";
}
if (warningOnly)
{
cmdPara = cmdPara + " -w";
}
if (filePath == null)
{
cmdExe = $"{Data.FilePath}\\THUAI6\\win\\CAPI\\cpp\\x64\\Debug\\API.exe";
}
else
{
cmdExe = filePath[i];
}
RunCmd(cmdExe, cmdPara);
}
if (trickerCount != 0)
{
string cmdPara;
cmdPara = cmdBase + " -p 4";
if (saveDebugLog)
{
cmdPara = cmdPara + " -d";
}
if (showDebugLog)
{
cmdPara = cmdPara + " -o";
}
if (warningOnly)
{
cmdPara = cmdPara + " -w";
}
if (filePath == null)
{
cmdExe = $"{Data.FilePath}\\THUAI6\\win\\CAPI\\cpp\\x64\\Debug\\API.exe";
}
else
{
cmdExe = filePath[studentCount];
}
RunCmd(cmdExe, cmdPara);
}
return 0;
}
///
/// 启动客户端
/// 会显示命令窗口
///
/// 指定Server运行的IPV4地址
/// 指定Server运行的端口
/// 进入游戏时的角色ID 0~4,0~3为学生,4为捣蛋鬼
/// 是否观战,当值为true时,characterID无效
/// 指定参加游戏时的角色职业,详情见说明文档
/// 角色类别,type = 1 表示学生,type = 2 表示捣蛋鬼
public static int RunGUIClient(string? IP, int port, int characterID, bool visiting, int occupation = 1, int type = 1)
{
string cmdExe = $"{Data.FilePath}\\THUAI6\\win\\win64\\Client.exe";
string cmdBase = $"--port {port} --ip {IP} --type {type} --occupation {occupation}";
if (visiting)
{
cmdBase = cmdBase + " --characterID 200000";
}
else
{
cmdBase = cmdBase + $" --characterID {characterID}";
}
cmdBase = cmdBase + " --cl";
RunCmd(cmdExe, cmdBase);
return 0;
}
//启动python,参数同RunCpp
public static int RunPython(string? IP, int port, int studentCount, int trickerCount, bool saveDebugLog,
bool showDebugLog, bool warningOnly, List? playerIp = null, List? filePath = null)
{
string cmdExe = $"python";
string cmdBase;
for (int i = 0; i < studentCount; i++)
{
string cmdPara;
if (filePath == null)
{
cmdBase = $" {Data.FilePath}\\THUAI6\\win\\CAPI\\python\\PyAPI\\main.py -I {IP} -P {port} ";
}
else
{
cmdBase = " " + filePath[i] + $" -I {IP} -P {port} ";
}
if (playerIp == null)
{
cmdPara = cmdBase + $" -p {i}";
}
else
{
cmdPara = cmdBase + $" -p {playerIp[i]}";
}
if (saveDebugLog)
{
cmdPara = cmdPara + " -d";
}
if (showDebugLog)
{
cmdPara = cmdPara + " -o";
}
if (warningOnly)
{
cmdPara = cmdPara + " -w";
}
RunCmd(cmdExe, cmdPara);
}
if (trickerCount != 0)
{
string cmdPara;
if (filePath == null)
{
cmdBase = $" {Data.FilePath}\\THUAI6\\win\\CAPI\\python\\PyAPI\\main.py -I {IP} -P {port} ";
}
else
{
cmdBase = " " + filePath[studentCount] + $" -I {IP} -P {port} ";
}
cmdPara = cmdBase + " -p 4";
if (saveDebugLog)
{
cmdPara = cmdPara + " -d";
}
if (showDebugLog)
{
cmdPara = cmdPara + " -o";
}
if (warningOnly)
{
cmdPara = cmdPara + " -w";
}
RunCmd(cmdExe, cmdPara);
}
return 0;
}
}
}
}
namespace WebConnect
{
class Web
{
public enum language { cpp, py };
public static string logintoken = "";
async public Task LoginToEEsast(HttpClient client, string useremail, string password)
{
string token = "";
try
{
using (var response = await client.PostAsync("https://api.eesast.com/users/login", JsonContent.Create(new
{
email = useremail,
password = password,
})))
{
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.OK:
//Console.WriteLine("Success login");
token = (System.Text.Json.JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), typeof(LoginResponse), new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
}) as LoginResponse)
?.Token ??
throw new Exception("no token!");
logintoken = token;
SaveToken();
var info = Utils.DeserializeJson1>(await response.Content.ReadAsStringAsync());
Downloader.UserInfo._id = info["_id"];
Downloader.UserInfo.email = info["email"];
break;
default:
int code = ((int)response.StatusCode);
//Console.WriteLine(code);
if (code == 401)
{
//Console.WriteLine("邮箱或密码错误!");
return -1;
}
break;
}
return 0;
}
}
catch
{
return -2;
}
}
///
///
///
/// http client
/// 代码源位置
/// 编程语言,格式为"cpp"或"python"
/// 第x位玩家,格式为"player_x"
/// -1:tokenFail;-2:FileNotExist;-3:CosFail;-4:loginTimeout;-5:Fail;-6:ReadFileFail;-7:networkError
async public Task UploadFiles(HttpClient client, string tarfile, string type, string plr) //用来上传文件
{
if (!ReadToken()) //读取token失败
{
return -1;
}
try
{
string content;
client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken);
if (!File.Exists(tarfile))
{
//Console.WriteLine("文件不存在!");
return -2;
}
using FileStream fs = new FileStream(tarfile, FileMode.Open, FileAccess.Read);
using StreamReader sr = new StreamReader(fs);
content = sr.ReadToEnd();
string targetUrl = $"https://api.eesast.com/static/player?team_id={await GetTeamId()}";
using (var response = await client.GetAsync(targetUrl))
{
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.OK:
var res = Utils.DeserializeJson1>(await response.Content.ReadAsStringAsync());
string appid = "1255334966"; // 设置腾讯云账户的账户标识(APPID)
string region = "ap-beijing"; // 设置一个默认的存储桶地域
CosXmlConfig config = new CosXmlConfig.Builder()
.IsHttps(true) // 设置默认 HTTPS 请求
.SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
.SetRegion(region) // 设置一个默认的存储桶地域
.SetDebugLog(true) // 显示日志
.Build(); // 创建 CosXmlConfig 对象
string tmpSecretId = res["TmpSecretId"]; //"临时密钥 SecretId";
string tmpSecretKey = res["TmpSecretKey"]; //"临时密钥 SecretKey";
string tmpToken = res["SecurityToken"]; //"临时密钥 token";
long tmpExpiredTime = Convert.ToInt64(res["ExpiredTime"]); //临时密钥有效截止时间,精确到秒
QCloudCredentialProvider cosCredentialProvider = new DefaultSessionQCloudCredentialProvider(
tmpSecretId, tmpSecretKey, tmpExpiredTime, tmpToken
);
// 初始化 CosXmlServer
CosXmlServer cosXml = new CosXmlServer(config, cosCredentialProvider);
// 初始化 TransferConfig
TransferConfig transferConfig = new TransferConfig();
// 初始化 TransferManager
TransferManager transferManager = new TransferManager(cosXml, transferConfig);
string bucket = "eesast-1255334966"; //存储桶,格式:BucketName-APPID
string cosPath = $"/THUAI6/{GetTeamId()}/{type}/{plr}"; //对象在存储桶中的位置标识符,即称对象键
string srcPath = tarfile;//本地文件绝对路径
// 上传对象
COSXMLUploadTask uploadTask = new COSXMLUploadTask(bucket, cosPath);
uploadTask.SetSrcPath(srcPath);
uploadTask.progressCallback = delegate (long completed, long total)
{
//Console.WriteLine(string.Format("progress = {0:##.##}%", completed * 100.0 / total));
};
try
{
COSXMLUploadTask.UploadTaskResult result = await transferManager.UploadAsync(uploadTask);
//Console.WriteLine(result.GetResultInfo());
string eTag = result.eTag;
//到这里应该是成功了,但是因为我没有试过,也不知道具体情况,可能还要根据result的内容判断
}
catch (Exception)
{
return -3;
}
break;
case System.Net.HttpStatusCode.Unauthorized:
//Console.WriteLine("您未登录或登录过期,请先登录");
return -4;
default:
//Console.WriteLine("上传失败!");
return -5;
}
}
}
catch (IOException)
{
//Console.WriteLine("文件读取错误!请检查文件是否被其它应用占用!");
return -6;
}
catch
{
//Console.WriteLine("请求错误!请检查网络连接!");
return -7;
}
return 0;
}
async public Task UserDetails(HttpClient client) // 用来测试访问网站
{
if (!ReadToken()) // 读取token失败
{
return;
}
try
{
client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken);
Console.WriteLine(logintoken);
using (var response = await client.GetAsync("https://api.eesast.com/application/info")) // JsonContent.Create(new
//{
//})))
{
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.OK:
Console.WriteLine("Require OK");
Console.WriteLine(await response.Content.ReadAsStringAsync());
break;
default:
int code = ((int)response.StatusCode);
if (code == 401)
{
Console.WriteLine("您未登录或登录过期,请先登录");
}
return;
}
}
}
catch
{
Console.WriteLine("请求错误!请检查网络连接!");
}
}
public void SaveToken() // 保存token
{
string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
try
{
string json;
Dictionary dict = new Dictionary();
using FileStream fs = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
using (StreamReader r = new StreamReader(fs))
{
json = r.ReadToEnd();
if (json == null || json == "")
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson1>(json);
if (dict.ContainsKey("token"))
{
dict.Remove("token");
}
dict.Add("token", logintoken);
}
using FileStream fs2 = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
using StreamWriter sw = new StreamWriter(fs2);
fs2.SetLength(0);
sw.Write(JsonConvert.SerializeObject(dict)); //将token写入文件
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("保存token时未找到下载器地址!请检查下载器是否被移动!");
}
catch (PathTooLongException)
{
Console.WriteLine("下载器的路径名太长!请尝试移动下载器!");
}
catch (ArgumentNullException)
{
Console.WriteLine("下载器路径初始化失败!");
}
catch (IOException)
{
Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!");
}
}
public static int WriteJson(string key, string data)
{
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 = Utils.DeserializeJson1>(json);
if (!dict.ContainsKey(key))
{
dict.Add(key, data);
}
else
{
dict[key] = data;
}
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;//失败
}
}
public static string? ReadJson(string key)
{
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 = Utils.DeserializeJson1>(json);
fs.Close();
sr.Close();
return dict[key];
}
catch
{
return null; //文件不存在或者已被占用
}
}
public bool ReadToken() // 读取token
{
try
{
string json;
Dictionary dict = new Dictionary();
string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
using FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read);
using StreamReader sr = new StreamReader(fs);
json = sr.ReadToEnd();
if (json == null || json == "")
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson1>(json);
if (!dict.ContainsKey("token"))
{
return false;
}
else
{
logintoken = dict["token"];
return true;
}
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("读取token时未找到下载器地址!请检查下载器是否被移动!");
return false;
}
catch (FileNotFoundException)
{
//没有登陆
Console.WriteLine("请先登录!");
return false;
}
catch (PathTooLongException)
{
Console.WriteLine("下载器的路径名太长!请尝试移动下载器!");
return false;
}
catch (ArgumentNullException)
{
Console.WriteLine("下载器路径初始化失败!");
return false;
}
catch (IOException)
{
Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!");
return false;
}
}
async public Task GetTeamId()
{
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.eesast.com/dev/v1/graphql");
request.Headers.Add("x-hasura-admin-secret", "hasuraDevAdminSecret");
//var content = new StringContent($@"
// {{
// ""query"": ""query MyQuery {{contest_team_member(where: {{user_id: {{_eq: \""{Downloader.UserInfo._id}\""}}}}) {{ team_id }}}}"",
// ""variables"": {{}},
// }}", null, "application/json");
var content = new StringContent("{\"query\":\"query MyQuery {\\r\\n contest_team_member(where: {user_id: {_eq: \\\"" + Downloader.UserInfo._id + "\\\"}}) {\\r\\n team_id\\r\\n }\\r\\n}\",\"variables\":{}}", null, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var info = await response.Content.ReadAsStringAsync();
var s1 = Utils.DeserializeJson1>(info)["data"];
var s2 = Utils.DeserializeJson1>>(s1.ToString() ?? "")["contest_team_member"];
var sres = Utils.DeserializeJson1>(s2[0].ToString() ?? "")["team_id"];
return sres;
}
async public Task GetUserId(string learnNumber)
{
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.eesast.com/dev/v1/graphql");
request.Headers.Add("x-hasura-admin-secret", "hasuraDevAdminSecret");
var content = new StringContent("{\"query\":\"query MyQuery {\r\n user(where: {id: {_eq: \""
+ learnNumber + "\"}}) {\r\n _id\r\n }\r\n}\r\n\",\"variables\":{}}", null, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
[Serializable]
record LoginResponse
{
// Map `Token` to `token` when serializing
public string Token { get; set; } = "";
}
internal static class Utils
{
public static T DeserializeJson1(string json)
where T : notnull
{
return JsonConvert.DeserializeObject(json)
?? throw new Exception("Failed to deserialize json.");
}
public static T? TryDeserializeJson(string json)
where T : notnull
{
return JsonConvert.DeserializeObject(json);
}
}
}