You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Model.cs 81 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
  1. using COSXML.Auth;
  2. using COSXML.CosException;
  3. using COSXML.Model.Object;
  4. using COSXML;
  5. using Newtonsoft.Json;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.IO;
  9. using System.Security.Cryptography;
  10. using System.Text;
  11. using System;
  12. using COSXML.Model.Bucket;
  13. using System.Runtime.InteropServices;
  14. using System.Text.Json.Nodes;
  15. using System.Net.Http.Json;
  16. using System.Text.Json;
  17. using System.Xml.Schema;
  18. using static Downloader.Program;
  19. using System.Threading.Tasks;
  20. using System.Net.Http;
  21. using System.Windows;
  22. using System.Windows.Shapes;
  23. using System.Collections.Concurrent;
  24. //using System.Windows.Forms;
  25. using System.Threading;
  26. using MessageBox = System.Windows.MessageBox;
  27. using Downloader;
  28. using COSXML.Transfer;
  29. using WebConnect;
  30. using System.IO.Compression;
  31. using ICSharpCode.SharpZipLib.Tar;
  32. using ICSharpCode.SharpZipLib.GZip;
  33. using static System.Net.WebRequestMethods;
  34. using File = System.IO.File;
  35. using System.Linq;
  36. using Installer;
  37. using starter.viewmodel.settings;
  38. using System.Security.Permissions;
  39. using System.Windows.Media;
  40. namespace starter.viewmodel.settings
  41. {
  42. /// <summary>
  43. /// Settings Window Model
  44. /// </summary>
  45. public class SettingsModel
  46. {
  47. /// <summary>
  48. /// downloader function
  49. /// </summary>
  50. private Data configData = new Data("");
  51. private Tencent_cos_download cloud = new Tencent_cos_download();
  52. private HttpClient client = new HttpClient();
  53. private WebConnect.Web web = new WebConnect.Web();
  54. public SettingsModel()
  55. {
  56. Route = Data.FilePath;
  57. Username = "";
  58. Password = "";
  59. updates = "";
  60. CodeRoute = "";
  61. PlayerNum = "nSelect";
  62. UploadReady = false;
  63. LoginFailed = false;
  64. launchLanguage = LaunchLanguage.cpp;
  65. usingOS = ReadUsingOS();
  66. }
  67. /// <summary>
  68. /// save settings
  69. /// </summary>
  70. public bool install()
  71. {
  72. if (Tencent_cos_download.CheckAlreadyDownload())
  73. {
  74. MessageBoxResult repeatOption = MessageBox.Show($"文件已存在于{Downloader.Program.Data.FilePath},是否移动到新位置?", "重复安装", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
  75. // ask if abort install, with warning sign, defalut move instead of abort;
  76. if (repeatOption == MessageBoxResult.No)
  77. {
  78. Route = Data.FilePath;
  79. return false;
  80. }
  81. else
  82. {
  83. Downloader.Program.Tencent_cos_download.MoveProgram(Route);
  84. return true;
  85. }
  86. }
  87. else
  88. {
  89. Data.ResetFilepath(Route);
  90. Tencent_cos_download.DownloadAll();
  91. return true;
  92. }
  93. }
  94. public int move()
  95. {
  96. int state = Tencent_cos_download.MoveProgram(Route);
  97. if (state != 0)
  98. Route = Data.FilePath;
  99. return state;
  100. }
  101. ///<summary>
  102. ///check for update
  103. /// </summary>
  104. static bool ProfileAvailable
  105. {
  106. get; set;
  107. }
  108. /// <summary>
  109. /// 检查更新
  110. /// </summary>
  111. /// <returns></returns>
  112. public Status checkUpdate()
  113. {
  114. UpdateInfo updateInfo = Tencent_cos_download.Check(usingOS);
  115. if (updateInfo.newFileCount == -1)
  116. {
  117. if (updateInfo.changedFileCount == -1)
  118. {
  119. return Status.error;
  120. }
  121. else
  122. {
  123. return Status.disconnected;
  124. }
  125. }
  126. else
  127. {
  128. if (updateInfo.changedFileCount != 0 || updateInfo.newFileCount != 0)
  129. {
  130. Updates = $"{updateInfo.newFileCount}个新文件,{updateInfo.changedFileCount}个文件变化";
  131. }
  132. return Status.menu;
  133. }
  134. }
  135. public async Task<int> Login()
  136. {
  137. return await web.LoginToEEsast(client, Username, Password);
  138. }
  139. public bool RememberUser()
  140. {
  141. int result = 0;
  142. result |= Web.WriteJson("email", Username);
  143. result |= Web.WriteJson("password", Password);
  144. return result == 0;
  145. }
  146. public bool RecallUser()
  147. {
  148. var username = Web.ReadJson("email");
  149. if (username == null || username.Equals(""))
  150. {
  151. Username = "";
  152. return false;
  153. }
  154. Username = username;
  155. var password = Web.ReadJson("password");
  156. if (password == null || password.Equals(""))
  157. {
  158. Password = "";
  159. return false;
  160. }
  161. Password = password;
  162. return true;
  163. }
  164. public bool ForgetUser()
  165. {
  166. int result = 0;
  167. result |= Web.WriteJson("email", "");
  168. result |= Web.WriteJson("password", "");
  169. return result == 0;
  170. }
  171. public bool Update()
  172. {
  173. try
  174. {
  175. return Tencent_cos_download.Update();
  176. }
  177. catch
  178. {
  179. return false;
  180. }
  181. }
  182. public int Uninst()
  183. {
  184. return Tencent_cos_download.DeleteAll();
  185. }
  186. public bool Launch()
  187. {
  188. if (Tencent_cos_download.CheckAlreadyDownload())
  189. {
  190. Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
  191. return true;
  192. }
  193. else
  194. {
  195. MessageBox.Show($"文件还不存在,请安装主体文件", "文件不存在", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
  196. return false;
  197. }
  198. }
  199. public async Task<int> Upload()
  200. {
  201. switch (CodeRoute.Substring(CodeRoute.LastIndexOf('.') + 1))
  202. {
  203. case "cpp":
  204. case "h":
  205. Language = "cpp";
  206. break;
  207. case "py":
  208. Language = "python";
  209. break;
  210. default:
  211. return -8;
  212. }
  213. if (PlayerNum.Equals("nSelect"))
  214. return -9;
  215. return await web.UploadFiles(client, CodeRoute, Language, PlayerNum);
  216. }
  217. public bool WriteUsingOS()
  218. {
  219. string OS = "";
  220. switch (usingOS)
  221. {
  222. case UsingOS.Win:
  223. OS = "win";
  224. break;
  225. case UsingOS.Linux:
  226. OS = "linux";
  227. break;
  228. case UsingOS.OSX:
  229. OS = "osx";
  230. break;
  231. }
  232. return Web.WriteJson("OS", OS) == 0;
  233. }
  234. public UsingOS ReadUsingOS()
  235. {
  236. return Web.ReadJson("OS") switch
  237. {
  238. "linux" => UsingOS.Linux,
  239. "osx" => UsingOS.OSX,
  240. _ => UsingOS.Win,
  241. };
  242. }
  243. /// <summary>
  244. /// Route of files
  245. /// </summary>
  246. public string Route
  247. {
  248. get; set;
  249. }
  250. public string Username
  251. {
  252. get; set;
  253. }
  254. public string Password
  255. {
  256. get; set;
  257. }
  258. public string CodeRoute
  259. {
  260. get; set;
  261. }
  262. public string? Language
  263. {
  264. get; set;
  265. }
  266. public string PlayerNum
  267. {
  268. get; set;
  269. }
  270. /// <summary>
  271. /// 关于更新的屏幕显示信息
  272. /// </summary>
  273. private string updates;
  274. public string Updates
  275. {
  276. get
  277. {
  278. return updates;
  279. }
  280. set
  281. {
  282. updates = value;
  283. }
  284. }
  285. /// <summary>
  286. /// 关于介绍的屏幕显示信息
  287. /// </summary>
  288. public enum Status { newUser, menu, move, working, disconnected, error, successful, login, web };
  289. public Status status
  290. {
  291. get; set;
  292. }
  293. public bool Working
  294. {
  295. get; set;
  296. }
  297. /// <summary>
  298. /// if an update is planned
  299. /// </summary>
  300. public bool UpdatePlanned
  301. {
  302. get
  303. {
  304. return Program.UpdatePlanned;
  305. }
  306. }
  307. public bool CombatCompleted
  308. {
  309. get
  310. {
  311. return false;
  312. }
  313. }
  314. public bool LoginFailed
  315. {
  316. get; set;
  317. }
  318. public bool UploadReady
  319. {
  320. get; set;
  321. }
  322. public bool RememberMe
  323. {
  324. get; set;
  325. }
  326. public enum LaunchLanguage { cpp, python };
  327. public LaunchLanguage launchLanguage
  328. {
  329. get; set;
  330. }
  331. public enum UsingOS { Win, Linux, OSX };
  332. public UsingOS usingOS
  333. {
  334. get; set;
  335. }
  336. }
  337. }
  338. namespace Downloader
  339. {
  340. class UserInfo
  341. {
  342. static public string _id = "";
  343. static public string email = "";
  344. }
  345. class Program
  346. {
  347. static ConcurrentQueue<string> newFileName = new ConcurrentQueue<string>();
  348. //static List<string> newFileName = new List<string>(); // 新文件名
  349. static ConcurrentQueue<string> updateFileName = new ConcurrentQueue<string>(); // 更新文件名
  350. static List<string> updateFailed = new List<string>(); //更新失败的文件名
  351. static public List<string> UpdateFailed
  352. {
  353. get { return updateFailed; }
  354. }
  355. static public void ResetUpdateFailedInfo()
  356. {
  357. updateFailed.Clear();
  358. }
  359. public static string ProgramName = "THUAI6"; // 要运行或下载的程序名称
  360. public static string playerFolder = "player"; // 选手代码保存文件夹路径
  361. public static string startName = "maintest.exe"; // 启动的程序名
  362. public struct UpdateInfo // 更新信息,包括新版本版本号、更改文件数和新文件数
  363. {
  364. public string status;
  365. public int changedFileCount;
  366. public int newFileCount;
  367. }
  368. public static bool UpdatePlanned
  369. {
  370. get; set;
  371. }
  372. static int filenum = 0; // 总文件个数
  373. public class Data
  374. {
  375. public static string path = ""; // 标记路径记录文件THUAI6.json的路径
  376. public static string FilePath = ""; // 最后一级为THUAI6文件夹所在目录
  377. public static string dataPath = ""; // C盘的文档文件夹
  378. public Data(string path)
  379. {
  380. dataPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
  381. //dataPath = new DirectoryInfo(".").FullName;
  382. Data.path = System.IO.Path.Combine(dataPath, "THUAI6.json");
  383. if (File.Exists(Data.path))
  384. {
  385. Dictionary<string, string>? dict;
  386. using (StreamReader r = new StreamReader(Data.path))
  387. {
  388. string json = r.ReadToEnd();
  389. if (json == null || json == "")
  390. {
  391. json += @"{""THUAI6""" + ":" + @"""2023""}";
  392. }
  393. dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
  394. if (dict != null && dict.ContainsKey("installpath"))
  395. {
  396. FilePath = dict["installpath"].Replace('\\', '/');
  397. } //读取安装路径
  398. }
  399. dict?.TryAdd("installpath", @path);
  400. using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  401. using StreamWriter sw = new StreamWriter(fs);
  402. sw.Write(JsonConvert.SerializeObject(dict));
  403. sw.Flush();
  404. }
  405. else
  406. {
  407. FilePath = System.IO.Path.GetDirectoryName(@path)
  408. ?? throw new Exception("Failed to get the path of the file");
  409. //将dat文件写入程序运行路径
  410. string json;
  411. Dictionary<string, string>? dict;
  412. using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  413. using (StreamReader r = new StreamReader(fs))
  414. {
  415. json = r.ReadToEnd();
  416. if (json == null || json == "")
  417. {
  418. json += @"{""THUAI6""" + ":" + @"""2023""}";
  419. }
  420. dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
  421. dict?.Add("installpath", path);
  422. }
  423. using FileStream fs2 = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  424. using StreamWriter sw = new StreamWriter(fs2);
  425. sw.Write(JsonConvert.SerializeObject(dict));
  426. sw.Flush();
  427. }
  428. }
  429. public static void ResetFilepath(string newPath)
  430. {
  431. string json;
  432. Dictionary<string, string>? dict;
  433. FilePath = newPath.Replace('\\', '/');
  434. path = System.IO.Path.Combine(dataPath, "THUAI6.json");
  435. using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  436. using (StreamReader r = new StreamReader(fs))
  437. {
  438. json = r.ReadToEnd();
  439. if (json == null || json == "")
  440. {
  441. json += @"{""THUAI6""" + ":" + @"""2023""}";
  442. }
  443. dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
  444. if (dict != null && dict.ContainsKey("installpath"))
  445. {
  446. dict["installpath"] = newPath;
  447. }
  448. else
  449. {
  450. dict?.Add("installpath", newPath);
  451. }
  452. if (dict == null || !dict.ContainsKey("download"))
  453. {
  454. dict?.Add("download", "true");
  455. }
  456. else
  457. {
  458. dict["download"] = "true";
  459. }
  460. }
  461. using FileStream fs2 = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
  462. using StreamWriter sw = new StreamWriter(fs2);
  463. fs2.SetLength(0);
  464. sw.Write(JsonConvert.SerializeObject(dict));
  465. sw.Flush();
  466. }
  467. }
  468. public class Tencent_cos_download
  469. {
  470. public void download(string download_dir, string key)
  471. {
  472. // download_dir标记根文件夹路径,key为相对根文件夹的路径(不带./)
  473. // 初始化CosXmlConfig(提供配置SDK接口)
  474. string appid = "1314234950"; // 设置腾讯云账户的账户标识(APPID)
  475. string region = "ap-beijing"; // 设置一个默认的存储桶地域
  476. CosXmlConfig config = new CosXmlConfig.Builder()
  477. .IsHttps(true) // 设置默认 HTTPS 请求
  478. .SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
  479. .SetRegion(region) // 设置一个默认的存储桶地域
  480. .SetDebugLog(true) // 显示日志
  481. .Build(); // 创建 CosXmlConfig 对象
  482. // 永久密钥访问凭证
  483. string secretId = "AKIDvhEVXN4cv0ugIlFYiniV6Wk1McfkplYA"; //"云 API 密钥 SecretId";
  484. string secretKey = "YyGLGCJG4f5VsEUddnz9JSRPSSK8sYBo"; //"云 API 密钥 SecretKey";
  485. long durationSecond = 1000; // 每次请求签名有效时长,单位为秒
  486. QCloudCredentialProvider cosCredentialProvider = new DefaultQCloudCredentialProvider(
  487. secretId, secretKey, durationSecond
  488. );
  489. // 初始化 CosXmlServer
  490. CosXmlServer cosXml = new CosXmlServer(config, cosCredentialProvider);
  491. // 创建存储桶
  492. try
  493. {
  494. string bucket = "thuai6-1314234950"; // 格式:BucketName-APPID
  495. string localDir = System.IO.Path.GetDirectoryName(download_dir) // 本地文件夹
  496. ?? throw new Exception("本地文件夹路径获取失败");
  497. string localFileName = System.IO.Path.GetFileName(download_dir); // 指定本地保存的文件名
  498. GetObjectRequest request = new GetObjectRequest(bucket, key, localDir, localFileName);
  499. Dictionary<string, string> test = request.GetRequestHeaders();
  500. request.SetCosProgressCallback(delegate (long completed, long total)
  501. {
  502. //Console.WriteLine(String.Format("progress = {0:##.##}%", completed * 100.0 / total));
  503. });
  504. // 执行请求
  505. GetObjectResult result = cosXml.GetObject(request);
  506. // 请求成功
  507. }
  508. catch (CosClientException clientEx)
  509. {
  510. throw clientEx;
  511. }
  512. catch (CosServerException serverEx)
  513. {
  514. throw serverEx;
  515. }
  516. catch
  517. {
  518. MessageBox.Show($"下载{download_dir}时出现未知问题,请反馈");
  519. }
  520. }
  521. public static void GetNewHash()
  522. {
  523. Tencent_cos_download Downloader = new Tencent_cos_download();
  524. Downloader.download(System.IO.Path.Combine(Data.FilePath, "hash.json"), "hash.json");
  525. }
  526. public static string GetFileMd5Hash(string strFileFullPath)
  527. {
  528. FileStream? fst = null;
  529. try
  530. {
  531. fst = new FileStream(strFileFullPath, FileMode.Open, FileAccess.Read);
  532. byte[] data = MD5.Create().ComputeHash(fst);
  533. StringBuilder sBuilder = new StringBuilder();
  534. for (int i = 0; i < data.Length; i++)
  535. {
  536. sBuilder.Append(data[i].ToString("x2"));
  537. }
  538. fst.Close();
  539. return sBuilder.ToString().ToLower();
  540. }
  541. catch (Exception)
  542. {
  543. if (fst != null)
  544. fst.Close();
  545. if (File.Exists(strFileFullPath))
  546. return "conflict";
  547. return "";
  548. }
  549. finally
  550. {
  551. }
  552. }
  553. public static bool IsUserFile(string filename)
  554. {
  555. if (filename.Substring(filename.Length - 3, 3).Equals(".sh") || filename.Substring(filename.Length - 4, 4).Equals(".cmd"))
  556. return true;
  557. if (filename.Equals("AI.cpp") || filename.Equals("AI.py"))
  558. return true;
  559. return false;
  560. }
  561. public static UpdateInfo Check(SettingsModel.UsingOS OS)
  562. {
  563. string json, MD5, jsonName;
  564. int newFile = 0, updateFile = 0;
  565. newFileName.Clear();
  566. updateFileName.Clear();
  567. jsonName = "hash.json";
  568. UpdateInfo updateInfo;
  569. Tencent_cos_download Downloader = new Tencent_cos_download();
  570. try
  571. {
  572. // 如果json存在就删了重新下
  573. if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
  574. {
  575. File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
  576. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  577. }
  578. else
  579. {
  580. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  581. }
  582. }
  583. catch (CosClientException clientEx)
  584. {
  585. // 请求失败
  586. updateInfo.status = "ClientEx: " + clientEx.ToString();
  587. updateInfo.newFileCount = -1;
  588. updateInfo.changedFileCount = 0;
  589. return updateInfo;
  590. }
  591. catch (CosServerException serverEx)
  592. {
  593. // 请求失败
  594. updateInfo.status = "ServerEx: " + serverEx.ToString();
  595. updateInfo.newFileCount = -1;
  596. updateInfo.changedFileCount = 0;
  597. return updateInfo;
  598. }
  599. using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
  600. json = r.ReadToEnd();
  601. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  602. var jsonDict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
  603. string updatingFolder = "";
  604. switch (OS)
  605. {
  606. case SettingsModel.UsingOS.Win:
  607. updatingFolder = "THUAI6/win";
  608. break;
  609. case SettingsModel.UsingOS.Linux:
  610. updatingFolder = "THUAI6/lin";
  611. break;
  612. case SettingsModel.UsingOS.OSX:
  613. updatingFolder = "THUAI6/osx";
  614. break;
  615. }
  616. foreach (KeyValuePair<string, string> pair in jsonDict)
  617. {
  618. if (pair.Key.Length > 10 && (pair.Key.Substring(0, 10).Equals(updatingFolder)) || pair.Key.Substring(pair.Key.Length - 4, 4).Equals(".pdf"))
  619. {
  620. MD5 = GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key.TrimStart(new char[] { '.', '/' })));
  621. if (MD5.Length == 0) // 文档不存在
  622. newFileName.Enqueue(pair.Key);
  623. else if (MD5.Equals("conflict"))
  624. {
  625. if (pair.Key.Equals("THUAI6/win/CAPI/cpp/.vs/CAPI/v17/Browse.VC.db"))
  626. {
  627. MessageBox.Show($"visual studio未关闭:\n" +
  628. $"对于visual studio 2022,可以更新,更新会覆盖visual studio中已经打开的选手包;\n" +
  629. $"若使用其他版本的visual studio是继续更新出现问题,请汇报;\n" +
  630. $"若您自行修改了选手包,请注意备份;\n" +
  631. $"若关闭visual studio后仍弹出,请汇报。\n\n",
  632. "visual studio未关闭", MessageBoxButton.OK, MessageBoxImage.Information);
  633. }
  634. else
  635. MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
  636. }
  637. else if (!MD5.Equals(pair.Value) && !IsUserFile(System.IO.Path.GetFileName(pair.Key))) // MD5不匹配
  638. updateFileName.Enqueue(pair.Key);
  639. }
  640. }
  641. newFile = newFileName.Count;
  642. updateFile = updateFileName.Count;
  643. filenum = newFile + updateFile;
  644. //Console.WriteLine("----------------------" + Environment.NewLine);
  645. if (newFile + updateFile == 0)
  646. {
  647. updateInfo.status = "latest";
  648. updateInfo.newFileCount = 0;
  649. updateInfo.changedFileCount = 0;
  650. newFileName.Clear();
  651. updateFileName.Clear();
  652. }
  653. else
  654. {
  655. updateInfo.status = "old";
  656. //TODO:获取版本号
  657. updateInfo.newFileCount = newFile;
  658. /*
  659. foreach (string filename in newFileName)
  660. {
  661. Console.WriteLine(filename);
  662. }
  663. */
  664. updateInfo.changedFileCount = updateFile;
  665. /*
  666. foreach (string filename in updateFileName)
  667. {
  668. Console.WriteLine(filename);
  669. }
  670. Console.Write(Environment.NewLine + "是否下载新文件? y/n:");
  671. if (Console.Read() != 'y')
  672. Console.WriteLine("下载取消!");
  673. else
  674. Download();
  675. */
  676. UpdatePlanned = true;
  677. }
  678. return updateInfo;
  679. }
  680. public static bool Update()
  681. {
  682. if (UpdatePlanned)
  683. {
  684. Download();
  685. if (updateFailed.Count == 0)
  686. return true;
  687. }
  688. return false;
  689. }
  690. private static void Download()
  691. {
  692. Tencent_cos_download Downloader = new Tencent_cos_download();
  693. int newFile = 0, updateFile = 0;
  694. int totalnew = newFileName.Count, totalupdate = updateFileName.Count;
  695. filenum = totalnew + totalupdate;
  696. updateFailed.Clear();
  697. if (newFileName.Count > 0 || updateFileName.Count > 0)
  698. {
  699. try
  700. {
  701. int cnt = newFileName.Count;
  702. if (cnt <= 20)
  703. {
  704. while (newFileName.TryDequeue(out var filename))
  705. {
  706. Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
  707. //Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
  708. Interlocked.Increment(ref newFile);
  709. }
  710. }
  711. else
  712. {
  713. const int nthread = 8;
  714. var thrds = new List<Thread>();
  715. for (int i = 0; i < nthread; i++)
  716. {
  717. var thrd = new Thread(() =>
  718. {
  719. while (newFileName.TryDequeue(out var filename))
  720. {
  721. Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
  722. //Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
  723. Interlocked.Increment(ref newFile);
  724. }
  725. });
  726. thrd.Start();
  727. thrds.Add(thrd);
  728. }
  729. foreach (var thrd in thrds)
  730. {
  731. thrd.Join();
  732. }
  733. }
  734. // 读取 Interlocked.CompareExchange(ref newFile, 0, 0);
  735. int upcnt = updateFileName.Count;
  736. if(upcnt <= 20)
  737. {
  738. while (newFileName.TryDequeue(out var filename))
  739. {
  740. try
  741. {
  742. File.Delete(System.IO.Path.Combine(@Data.FilePath, filename));
  743. Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
  744. }
  745. catch (System.IO.IOException)
  746. {
  747. updateFailed = updateFailed.Append(filename).ToList();
  748. }
  749. catch
  750. {
  751. if (filename.Substring(filename.Length - 4, 4).Equals(".pdf"))
  752. {
  753. MessageBox.Show($"由于曾经发生过的访问冲突,下载器无法更新{filename}\n"
  754. + $"请手动删除{filename},然后再试一次。");
  755. }
  756. else
  757. MessageBox.Show($"更新{filename}时遇到未知问题,请反馈");
  758. updateFailed = updateFailed.Append(filename).ToList();
  759. }
  760. Interlocked.Increment(ref newFile);
  761. }
  762. }
  763. else
  764. {
  765. const int nthread = 8;
  766. var thrds = new List<Thread>();
  767. for (int i = 0; i < nthread; i++)
  768. {
  769. var thrd = new Thread(() =>
  770. {
  771. while (updateFileName.TryDequeue(out var filename))
  772. {
  773. try
  774. {
  775. File.Delete(System.IO.Path.Combine(@Data.FilePath, filename));
  776. Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
  777. }
  778. catch (System.IO.IOException)
  779. {
  780. updateFailed = updateFailed.Append(filename).ToList();
  781. }
  782. catch
  783. {
  784. if (filename.Substring(filename.Length - 4, 4).Equals(".pdf"))
  785. {
  786. MessageBox.Show($"由于曾经发生过的访问冲突,下载器无法更新{filename}\n"
  787. + $"请手动删除{filename},然后再试一次。");
  788. }
  789. else
  790. MessageBox.Show($"更新{filename}时遇到未知问题,请反馈");
  791. updateFailed = updateFailed.Append(filename).ToList();
  792. }
  793. Interlocked.Increment(ref newFile);
  794. }
  795. });
  796. thrd.Start();
  797. thrds.Add(thrd);
  798. }
  799. foreach (var thrd in thrds)
  800. {
  801. thrd.Join();
  802. }
  803. }
  804. if (updateFailed.Count == 0)
  805. UpdatePlanned = false;
  806. }
  807. catch (CosClientException clientEx)
  808. {
  809. // 请求失败
  810. MessageBox.Show("连接错误:" + clientEx.ToString());
  811. Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
  812. return;
  813. }
  814. catch (CosServerException serverEx)
  815. {
  816. // 请求失败
  817. MessageBox.Show("连接错误:" + serverEx.ToString());
  818. Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
  819. return;
  820. }
  821. catch (Exception)
  822. {
  823. MessageBox.Show("未知错误且无法定位到出错文件,请反馈");
  824. throw;
  825. }
  826. }
  827. else
  828. Console.WriteLine("当前平台已是最新版本!" + Environment.NewLine);
  829. newFileName.Clear();
  830. updateFileName.Clear();
  831. }
  832. public static bool CheckAlreadyDownload() // 检查是否已经下载
  833. {
  834. string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  835. if (!File.Exists(existpath)) // 文件不存在
  836. {
  837. using FileStream fs = new FileStream(existpath, FileMode.Create, FileAccess.ReadWrite);
  838. return false;
  839. }
  840. else // 文件存在
  841. {
  842. using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.Read);
  843. using StreamReader sr = new StreamReader(fs);
  844. string json = sr.ReadToEnd();
  845. if (json == null || json == "")
  846. {
  847. json += @"{""THUAI6""" + ":" + @"""2023""}";
  848. }
  849. var dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
  850. if (dict == null || !dict.ContainsKey("download") || "false" == dict["download"])
  851. {
  852. return false;
  853. }
  854. else if (dict["download"] == "true")
  855. {
  856. return true;
  857. }
  858. else
  859. {
  860. return false;
  861. }
  862. }
  863. }
  864. public static void DownloadAll() // 下载全部文件
  865. {
  866. string jsonName = "hash.json";
  867. string json;
  868. Tencent_cos_download Downloader = new Tencent_cos_download();
  869. try
  870. {
  871. // 如果json存在就删了重新下
  872. if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
  873. {
  874. File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
  875. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  876. }
  877. else
  878. {
  879. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  880. }
  881. }
  882. catch (CosClientException clientEx)
  883. {
  884. // 请求失败
  885. Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
  886. return;
  887. }
  888. catch (CosServerException serverEx)
  889. {
  890. // 请求失败
  891. Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
  892. return;
  893. }
  894. using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
  895. json = r.ReadToEnd();
  896. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  897. // var jsonDict = Utils.DeserializeJson<Dictionary1<string, string>>(json);
  898. newFileName.Clear();
  899. updateFileName.Clear();
  900. newFileName.Enqueue("THUAI6.tar.gz");
  901. Download();
  902. Stream? inStream = null;
  903. Stream? gzipStream = null;
  904. TarArchive? tarArchive = null;
  905. try
  906. {
  907. using (inStream = File.OpenRead(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz")))
  908. {
  909. using (gzipStream = new GZipInputStream(inStream))
  910. {
  911. tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
  912. tarArchive.ExtractContents(Data.FilePath);
  913. tarArchive.Close();
  914. }
  915. }
  916. }
  917. catch
  918. {
  919. //出错
  920. }
  921. finally
  922. {
  923. if (null != tarArchive) tarArchive.Close();
  924. if (null != gzipStream) gzipStream.Close();
  925. if (null != inStream) inStream.Close();
  926. }
  927. FileInfo fileInfo = new FileInfo(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz"));
  928. fileInfo.Delete();
  929. string json2;
  930. Dictionary<string, string>? dict;
  931. string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  932. using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  933. using (StreamReader r = new StreamReader(fs))
  934. {
  935. json2 = r.ReadToEnd();
  936. if (json2 == null || json2 == "")
  937. {
  938. json2 += @"{""THUAI6""" + ":" + @"""2023""}";
  939. }
  940. dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json2);
  941. if (dict == null || !dict.ContainsKey("download"))
  942. {
  943. dict?.Add("download", "true");
  944. }
  945. else
  946. {
  947. dict["download"] = "true";
  948. }
  949. }
  950. using FileStream fs2 = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  951. using StreamWriter sw = new StreamWriter(fs2);
  952. fs2.SetLength(0);
  953. sw.Write(JsonConvert.SerializeObject(dict));
  954. Check(SettingsModel.UsingOS.Win);
  955. Download();
  956. if (File.Exists(Data.FilePath + "/THUAI6/AI.cpp"))
  957. {
  958. FileInfo userCpp = new FileInfo((Data.FilePath + "/THUAI6/AI.cpp").Replace("/", "\\"));
  959. userCpp.MoveTo(Data.FilePath + "/THUAI6/win/CAPI/cpp/API/src/AI.cpp", true);
  960. }
  961. if (File.Exists(Data.FilePath + "/THUAI6/AI.py"))
  962. {
  963. FileInfo userCpp = new FileInfo((Data.FilePath + "/THUAI6/AI.py").Replace("/", "\\"));
  964. userCpp.MoveTo(Data.FilePath + "/THUAI6/win/CAPI/python/PyAPI/AI.cpp", true);
  965. }
  966. }
  967. public static void Change_all_hash(string topDir, Dictionary<string, string> jsonDict) // 更改HASH
  968. {
  969. DirectoryInfo theFolder = new DirectoryInfo(@topDir);
  970. bool ifexist = false;
  971. // 遍历文件
  972. foreach (FileInfo NextFile in theFolder.GetFiles())
  973. {
  974. string filepath = topDir + @"/" + NextFile.Name; // 文件路径
  975. //Console.WriteLine(filepath);
  976. foreach (KeyValuePair<string, string> pair in jsonDict)
  977. {
  978. if (System.IO.Path.Equals(filepath, System.IO.Path.Combine(Data.FilePath, pair.Key).Replace('\\', '/')))
  979. {
  980. ifexist = true;
  981. string MD5 = GetFileMd5Hash(filepath);
  982. jsonDict[pair.Key] = MD5;
  983. }
  984. }
  985. if (!ifexist && NextFile.Name != "hash.json")
  986. {
  987. string MD5 = GetFileMd5Hash(filepath);
  988. string relapath = filepath.Replace(Data.FilePath + '/', string.Empty);
  989. jsonDict.Add(relapath, MD5);
  990. }
  991. ifexist = false;
  992. }
  993. // 遍历文件夹
  994. foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
  995. {
  996. if (System.IO.Path.Equals(NextFolder.FullName, System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder))))
  997. {
  998. foreach (FileInfo NextFile in NextFolder.GetFiles())
  999. {
  1000. if (NextFile.Name == "AI.cpp" || NextFile.Name == "AI.py")
  1001. {
  1002. string MD5 = GetFileMd5Hash(NextFile.FullName);
  1003. string relapath = NextFile.FullName.Replace('\\', '/').Replace(Data.FilePath + '/', string.Empty);
  1004. jsonDict.Add(relapath, MD5);
  1005. }
  1006. }
  1007. continue; // 如果是选手文件夹就忽略
  1008. }
  1009. Change_all_hash(NextFolder.FullName.Replace('\\', '/'), jsonDict);
  1010. }
  1011. }
  1012. public static void UpdateHash()
  1013. {
  1014. while (true)
  1015. {
  1016. if (Directory.Exists(Data.FilePath))
  1017. {
  1018. string json;
  1019. if (!File.Exists(System.IO.Path.Combine(Data.FilePath, "hash.json")))
  1020. {
  1021. Console.WriteLine("hash.json文件丢失!即将重新下载该文件!");
  1022. GetNewHash();
  1023. }
  1024. using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, "hash.json")))
  1025. json = r.ReadToEnd();
  1026. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("/", @"\\");
  1027. Dictionary<string, string> jsonDict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
  1028. Change_all_hash(Data.FilePath, jsonDict);
  1029. OverwriteHash(jsonDict);
  1030. break;
  1031. }
  1032. else
  1033. {
  1034. Console.WriteLine("读取路径失败!请重新输入文件路径:");
  1035. Data.ResetFilepath(Console.ReadLine() ?? "");
  1036. }
  1037. }
  1038. }
  1039. public static int DeleteAll()
  1040. {
  1041. DirectoryInfo di = new DirectoryInfo(Data.FilePath + "/THUAI6");
  1042. //DirectoryInfo player = new DirectoryInfo(System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder)));
  1043. FileInfo[] allfile = di.GetFiles();
  1044. try
  1045. {
  1046. foreach (FileInfo file in allfile)
  1047. {
  1048. //if(file.Name == "AI.cpp" || file.Name == "AI.py")
  1049. //{
  1050. // string filename = System.IO.Path.GetFileName(file.FullName);
  1051. // file.MoveTo(System.IO.Path.Combine(Data.FilePath, filename));
  1052. // continue;
  1053. //}
  1054. file.Delete();
  1055. }
  1056. FileInfo userFileCpp = new FileInfo(Data.FilePath + "/THUAI6/win/CAPI/cpp/API/src/AI.cpp");
  1057. FileInfo userFilePy = new FileInfo(Data.FilePath + "/THUAI6/win/CAPI/python/PyAPI/AI.py");
  1058. userFileCpp.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", System.IO.Path.GetFileName(userFileCpp.FullName)));
  1059. userFilePy.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", System.IO.Path.GetFileName(userFilePy.FullName)));
  1060. foreach (DirectoryInfo subdi in di.GetDirectories())
  1061. {
  1062. subdi.Delete(true);
  1063. }
  1064. FileInfo hashFile = new FileInfo(Data.FilePath + "/hash.json");
  1065. hashFile.Delete();
  1066. }
  1067. catch (UnauthorizedAccessException)
  1068. {
  1069. Console.WriteLine("权限不足,无法删除!");
  1070. return -2;
  1071. }
  1072. catch (DirectoryNotFoundException)
  1073. {
  1074. Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
  1075. return -3;
  1076. }
  1077. catch (IOException)
  1078. {
  1079. Console.WriteLine("文件已经打开,请关闭后再删除");
  1080. return -1;
  1081. }
  1082. string json2;
  1083. Dictionary<string, string>? dict;
  1084. string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1085. using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  1086. using (StreamReader r = new StreamReader(fs))
  1087. {
  1088. json2 = r.ReadToEnd();
  1089. if (json2 == null || json2 == "")
  1090. {
  1091. json2 += @"{""THUAI6""" + ":" + @"""2023""}";
  1092. }
  1093. dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json2);
  1094. if (dict == null || !dict.ContainsKey("download"))
  1095. {
  1096. dict?.Add("download", "false");
  1097. }
  1098. else
  1099. {
  1100. dict["download"] = "false";
  1101. }
  1102. }
  1103. using FileStream fs2 = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  1104. using StreamWriter sw = new StreamWriter(fs2);
  1105. fs2.SetLength(0);
  1106. sw.Write(JsonConvert.SerializeObject(dict));
  1107. sw.Close();
  1108. fs2.Close();
  1109. try
  1110. {
  1111. File.Delete(Data.path);
  1112. }
  1113. catch (UnauthorizedAccessException)
  1114. {
  1115. Console.WriteLine("权限不足,无法删除!");
  1116. return -2;
  1117. }
  1118. catch (DirectoryNotFoundException)
  1119. {
  1120. Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
  1121. return -3;
  1122. }
  1123. catch (IOException)
  1124. {
  1125. Console.WriteLine("文件已经打开,请关闭后再删除");
  1126. return -1;
  1127. }
  1128. return 0;
  1129. }
  1130. public static void OverwriteHash(Dictionary<string, string> jsonDict)
  1131. {
  1132. string Contentjson = JsonConvert.SerializeObject(jsonDict);
  1133. Contentjson = Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/");
  1134. File.WriteAllText(@System.IO.Path.Combine(Data.FilePath, "hash.json"), Contentjson);
  1135. }
  1136. public static int MoveProgram(string newPath)
  1137. {
  1138. DirectoryInfo newdi = new DirectoryInfo(newPath + "/THUAI6");
  1139. DirectoryInfo olddi = new DirectoryInfo(Data.FilePath + "/THUAI6");
  1140. try
  1141. {
  1142. if (!Directory.Exists(newPath + "/THUAI6"))
  1143. Directory.CreateDirectory(newPath + "/THUAI6");
  1144. foreach (DirectoryInfo direct in olddi.GetDirectories())
  1145. {
  1146. direct.MoveTo(System.IO.Path.Combine(newPath + "/THUAI6", direct.Name));
  1147. }
  1148. foreach (FileInfo file in olddi.GetFiles())
  1149. {
  1150. file.MoveTo(System.IO.Path.Combine(newPath + "/THUAI6", file.Name));
  1151. }
  1152. olddi.Delete();
  1153. }
  1154. catch (DirectoryNotFoundException)
  1155. {
  1156. Console.WriteLine("原路径未找到!请检查文件是否损坏");
  1157. if (newdi.GetDirectories().Length != 0)
  1158. {
  1159. foreach (DirectoryInfo newdirect in newdi.GetDirectories())
  1160. {
  1161. newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", newdirect.Name));
  1162. }
  1163. }
  1164. if (newdi.GetFiles().Length != 0)
  1165. {
  1166. foreach (FileInfo file in newdi.GetFiles())
  1167. {
  1168. file.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", file.Name));
  1169. }
  1170. }
  1171. Console.WriteLine("移动失败!");
  1172. if (newdi.Exists)
  1173. newdi.Delete();
  1174. return -2;
  1175. }
  1176. catch (IOException)
  1177. {
  1178. Console.WriteLine("文件已打开或者目标路径下有同名文件!");
  1179. if (newdi.GetDirectories().Length != 0)
  1180. {
  1181. foreach (DirectoryInfo newdirect in newdi.GetDirectories())
  1182. {
  1183. newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", newdirect.Name));
  1184. }
  1185. }
  1186. if (newdi.GetFiles().Length != 0)
  1187. {
  1188. foreach (FileInfo file in newdi.GetFiles())
  1189. {
  1190. file.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", file.Name));
  1191. }
  1192. }
  1193. if (newdi.Exists)
  1194. newdi.Delete();
  1195. Console.WriteLine("移动失败!");
  1196. return -1;
  1197. }
  1198. FileInfo hashFile = new FileInfo(Data.FilePath + "/hash.json");
  1199. hashFile.MoveTo(newPath + "/hash.json");
  1200. Data.ResetFilepath(newPath);
  1201. Console.WriteLine("更改路径成功!");
  1202. return 0;
  1203. }
  1204. public static async Task main(string[] args)
  1205. {
  1206. var client = new HttpClient();
  1207. var web = new WebConnect.Web();
  1208. Data date = new Data("");
  1209. while (true)
  1210. {
  1211. Console.WriteLine($"1. 更新hash.json 2. 检查更新 3.下载{ProgramName} 4.删除{ProgramName} 5.启动进程 6.移动{ProgramName}到其它路径");
  1212. string choose = Console.ReadLine() ?? "";
  1213. if (choose == "1")
  1214. {
  1215. if (!CheckAlreadyDownload())
  1216. {
  1217. Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
  1218. continue;
  1219. }
  1220. UpdateHash();
  1221. }
  1222. else if (choose == "2")
  1223. {
  1224. if (!CheckAlreadyDownload())
  1225. {
  1226. Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
  1227. continue;
  1228. }
  1229. while (true)
  1230. {
  1231. if (Data.FilePath != null && Directory.Exists(Data.FilePath))
  1232. {
  1233. Check(SettingsModel.UsingOS.Win);
  1234. break;
  1235. }
  1236. else
  1237. {
  1238. Console.WriteLine("读取路径失败!请重新输入文件路径:");
  1239. Data.ResetFilepath(Console.ReadLine() ?? "");
  1240. }
  1241. }
  1242. }
  1243. else if (choose == "3")
  1244. {
  1245. if (CheckAlreadyDownload())
  1246. {
  1247. Console.WriteLine($"已经将{ProgramName}下载到{Data.FilePath}!若要重新下载请先完成删除操作!");
  1248. }
  1249. else
  1250. {
  1251. string newpath;
  1252. Console.WriteLine("请输入下载路径:");
  1253. newpath = Console.ReadLine() ?? "";
  1254. Data.ResetFilepath(newpath);
  1255. DownloadAll();
  1256. }
  1257. }
  1258. else if (choose == "4")
  1259. {
  1260. DeleteAll();
  1261. }
  1262. else if (choose == "5")
  1263. {
  1264. if (CheckAlreadyDownload())
  1265. {
  1266. Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
  1267. }
  1268. else
  1269. {
  1270. Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
  1271. }
  1272. }
  1273. else if (choose == "6")
  1274. {
  1275. string newPath;
  1276. newPath = Console.ReadLine() ?? "";
  1277. MoveProgram(newPath);
  1278. }
  1279. else if (choose == "7")
  1280. {
  1281. Console.WriteLine("请输入email:");
  1282. string username = Console.ReadLine() ?? "";
  1283. Console.WriteLine("请输入密码:");
  1284. string password = Console.ReadLine() ?? "";
  1285. await web.LoginToEEsast(client, username, password);
  1286. }
  1287. else if (choose == "8")
  1288. {
  1289. await web.UserDetails(client);
  1290. }
  1291. else if (choose == "9")
  1292. {
  1293. await web.UploadFiles(client, "", "", "");
  1294. }
  1295. else if (choose == "exit")
  1296. {
  1297. return;
  1298. }
  1299. }
  1300. }
  1301. public static int CheckSelfVersion()
  1302. {
  1303. string keyHead = "Installer/";
  1304. Tencent_cos_download downloader = new Tencent_cos_download();
  1305. string hashName = "installerHash.json";
  1306. string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName)
  1307. ?? throw new Exception("Failed to get current directory");
  1308. int result = 0;
  1309. try
  1310. {
  1311. if (File.Exists(System.IO.Path.Combine(dir, hashName)))
  1312. File.Delete(System.IO.Path.Combine(dir, hashName));
  1313. downloader.download(System.IO.Path.Combine(dir, hashName), hashName);
  1314. }
  1315. catch
  1316. {
  1317. return -1;
  1318. }
  1319. string json;
  1320. using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, hashName)))
  1321. json = r.ReadToEnd();
  1322. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  1323. var jsonDict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
  1324. string md5 = "";
  1325. List<string> awaitUpdate = new List<string>();
  1326. if (jsonDict != null)
  1327. {
  1328. foreach (KeyValuePair<string, string> pair in jsonDict)
  1329. {
  1330. md5 = GetFileMd5Hash(System.IO.Path.Combine(dir, pair.Key));
  1331. if (md5.Length == 0) // 文档不存在
  1332. {
  1333. downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key);
  1334. }
  1335. else if (md5.Equals("conflict"))
  1336. {
  1337. MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
  1338. }
  1339. else if (md5 != pair.Value) // MD5不匹配
  1340. {
  1341. if (pair.Key.Substring(0, 12).Equals("InstallerUpd"))
  1342. {
  1343. File.Delete(System.IO.Path.Combine(dir, pair.Key));
  1344. downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key);
  1345. }
  1346. else
  1347. {
  1348. result = 1;
  1349. awaitUpdate = awaitUpdate.Append(pair.Key).ToList();
  1350. }
  1351. }
  1352. }
  1353. }
  1354. else
  1355. return -1;
  1356. string Contentjson = JsonConvert.SerializeObject(awaitUpdate);
  1357. Contentjson = Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/");
  1358. File.WriteAllText(@System.IO.Path.Combine(dir, "updateList.json"), Contentjson);
  1359. return result;
  1360. }
  1361. static public bool SelfUpdateDismissed()
  1362. {
  1363. string json;
  1364. string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName)
  1365. ?? throw new Exception("Failed to get directory!");
  1366. if (!File.Exists(System.IO.Path.Combine(dir, "updateList.json")))
  1367. return false;
  1368. using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, "updateList.json")))
  1369. json = r.ReadToEnd();
  1370. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  1371. List<string>? jsonList;
  1372. if (json != null)
  1373. jsonList = Utils.TryDeserializeJson<List<string>>(json);
  1374. else
  1375. return false;
  1376. if (jsonList != null && jsonList.Contains("Dismiss"))
  1377. {
  1378. listJsonClear(System.IO.Path.Combine(dir, "updateList.json"));
  1379. return true;
  1380. }
  1381. return false;
  1382. }
  1383. static private void listJsonClear(string directory)
  1384. {
  1385. List<string> list = new List<string>();
  1386. list.Add("None");
  1387. StreamWriter sw = new StreamWriter(directory, false);
  1388. sw.WriteLine(JsonConvert.SerializeObject(list));
  1389. sw.Close();
  1390. }
  1391. }
  1392. public class RunProgram
  1393. {
  1394. public static int StartServer()
  1395. {
  1396. Console.WriteLine("Input port: ");
  1397. string? port = Console.ReadLine();
  1398. if(port == null || port.Length == 0)
  1399. {
  1400. return 1;
  1401. }
  1402. Process process_cmd = new Process();
  1403. process_cmd.StartInfo.FileName = "cmd.exe";
  1404. process_cmd.StartInfo.RedirectStandardInput = true;//是否可以输入
  1405. process_cmd.StartInfo.RedirectStandardOutput = true;//是否可以输出
  1406. process_cmd.StartInfo.CreateNoWindow = false;//不创建窗体 也就是隐藏窗体
  1407. process_cmd.StartInfo.UseShellExecute = true;//是否使用系统shell执行,否
  1408. process_cmd.Start();
  1409. string command = Data.FilePath + "\\THUAI6\\win" + "\\win64\\Server.exe --port 8888 --studentCount 1 --trickerCount 1 --gameTimeInSecond 600 --fileName video";
  1410. process_cmd.StandardInput.WriteLine("你要执行的命令");
  1411. return -1;
  1412. }
  1413. }
  1414. }
  1415. }
  1416. namespace WebConnect
  1417. {
  1418. class Web
  1419. {
  1420. public enum language { cpp, py };
  1421. public static string logintoken = "";
  1422. async public Task<int> LoginToEEsast(HttpClient client, string useremail, string password)
  1423. {
  1424. string token = "";
  1425. try
  1426. {
  1427. using (var response = await client.PostAsync("https://api.eesast.com/users/login", JsonContent.Create(new
  1428. {
  1429. email = useremail,
  1430. password = password,
  1431. })))
  1432. {
  1433. switch (response.StatusCode)
  1434. {
  1435. case System.Net.HttpStatusCode.OK:
  1436. //Console.WriteLine("Success login");
  1437. token = (System.Text.Json.JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), typeof(LoginResponse), new JsonSerializerOptions()
  1438. {
  1439. PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
  1440. }) as LoginResponse)
  1441. ?.Token ??
  1442. throw new Exception("no token!");
  1443. logintoken = token;
  1444. SaveToken();
  1445. var info = Utils.DeserializeJson1<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
  1446. Downloader.UserInfo._id = info["_id"];
  1447. Downloader.UserInfo.email = info["email"];
  1448. break;
  1449. default:
  1450. int code = ((int)response.StatusCode);
  1451. //Console.WriteLine(code);
  1452. if (code == 401)
  1453. {
  1454. //Console.WriteLine("邮箱或密码错误!");
  1455. return -1;
  1456. }
  1457. break;
  1458. }
  1459. return 0;
  1460. }
  1461. }
  1462. catch
  1463. {
  1464. return -2;
  1465. }
  1466. }
  1467. /// <summary>
  1468. ///
  1469. /// </summary>
  1470. /// <param name="client">http client</param>
  1471. /// <param name="tarfile">代码源位置</param>
  1472. /// <param name="type">编程语言,格式为"cpp"或"python"</param>
  1473. /// <param name="plr">第x位玩家,格式为"player_x"</param>
  1474. /// <returns>-1:tokenFail;-2:FileNotExist;-3:CosFail;-4:loginTimeout;-5:Fail;-6:ReadFileFail;-7:networkError</returns>
  1475. async public Task<int> UploadFiles(HttpClient client, string tarfile, string type, string plr) //用来上传文件
  1476. {
  1477. if (!ReadToken()) //读取token失败
  1478. {
  1479. return -1;
  1480. }
  1481. try
  1482. {
  1483. string content;
  1484. client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken);
  1485. if (!File.Exists(tarfile))
  1486. {
  1487. //Console.WriteLine("文件不存在!");
  1488. return -2;
  1489. }
  1490. using FileStream fs = new FileStream(tarfile, FileMode.Open, FileAccess.Read);
  1491. using StreamReader sr = new StreamReader(fs);
  1492. content = sr.ReadToEnd();
  1493. string targetUrl = $"https://api.eesast.com/static/player?team_id={await GetTeamId()}";
  1494. using (var response = await client.GetAsync(targetUrl))
  1495. {
  1496. switch (response.StatusCode)
  1497. {
  1498. case System.Net.HttpStatusCode.OK:
  1499. var res = Utils.DeserializeJson1<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
  1500. string appid = "1255334966"; // 设置腾讯云账户的账户标识(APPID)
  1501. string region = "ap-beijing"; // 设置一个默认的存储桶地域
  1502. CosXmlConfig config = new CosXmlConfig.Builder()
  1503. .IsHttps(true) // 设置默认 HTTPS 请求
  1504. .SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
  1505. .SetRegion(region) // 设置一个默认的存储桶地域
  1506. .SetDebugLog(true) // 显示日志
  1507. .Build(); // 创建 CosXmlConfig 对象
  1508. string tmpSecretId = res["TmpSecretId"]; //"临时密钥 SecretId";
  1509. string tmpSecretKey = res["TmpSecretKey"]; //"临时密钥 SecretKey";
  1510. string tmpToken = res["SecurityToken"]; //"临时密钥 token";
  1511. long tmpExpiredTime = Convert.ToInt64(res["ExpiredTime"]); //临时密钥有效截止时间,精确到秒
  1512. QCloudCredentialProvider cosCredentialProvider = new DefaultSessionQCloudCredentialProvider(
  1513. tmpSecretId, tmpSecretKey, tmpExpiredTime, tmpToken
  1514. );
  1515. // 初始化 CosXmlServer
  1516. CosXmlServer cosXml = new CosXmlServer(config, cosCredentialProvider);
  1517. // 初始化 TransferConfig
  1518. TransferConfig transferConfig = new TransferConfig();
  1519. // 初始化 TransferManager
  1520. TransferManager transferManager = new TransferManager(cosXml, transferConfig);
  1521. string bucket = "eesast-1255334966"; //存储桶,格式:BucketName-APPID
  1522. string cosPath = $"/THUAI6/{GetTeamId()}/{type}/{plr}"; //对象在存储桶中的位置标识符,即称对象键
  1523. string srcPath = tarfile;//本地文件绝对路径
  1524. // 上传对象
  1525. COSXMLUploadTask uploadTask = new COSXMLUploadTask(bucket, cosPath);
  1526. uploadTask.SetSrcPath(srcPath);
  1527. uploadTask.progressCallback = delegate (long completed, long total)
  1528. {
  1529. //Console.WriteLine(string.Format("progress = {0:##.##}%", completed * 100.0 / total));
  1530. };
  1531. try
  1532. {
  1533. COSXMLUploadTask.UploadTaskResult result = await transferManager.UploadAsync(uploadTask);
  1534. //Console.WriteLine(result.GetResultInfo());
  1535. string eTag = result.eTag;
  1536. //到这里应该是成功了,但是因为我没有试过,也不知道具体情况,可能还要根据result的内容判断
  1537. }
  1538. catch (Exception)
  1539. {
  1540. return -3;
  1541. }
  1542. break;
  1543. case System.Net.HttpStatusCode.Unauthorized:
  1544. //Console.WriteLine("您未登录或登录过期,请先登录");
  1545. return -4;
  1546. default:
  1547. //Console.WriteLine("上传失败!");
  1548. return -5;
  1549. }
  1550. }
  1551. }
  1552. catch (IOException)
  1553. {
  1554. //Console.WriteLine("文件读取错误!请检查文件是否被其它应用占用!");
  1555. return -6;
  1556. }
  1557. catch
  1558. {
  1559. //Console.WriteLine("请求错误!请检查网络连接!");
  1560. return -7;
  1561. }
  1562. return 0;
  1563. }
  1564. async public Task UserDetails(HttpClient client) // 用来测试访问网站
  1565. {
  1566. if (!ReadToken()) // 读取token失败
  1567. {
  1568. return;
  1569. }
  1570. try
  1571. {
  1572. client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken);
  1573. Console.WriteLine(logintoken);
  1574. using (var response = await client.GetAsync("https://api.eesast.com/application/info")) // JsonContent.Create(new
  1575. //{
  1576. //})))
  1577. {
  1578. switch (response.StatusCode)
  1579. {
  1580. case System.Net.HttpStatusCode.OK:
  1581. Console.WriteLine("Require OK");
  1582. Console.WriteLine(await response.Content.ReadAsStringAsync());
  1583. break;
  1584. default:
  1585. int code = ((int)response.StatusCode);
  1586. if (code == 401)
  1587. {
  1588. Console.WriteLine("您未登录或登录过期,请先登录");
  1589. }
  1590. return;
  1591. }
  1592. }
  1593. }
  1594. catch
  1595. {
  1596. Console.WriteLine("请求错误!请检查网络连接!");
  1597. }
  1598. }
  1599. public void SaveToken() // 保存token
  1600. {
  1601. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1602. try
  1603. {
  1604. string json;
  1605. Dictionary<string, string> dict = new Dictionary<string, string>();
  1606. using FileStream fs = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
  1607. using (StreamReader r = new StreamReader(fs))
  1608. {
  1609. json = r.ReadToEnd();
  1610. if (json == null || json == "")
  1611. {
  1612. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1613. }
  1614. dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
  1615. if (dict.ContainsKey("token"))
  1616. {
  1617. dict.Remove("token");
  1618. }
  1619. dict.Add("token", logintoken);
  1620. }
  1621. using FileStream fs2 = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
  1622. using StreamWriter sw = new StreamWriter(fs2);
  1623. fs2.SetLength(0);
  1624. sw.Write(JsonConvert.SerializeObject(dict)); //将token写入文件
  1625. }
  1626. catch (DirectoryNotFoundException)
  1627. {
  1628. Console.WriteLine("保存token时未找到下载器地址!请检查下载器是否被移动!");
  1629. }
  1630. catch (PathTooLongException)
  1631. {
  1632. Console.WriteLine("下载器的路径名太长!请尝试移动下载器!");
  1633. }
  1634. catch (ArgumentNullException)
  1635. {
  1636. Console.WriteLine("下载器路径初始化失败!");
  1637. }
  1638. catch (IOException)
  1639. {
  1640. Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!");
  1641. }
  1642. }
  1643. public static int WriteJson(string key, string data)
  1644. {
  1645. try
  1646. {
  1647. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1648. FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite);
  1649. StreamReader sr = new StreamReader(fs);
  1650. string json = sr.ReadToEnd();
  1651. if (json == null || json == "")
  1652. {
  1653. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1654. }
  1655. Dictionary<string, string> dict = new Dictionary<string, string>();
  1656. dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
  1657. if (!dict.ContainsKey(key))
  1658. {
  1659. dict.Add(key, data);
  1660. }
  1661. else
  1662. {
  1663. dict[key] = data;
  1664. }
  1665. sr.Close();
  1666. fs.Close();
  1667. FileStream fs2 = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite);
  1668. StreamWriter sw = new StreamWriter(fs2);
  1669. sw.WriteLine(JsonConvert.SerializeObject(dict));
  1670. sw.Close();
  1671. fs2.Close();
  1672. return 0;//成功
  1673. }
  1674. catch
  1675. {
  1676. return -1;//失败
  1677. }
  1678. }
  1679. public static string? ReadJson(string key)
  1680. {
  1681. try
  1682. {
  1683. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1684. FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read);
  1685. StreamReader sr = new StreamReader(fs);
  1686. string json = sr.ReadToEnd();
  1687. Dictionary<string, string> dict = new Dictionary<string, string>();
  1688. if (json == null || json == "")
  1689. {
  1690. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1691. }
  1692. dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
  1693. fs.Close();
  1694. sr.Close();
  1695. return dict[key];
  1696. }
  1697. catch
  1698. {
  1699. return null; //文件不存在或者已被占用
  1700. }
  1701. }
  1702. public bool ReadToken() // 读取token
  1703. {
  1704. try
  1705. {
  1706. string json;
  1707. Dictionary<string, string> dict = new Dictionary<string, string>();
  1708. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1709. using FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read);
  1710. using StreamReader sr = new StreamReader(fs);
  1711. json = sr.ReadToEnd();
  1712. if (json == null || json == "")
  1713. {
  1714. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1715. }
  1716. dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
  1717. if (!dict.ContainsKey("token"))
  1718. {
  1719. return false;
  1720. }
  1721. else
  1722. {
  1723. logintoken = dict["token"];
  1724. return true;
  1725. }
  1726. }
  1727. catch (DirectoryNotFoundException)
  1728. {
  1729. Console.WriteLine("读取token时未找到下载器地址!请检查下载器是否被移动!");
  1730. return false;
  1731. }
  1732. catch (FileNotFoundException)
  1733. {
  1734. //没有登陆
  1735. Console.WriteLine("请先登录!");
  1736. return false;
  1737. }
  1738. catch (PathTooLongException)
  1739. {
  1740. Console.WriteLine("下载器的路径名太长!请尝试移动下载器!");
  1741. return false;
  1742. }
  1743. catch (ArgumentNullException)
  1744. {
  1745. Console.WriteLine("下载器路径初始化失败!");
  1746. return false;
  1747. }
  1748. catch (IOException)
  1749. {
  1750. Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!");
  1751. return false;
  1752. }
  1753. }
  1754. async public Task<string> GetTeamId()
  1755. {
  1756. var client = new HttpClient();
  1757. var request = new HttpRequestMessage(HttpMethod.Post, "https://api.eesast.com/dev/v1/graphql");
  1758. request.Headers.Add("x-hasura-admin-secret", "hasuraDevAdminSecret");
  1759. //var content = new StringContent($@"
  1760. // {{
  1761. // ""query"": ""query MyQuery {{contest_team_member(where: {{user_id: {{_eq: \""{Downloader.UserInfo._id}\""}}}}) {{ team_id }}}}"",
  1762. // ""variables"": {{}},
  1763. // }}", null, "application/json");
  1764. 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");
  1765. request.Content = content;
  1766. var response = await client.SendAsync(request);
  1767. response.EnsureSuccessStatusCode();
  1768. var info = await response.Content.ReadAsStringAsync();
  1769. var s1 = Utils.DeserializeJson1<Dictionary<string, object>>(info)["data"];
  1770. var s2 = Utils.DeserializeJson1<Dictionary<string, List<object>>>(s1.ToString() ?? "")["contest_team_member"];
  1771. var sres = Utils.DeserializeJson1<Dictionary<string, string>>(s2[0].ToString() ?? "")["team_id"];
  1772. return sres;
  1773. }
  1774. async public Task<string> GetUserId(string learnNumber)
  1775. {
  1776. var client = new HttpClient();
  1777. var request = new HttpRequestMessage(HttpMethod.Post, "https://api.eesast.com/dev/v1/graphql");
  1778. request.Headers.Add("x-hasura-admin-secret", "hasuraDevAdminSecret");
  1779. var content = new StringContent("{\"query\":\"query MyQuery {\r\n user(where: {id: {_eq: \""
  1780. + learnNumber + "\"}}) {\r\n _id\r\n }\r\n}\r\n\",\"variables\":{}}", null, "application/json");
  1781. request.Content = content;
  1782. var response = await client.SendAsync(request);
  1783. response.EnsureSuccessStatusCode();
  1784. return await response.Content.ReadAsStringAsync();
  1785. }
  1786. }
  1787. [Serializable]
  1788. record LoginResponse
  1789. {
  1790. // Map `Token` to `token` when serializing
  1791. public string Token { get; set; } = "";
  1792. }
  1793. internal static class Utils
  1794. {
  1795. public static T DeserializeJson1<T>(string json)
  1796. where T : notnull
  1797. {
  1798. return JsonConvert.DeserializeObject<T>(json)
  1799. ?? throw new Exception("Failed to deserialize json.");
  1800. }
  1801. public static T? TryDeserializeJson<T>(string json)
  1802. where T : notnull
  1803. {
  1804. return JsonConvert.DeserializeObject<T>(json);
  1805. }
  1806. }
  1807. }