diff --git a/dependency/algorithm/README.md b/dependency/algorithm/README.md index fe9624e..1ea7788 100644 --- a/dependency/algorithm/README.md +++ b/dependency/algorithm/README.md @@ -247,6 +247,8 @@ int main() ## THUAI6 +### high-ladder + 因为今年的对局得分是两局得分之和,所以会出现一定程度的“数值膨胀”,在这里调低了胜者得分权值,同时提高了比赛分差距悬殊阈值和天梯分差距悬殊阈值。同时由于今年得分的上限不好确定,所以负者失分的基础值变为与胜者的得分之差。 ```c++ @@ -330,3 +332,126 @@ mypair cal(mypair orgScore, mypair competitionScore) } ``` +### competition + +与天梯得分算法要满足的“枫氏七条”类似,比赛得分算法也要满足“唐氏四律”,分别如下: + +1. 两队经过某场比赛的得分变化,应只与该场比赛有关,而与历史积分无关。 +2. 须赋予比赛获胜一方基础得分,哪怕获胜一方的优势非常小。也就是说,哪怕胜利一方仅以微弱优势获胜,也需要拉开胜者与败者的分差。 +3. 胜利一方优势越大,得分理应越高。 +4. 对于一场比赛,胜利一方的得分不能无限大,须控制在一个合理的数值以下。 + +- 在非平局的情况下,(胜者)天梯得分与双方比赛分差值成正相关,得分函数如下(以x表示得分差值,y表示(胜者)天梯得分,a、b为固定参数) + +​ $$y=ax^2(1-0.375\cdot(\tanh(\frac{x}{b}-1)+1))$$ + +- 在平局情况下,(双方)天梯得分与比赛分成正相关,得分函数如下(以x表示比赛分,y表示(双方)天梯得分,c为固定参数) + +​ $$y=cx^2$$ + +- 不管是哪种情况,都有得分下界,非平局为100,平局为25 + +```c++ +#include +#include +#include +#include +using namespace std; + +template +using mypair = pair; +double minScore = 100; + +double TieScore(double gameScore) +{ + const double get = 9e-5; // 天梯得分权值 + double deltaScore = 2000.0; // 订正的幅度,该值越小,则在双方分差较大时,天梯分数改变量越小,整个函数的变化范围大约为0~2*deltaScore + double highScore = 6000.0; // 将highScore设定为较大值,使得correct较小 + double correct = 1 - 0.375 * (tanh((highScore - deltaScore) / deltaScore) + 1.0); // 一场比赛中,在双方分差较大时,减小天梯分数的改变量 + cout << "correct: " << correct << endl; + int score = round(gameScore * gameScore * get * correct / 4); + return score > minScore / 4 ? score : minScore / 4; +} + +double WinScore(double delta, double winnerGameScore) // 根据游戏得分差值,与绝对分数,决定最后的加分 +{ + assert(delta > 0); + const double firstnerGet = 9e-5; // 胜利者天梯得分权值 + double deltaScore = 2000.0; // 订正的幅度,该值越小,则在双方分差较大时,天梯分数改变量越小,整个函数的变化范围大约为0~2*deltaScore + double correct = 1 - 0.375 * (tanh((delta - deltaScore) / deltaScore) + 1.0); // 一场比赛中,在双方分差较大时,减小天梯分数的改变量 + cout << "correct: " << correct << endl; + int score = round(delta * delta * firstnerGet * correct); + return score > minScore ? score : minScore; +} + +// orgScore 是天梯中两队的分数;competitionScore 是这次游戏两队的得分 +mypair cal(mypair orgScore, mypair competitionScore) +{ + // 调整顺序,让第一个元素成为获胜者,便于计算 + + bool reverse = false; // 记录是否需要调整 + + if (competitionScore.first < competitionScore.second) + { + reverse = true; + } + + if (reverse) // 如果需要换,换两者的顺序 + { + swap(competitionScore.first, competitionScore.second); + swap(orgScore.first, orgScore.second); + } + + double delta = competitionScore.first - competitionScore.second; + double addScore; + mypair resScore; + + // 先处理平局的情况 + if (delta == 0) + { + addScore = TieScore(competitionScore.first); + resScore = mypair(orgScore.first + addScore, orgScore.second + addScore); + } + + // 再处理有胜负的情况 + else + { + addScore = WinScore(delta, competitionScore.first); + resScore = mypair(orgScore.first + addScore, orgScore.second); + } + + // 如果换过,再换回来 + if (reverse) + { + swap(resScore.first, resScore.second); + } + + return resScore; +} + +void Print(mypair score) +{ + std::cout << "team1: " << score.first << std::endl + << "team2: " << score.second << std::endl; +} + +int main() +{ + double x, y, t, i = 0; + cin >> t; + while (i < t) + { + cout << "----------------------------------------\n"; + std::cout << "origin score of team 1 and 2: " << std::endl; + std::cin >> x >> y; + auto ori = mypair(x, y); + std::cout << "game score of team 1 and 2: " << std::endl; + std::cin >> x >> y; + auto sco = mypair(x, y); + Print(cal(ori, sco)); + ++i; + } + return 0; +} +``` + diff --git a/installer/Installer/Common.cs b/installer/Installer/Common.cs index 0f3697d..d38059f 100644 --- a/installer/Installer/Common.cs +++ b/installer/Installer/Common.cs @@ -10,7 +10,7 @@ namespace starter.viewmodel.common { public abstract class NotificationObject : INotifyPropertyChanged { - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; ///< summary> /// announce notification /// @@ -25,21 +25,21 @@ namespace starter.viewmodel.common /// public class BaseCommand : ICommand { - private Func _canExecute; - private Action _execute; + private Func? _canExecute; + private Action _execute; - public BaseCommand(Func canExecute, Action execute) + public BaseCommand(Func? canExecute, Action execute) { _canExecute = canExecute; _execute = execute; } - public BaseCommand(Action execute) : + public BaseCommand(Action execute) : this(null, execute) { } - public event EventHandler CanExecuteChanged + public event EventHandler? CanExecuteChanged { add { @@ -57,12 +57,12 @@ namespace starter.viewmodel.common } } - public bool CanExecute(object parameter) + public bool CanExecute(object? parameter) { return _canExecute == null ? true : _canExecute(parameter); } - public void Execute(object parameter) + public void Execute(object? parameter) { if (_execute != null && CanExecute(parameter)) { @@ -79,15 +79,15 @@ namespace starter.viewmodel.common { return false; } - string checkvalue = value.ToString(); - string targetvalue = parameter.ToString(); + string checkvalue = value.ToString() ?? ""; + string targetvalue = parameter.ToString() ?? ""; bool r = checkvalue.Equals(targetvalue); return r; } - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { - if (value == null || parameter == null) + if (value is null || parameter is null) { return null; } @@ -132,22 +132,22 @@ namespace starter.viewmodel.common static bool _isUpdating = false; private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - PasswordBox pb = d as PasswordBox; + PasswordBox pb = (d as PasswordBox)!; pb.PasswordChanged -= Pb_PasswordChanged; if (!_isUpdating) - (d as PasswordBox).Password = e.NewValue.ToString(); + (d as PasswordBox)!.Password = e.NewValue.ToString(); pb.PasswordChanged += Pb_PasswordChanged; } private static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - PasswordBox pb = d as PasswordBox; + PasswordBox pb = (d as PasswordBox)!; pb.PasswordChanged += Pb_PasswordChanged; } private static void Pb_PasswordChanged(object sender, RoutedEventArgs e) { - PasswordBox pb = sender as PasswordBox; + PasswordBox pb = (sender as PasswordBox)!; _isUpdating = true; SetPassword(pb, pb.Password); _isUpdating = false; diff --git a/installer/Installer/MainWindow.xaml b/installer/Installer/MainWindow.xaml index c29b75d..85f52ab 100644 --- a/installer/Installer/MainWindow.xaml +++ b/installer/Installer/MainWindow.xaml @@ -5,7 +5,9 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Installer" xmlns:c="clr-namespace:starter.viewmodel.common" mc:Ignorable="d" - Title="Installer" Window.SizeToContent="WidthAndHeight"> + Title="Installer" Window.SizeToContent="WidthAndHeight" + ResizeMode="CanMinimize" + > diff --git a/installer/Installer/Model.cs b/installer/Installer/Model.cs index f9bea79..552c8cd 100644 --- a/installer/Installer/Model.cs +++ b/installer/Installer/Model.cs @@ -21,7 +21,6 @@ using System.Net.Http; using System.Windows; using System.Windows.Shapes; //using System.Windows.Forms; -using System.Threading.Tasks; using System.Threading; using MessageBox = System.Windows.MessageBox; @@ -153,18 +152,22 @@ namespace starter.viewmodel.settings } public bool RecallUser() { - Username = Web.ReadJson("email"); - if (Username == null || Username.Equals("")) + var username = Web.ReadJson("email"); + if (username == null || username.Equals("")) { Username = ""; return false; } - Password = Web.ReadJson("password"); - if (Password == null || Username.Equals("")) + Username = username; + + var password = Web.ReadJson("password"); + if (password == null || password.Equals("")) { Password = ""; return false; } + Password = password; + return true; } public bool ForgetUser() @@ -210,8 +213,6 @@ namespace starter.viewmodel.settings switch (CodeRoute.Substring(CodeRoute.LastIndexOf('.') + 1)) { case "cpp": - Language = "cpp"; - break; case "h": Language = "cpp"; break; @@ -244,15 +245,12 @@ namespace starter.viewmodel.settings } public UsingOS ReadUsingOS() { - string OS = Web.ReadJson("OS"); - if (OS == null) - return UsingOS.Win; - else if (OS.Equals("linux")) - return UsingOS.Linux; - else if (OS.Equals("osx")) - return UsingOS.OSX; - else - return UsingOS.Win; + return Web.ReadJson("OS") switch + { + "linux" => UsingOS.Linux, + "osx" => UsingOS.OSX, + _ => UsingOS.Win, + }; } /// /// Route of files @@ -274,7 +272,7 @@ namespace starter.viewmodel.settings { get; set; } - public string Language + public string? Language { get; set; } @@ -411,7 +409,7 @@ namespace Downloader { json += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json); + dict = Utils.DeserializeJson>(json); if (dict != null && dict.ContainsKey("installpath")) { FilePath = dict["installpath"].Replace('\\', '/'); @@ -425,11 +423,12 @@ namespace Downloader } else { - FilePath = System.IO.Path.GetDirectoryName(@path); + FilePath = System.IO.Path.GetDirectoryName(@path) + ?? throw new Exception("Fail to find the path of the file"); //将dat文件写入程序运行路径 string json; - Dictionary dict = new Dictionary(); + Dictionary? dict; using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite); using (StreamReader r = new StreamReader(fs)) { @@ -438,7 +437,7 @@ namespace Downloader { json += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json); + dict = Utils.DeserializeJson>(json); dict?.Add("installpath", path); } using FileStream fs2 = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite); @@ -451,7 +450,7 @@ namespace Downloader public static void ResetFilepath(string newPath) { string json; - Dictionary dict = new Dictionary(); + Dictionary? dict; FilePath = newPath.Replace('\\', '/'); path = System.IO.Path.Combine(dataPath, "THUAI6.json"); using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite); @@ -462,14 +461,14 @@ namespace Downloader { json += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json); + dict = Utils.DeserializeJson>(json); if (dict != null && dict.ContainsKey("installpath")) { dict["installpath"] = newPath; } else { - dict.Add("installpath", newPath); + dict?.Add("installpath", newPath); } if (dict == null || !dict.ContainsKey("download")) { @@ -517,9 +516,10 @@ namespace Downloader // 创建存储桶 try { - string bucket = "thuai6-1314234950"; // 格式:BucketName-APPID - string localDir = System.IO.Path.GetDirectoryName(download_dir); // 本地文件夹 - string localFileName = System.IO.Path.GetFileName(download_dir); // 指定本地保存的文件名 + 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(); @@ -553,7 +553,7 @@ namespace Downloader public static string GetFileMd5Hash(string strFileFullPath) { - FileStream fst = null; + FileStream? fst = null; try { fst = new FileStream(strFileFullPath, FileMode.Open, FileAccess.Read); @@ -634,7 +634,7 @@ namespace Downloader 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); - Dictionary jsonDict = JsonConvert.DeserializeObject>(json); + Dictionary jsonDict = Utils.DeserializeJson>(json); string updatingFolder = ""; switch (OS) { @@ -815,7 +815,7 @@ namespace Downloader { json += @"{""THUAI6""" + ":" + @"""2023""}"; } - var dict = JsonConvert.DeserializeObject>(json); + var dict = Utils.DeserializeJson>(json); if (dict == null || !dict.ContainsKey("download") || "false" == dict["download"]) { return false; @@ -865,15 +865,15 @@ namespace Downloader 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); - Dictionary jsonDict = JsonConvert.DeserializeObject>(json); + Dictionary jsonDict = Utils.DeserializeJson>(json); newFileName.Clear(); updateFileName.Clear(); newFileName.Add("THUAI6.tar.gz"); Download(); - Stream inStream = null; - Stream gzipStream = null; - TarArchive tarArchive = null; + Stream? inStream = null; + Stream? gzipStream = null; + TarArchive? tarArchive = null; try { using (inStream = File.OpenRead(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz"))) @@ -886,7 +886,7 @@ namespace Downloader } } } - catch (Exception ex) + catch { //出错 } @@ -909,7 +909,7 @@ namespace Downloader { json2 += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json2); + dict = Utils.DeserializeJson>(json2); if (dict == null || !dict.ContainsKey("download")) { dict?.Add("download", "true"); @@ -1000,7 +1000,7 @@ namespace Downloader 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 = JsonConvert.DeserializeObject>(json); + Dictionary jsonDict = Utils.DeserializeJson>(json); Change_all_hash(Data.FilePath, jsonDict); OverwriteHash(jsonDict); break; @@ -1008,7 +1008,7 @@ namespace Downloader else { Console.WriteLine("读取路径失败!请重新输入文件路径:"); - Data.ResetFilepath(Console.ReadLine()); + Data.ResetFilepath(Console.ReadLine() ?? ""); } } } @@ -1068,7 +1068,7 @@ namespace Downloader { json2 += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json2); + dict = Utils.DeserializeJson>(json2); if (dict == null || !dict.ContainsKey("download")) { dict?.Add("download", "false"); @@ -1189,7 +1189,7 @@ namespace Downloader while (true) { Console.WriteLine($"1. 更新hash.json 2. 检查更新 3.下载{ProgramName} 4.删除{ProgramName} 5.启动进程 6.移动{ProgramName}到其它路径"); - string choose = Console.ReadLine(); + string choose = Console.ReadLine() ?? ""; if (choose == "1") { if (!CheckAlreadyDownload()) @@ -1216,7 +1216,7 @@ namespace Downloader else { Console.WriteLine("读取路径失败!请重新输入文件路径:"); - Data.ResetFilepath(Console.ReadLine()); + Data.ResetFilepath(Console.ReadLine() ?? ""); } } } @@ -1230,7 +1230,7 @@ namespace Downloader { string newpath; Console.WriteLine("请输入下载路径:"); - newpath = Console.ReadLine(); + newpath = Console.ReadLine() ?? ""; Data.ResetFilepath(newpath); DownloadAll(); } @@ -1253,15 +1253,15 @@ namespace Downloader else if (choose == "6") { string newPath; - newPath = Console.ReadLine(); + newPath = Console.ReadLine() ?? ""; MoveProgram(newPath); } else if (choose == "7") { Console.WriteLine("请输入email:"); - string username = Console.ReadLine(); + string username = Console.ReadLine() ?? ""; Console.WriteLine("请输入密码:"); - string password = Console.ReadLine(); + string password = Console.ReadLine() ?? ""; await web.LoginToEEsast(client, username, password); } @@ -1285,7 +1285,8 @@ namespace Downloader 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); + string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName) + ?? throw new Exception("Failed to get current directory"); int result = 0; try { @@ -1301,7 +1302,7 @@ namespace Downloader using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, hashName))) json = r.ReadToEnd(); json = json.Replace("\r", string.Empty).Replace("\n", string.Empty); - Dictionary jsonDict = JsonConvert.DeserializeObject>(json); + Dictionary jsonDict = Utils.DeserializeJson>(json); string md5 = ""; List awaitUpdate = new List(); if (jsonDict != null) @@ -1343,7 +1344,8 @@ namespace Downloader static public bool SelfUpdateDismissed() { string json; - string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); + 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"))) @@ -1351,7 +1353,7 @@ namespace Downloader json = json.Replace("\r", string.Empty).Replace("\n", string.Empty); List jsonList; if (json != null) - jsonList = JsonConvert.DeserializeObject>(json); + jsonList = Utils.DeserializeJson>(json); else return false; if (jsonList != null && jsonList.Contains("Dismiss")) @@ -1403,7 +1405,7 @@ namespace WebConnect throw new Exception("no token!"); logintoken = token; SaveToken(); - var info = JsonConvert.DeserializeObject>(await response.Content.ReadAsStringAsync()); + var info = Utils.DeserializeJson>(await response.Content.ReadAsStringAsync()); Downloader.UserInfo._id = info["_id"]; Downloader.UserInfo.email = info["email"]; break; @@ -1459,7 +1461,7 @@ namespace WebConnect { case System.Net.HttpStatusCode.OK: - var res = JsonConvert.DeserializeObject>(await response.Content.ReadAsStringAsync()); + var res = Utils.DeserializeJson>(await response.Content.ReadAsStringAsync()); string appid = "1255334966"; // 设置腾讯云账户的账户标识(APPID) string region = "ap-beijing"; // 设置一个默认的存储桶地域 CosXmlConfig config = new CosXmlConfig.Builder() @@ -1584,12 +1586,12 @@ namespace WebConnect { json += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json); + dict = Utils.DeserializeJson>(json); if (dict.ContainsKey("token")) { dict.Remove("token"); } - dict?.Add("token", logintoken); + dict.Add("token", logintoken); } using FileStream fs2 = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite); using StreamWriter sw = new StreamWriter(fs2); @@ -1627,7 +1629,7 @@ namespace WebConnect json += @"{""THUAI6""" + ":" + @"""2023""}"; } Dictionary dict = new Dictionary(); - dict = JsonConvert.DeserializeObject>(json); + dict = Utils.DeserializeJson>(json); if (!dict.ContainsKey(key)) { dict.Add(key, data); @@ -1651,7 +1653,7 @@ namespace WebConnect } } - public static string ReadJson(string key) + public static string? ReadJson(string key) { try { @@ -1664,7 +1666,7 @@ namespace WebConnect { json += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json); + dict = Utils.DeserializeJson>(json); fs.Close(); sr.Close(); return dict[key]; @@ -1691,7 +1693,7 @@ namespace WebConnect { json += @"{""THUAI6""" + ":" + @"""2023""}"; } - dict = JsonConvert.DeserializeObject>(json); + dict = Utils.DeserializeJson>(json); if (!dict.ContainsKey("token")) { return false; @@ -1745,9 +1747,9 @@ namespace WebConnect var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); var info = await response.Content.ReadAsStringAsync(); - var s1 = JsonConvert.DeserializeObject>(info)["data"]; - var s2 = JsonConvert.DeserializeObject>>(s1.ToString())["contest_team_member"]; - var sres = JsonConvert.DeserializeObject>(s2[0].ToString())["team_id"]; + var s1 = Utils.DeserializeJson>(info)["data"]; + var s2 = Utils.DeserializeJson>>(s1.ToString() ?? "")["contest_team_member"]; + var sres = Utils.DeserializeJson>(s2[0].ToString() ?? "")["team_id"]; return sres; } async public Task GetUserId(string learnNumber) @@ -1773,4 +1775,13 @@ namespace WebConnect public string Token { get; set; } = ""; } + internal static class Utils + { + public static T DeserializeJson(string json) + { + return JsonConvert.DeserializeObject(json) + ?? throw new Exception("Failed to deserialize json."); + } + } + } diff --git a/installer/Installer/ViewModel.cs b/installer/Installer/ViewModel.cs index ca84add..742fbb1 100644 --- a/installer/Installer/ViewModel.cs +++ b/installer/Installer/ViewModel.cs @@ -36,14 +36,15 @@ namespace starter.viewmodel.settings //Program.Tencent_cos_download.UpdateHash(); Status = SettingsModel.Status.working; - string CurrentDirectory = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); + string currentDirectory = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName) + ?? throw new Exception("Fail to get current directory"); //MessageBox.Show("更新器工作正常"); if (!Program.Tencent_cos_download.SelfUpdateDismissed()) { switch (Program.Tencent_cos_download.CheckSelfVersion()) { case 1: - Process.Start(System.IO.Path.Combine(CurrentDirectory, "InstallerUpdater.exe")); + Process.Start(System.IO.Path.Combine(currentDirectory, "InstallerUpdater.exe")); Environment.Exit(0); break; case -1: @@ -156,7 +157,7 @@ namespace starter.viewmodel.settings { e.Cancel = true; MessageBox.Show("下载取消"); - if (e.Argument.ToString().Equals("Manual")) + if (e.Argument?.ToString()?.Equals("Manual") ?? false) { Status = SettingsModel.Status.menu; } @@ -167,7 +168,7 @@ namespace starter.viewmodel.settings else { if (obj.Update()) - if (e.Argument.ToString().Equals("Manual")) + if (e.Argument?.ToString()?.Equals("Manual") ?? false) { e.Result = 1; } @@ -598,14 +599,14 @@ namespace starter.viewmodel.settings return ""; } - private BaseCommand clickBrowseCommand; + private BaseCommand? clickBrowseCommand; public BaseCommand ClickBrowseCommand { get { if (clickBrowseCommand == null) { - clickBrowseCommand = new BaseCommand(new Action(o => + clickBrowseCommand = new BaseCommand(new Action(o => { Route = RouteSelectWindow("Folder"); })); @@ -613,14 +614,14 @@ namespace starter.viewmodel.settings return clickBrowseCommand; } } - private BaseCommand clickConfirmCommand; + private BaseCommand? clickConfirmCommand; public BaseCommand ClickConfirmCommand { get { if (clickConfirmCommand == null) { - clickConfirmCommand = new BaseCommand(new Action(o => + clickConfirmCommand = new BaseCommand(new Action(o => { if (Status == SettingsModel.Status.newUser) { @@ -672,14 +673,14 @@ namespace starter.viewmodel.settings return clickConfirmCommand; } } - private BaseCommand clickUpdateCommand; + private BaseCommand? clickUpdateCommand; public BaseCommand ClickUpdateCommand { get { if (clickUpdateCommand == null) { - clickUpdateCommand = new BaseCommand(new Action(o => + clickUpdateCommand = new BaseCommand(new Action(o => { this.RaisePropertyChanged("UpdateInfoVis"); if (obj.UpdatePlanned) @@ -719,14 +720,14 @@ namespace starter.viewmodel.settings return clickUpdateCommand; } } - private BaseCommand clickMoveCommand; + private BaseCommand? clickMoveCommand; public BaseCommand ClickMoveCommand { get { if (clickMoveCommand == null) { - clickMoveCommand = new BaseCommand(new Action(o => + clickMoveCommand = new BaseCommand(new Action(o => { Status = SettingsModel.Status.move; })); @@ -734,14 +735,14 @@ namespace starter.viewmodel.settings return clickMoveCommand; } } - private BaseCommand clickUninstCommand; + private BaseCommand? clickUninstCommand; public BaseCommand ClickUninstCommand { get { if (clickUninstCommand == null) { - clickUninstCommand = new BaseCommand(new Action(o => + clickUninstCommand = new BaseCommand(new Action(o => { UpdateInfoVis = Visibility.Collapsed; this.RaisePropertyChanged("UpdateInfoVis"); @@ -767,14 +768,14 @@ namespace starter.viewmodel.settings } } - private BaseCommand clickLoginCommand; + private BaseCommand? clickLoginCommand; public BaseCommand ClickLoginCommand { get { if (clickLoginCommand == null) { - clickLoginCommand = new BaseCommand(new Action(async o => + clickLoginCommand = new BaseCommand(new Action(async o => { switch (await obj.Login()) { @@ -813,14 +814,14 @@ namespace starter.viewmodel.settings } } - private BaseCommand clickLaunchCommand; + private BaseCommand? clickLaunchCommand; public BaseCommand ClickLaunchCommand { get { if (clickLaunchCommand == null) { - clickLaunchCommand = new BaseCommand(new Action(o => + clickLaunchCommand = new BaseCommand(new Action(o => { if (obj.UpdatePlanned) { @@ -840,14 +841,14 @@ namespace starter.viewmodel.settings return clickLaunchCommand; } } - private BaseCommand clickEditCommand; + private BaseCommand? clickEditCommand; public BaseCommand ClickEditCommand { get { if (clickEditCommand == null) { - clickEditCommand = new BaseCommand(new Action(o => + clickEditCommand = new BaseCommand(new Action(o => { Status = SettingsModel.Status.menu; if (obj.UpdatePlanned) @@ -858,14 +859,14 @@ namespace starter.viewmodel.settings return clickEditCommand; } } - private BaseCommand clickBackCommand; + private BaseCommand? clickBackCommand; public BaseCommand ClickBackCommand { get { if (clickBackCommand == null) { - clickBackCommand = new BaseCommand(new Action(o => + clickBackCommand = new BaseCommand(new Action(o => { UpdateInfoVis = Visibility.Collapsed; this.RaisePropertyChanged("UpdateInfoVis"); @@ -878,14 +879,14 @@ namespace starter.viewmodel.settings return clickBackCommand; } } - private BaseCommand clickUploadCommand; + private BaseCommand? clickUploadCommand; public BaseCommand ClickUploadCommand { get { if (clickUploadCommand == null) { - clickUploadCommand = new BaseCommand(new Action(async o => + clickUploadCommand = new BaseCommand(new Action(async o => { if (obj.UploadReady) { @@ -953,14 +954,14 @@ namespace starter.viewmodel.settings return clickUploadCommand; } } - private BaseCommand clickAboutUploadCommand; + private BaseCommand? clickAboutUploadCommand; public BaseCommand ClickAboutUploadCommand { get { if (clickAboutUploadCommand == null) { - clickAboutUploadCommand = new BaseCommand(new Action(o => + clickAboutUploadCommand = new BaseCommand(new Action(o => { if (obj.UploadReady) { @@ -987,14 +988,14 @@ namespace starter.viewmodel.settings return clickAboutUploadCommand; } } - private BaseCommand clickExitCommand; + private BaseCommand? clickExitCommand; public BaseCommand ClickExitCommand { get { if (clickExitCommand == null) { - clickExitCommand = new BaseCommand(new Action(o => + clickExitCommand = new BaseCommand(new Action(o => { Application.Current.Shutdown(); })); @@ -1002,14 +1003,14 @@ namespace starter.viewmodel.settings return clickExitCommand; } } - private BaseCommand clickShiftLanguageCommand; + private BaseCommand? clickShiftLanguageCommand; public BaseCommand ClickShiftLanguageCommand { get { if (clickShiftLanguageCommand == null) { - clickShiftLanguageCommand = new BaseCommand(new Action(o => + clickShiftLanguageCommand = new BaseCommand(new Action(o => { if (obj.launchLanguage == SettingsModel.LaunchLanguage.cpp) obj.launchLanguage = SettingsModel.LaunchLanguage.python; @@ -1023,14 +1024,14 @@ namespace starter.viewmodel.settings return clickShiftLanguageCommand; } } - private BaseCommand clickReadCommand; + private BaseCommand? clickReadCommand; public BaseCommand ClickReadCommand { get { if (clickReadCommand == null) { - clickReadCommand = new BaseCommand(new Action(o => + clickReadCommand = new BaseCommand(new Action(o => { if (!Directory.Exists(Route + "/THUAI6/win")) { @@ -1050,14 +1051,14 @@ namespace starter.viewmodel.settings return clickReadCommand; } } - private BaseCommand clickSwitchOSCommand; + private BaseCommand? clickSwitchOSCommand; public BaseCommand ClickSwitchOSCommand { get { if (clickSwitchOSCommand == null) { - clickSwitchOSCommand = new BaseCommand(new Action(o => + clickSwitchOSCommand = new BaseCommand(new Action(o => { switch (obj.usingOS) { diff --git a/installer/InstallerUpdater/MainWindow.xaml b/installer/InstallerUpdater/MainWindow.xaml index 271161a..5a3fdf1 100644 --- a/installer/InstallerUpdater/MainWindow.xaml +++ b/installer/InstallerUpdater/MainWindow.xaml @@ -5,7 +5,9 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:InstallerUpdater" mc:Ignorable="d" - Title="MainWindow" Height="180" Width="300"> + Title="MainWindow" Height="180" Width="300" + ResizeMode="CanMinimize" + > diff --git a/installer/InstallerUpdater/Program.cs b/installer/InstallerUpdater/Program.cs index 9a9fced..17e620e 100644 --- a/installer/InstallerUpdater/Program.cs +++ b/installer/InstallerUpdater/Program.cs @@ -18,7 +18,8 @@ namespace Program { class Updater { - public static string Dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); + public static string Dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName) + ?? throw new Exception("Cannot get current directory"); public static string InstallerName = "Installer.exe"; public static string jsonKey = "installerHash.json"; public static string KeyHead = "Installer/"; @@ -31,7 +32,8 @@ namespace Program 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 = JsonConvert.DeserializeObject>(json); + List jsonList = JsonConvert.DeserializeObject>(json) + ?? throw new Exception("Failed to deserialize json!"); foreach (string todo in jsonList) { if (!todo.Equals("None")) @@ -41,14 +43,14 @@ namespace Program } } } - catch (IOException) + catch (IOException ex) { - MessageBox.Show("下载器本体未能成功关闭"); + MessageBox.Show($"下载器本体未能成功关闭:\n{ex}"); return false; } - catch + catch (Exception ex) { - MessageBox.Show("尝试下载时出现问题"); + MessageBox.Show($"尝试下载时出现问题:\n{ex}\n{ex.StackTrace}"); return false; } return true; @@ -67,7 +69,8 @@ namespace Program json += @"{""None""}"; } List ls = new List(); - ls = JsonConvert.DeserializeObject>(json); + ls = JsonConvert.DeserializeObject>(json) + ?? throw new Exception("Failed to deserialize json!"); if (!ls.Contains("Dismiss")) { ls.Add("Dismiss"); @@ -114,9 +117,10 @@ namespace Program // 创建存储桶 try { - string bucket = "thuai6-1314234950"; // 格式:BucketName-APPID - string localDir = System.IO.Path.GetDirectoryName(download_dir); // 本地文件夹 - string localFileName = System.IO.Path.GetFileName(download_dir); // 指定本地保存的文件名 + string bucket = "thuai6-1314234950"; // 格式:BucketName-APPID + string localDir = System.IO.Path.GetDirectoryName(download_dir) // 本地文件夹 + ?? throw new Exception("Failed to get directory name!"); + string localFileName = System.IO.Path.GetFileName(download_dir); // 指定本地保存的文件名 GetObjectRequest request = new GetObjectRequest(bucket, key, localDir, localFileName); Dictionary test = request.GetRequestHeaders(); diff --git a/logic/Client/Client.csproj b/logic/Client/Client.csproj index abcb9a6..ffa5629 100644 --- a/logic/Client/Client.csproj +++ b/logic/Client/Client.csproj @@ -12,10 +12,6 @@ - - - - diff --git a/logic/Client/EESASTLogo.png b/logic/Client/EESASTLogo.png new file mode 100644 index 0000000..efba5b5 Binary files /dev/null and b/logic/Client/EESASTLogo.png differ diff --git a/logic/Client/Logo.png b/logic/Client/Logo.png index efba5b5..6d7d511 100644 Binary files a/logic/Client/Logo.png and b/logic/Client/Logo.png differ diff --git a/logic/Client/MainWindow.xaml b/logic/Client/MainWindow.xaml index e1326a7..7046f39 100644 --- a/logic/Client/MainWindow.xaml +++ b/logic/Client/MainWindow.xaml @@ -51,7 +51,7 @@ - + diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 340fbd4..d8dd6b5 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -20,6 +20,7 @@ using Playback; using CommandLine; using Preparation.Utility; using Preparation.Interface; +using System.Diagnostics.CodeAnalysis; // 目前MainWindow还未复现的功能: // private void ClickToSetMode(object sender, RoutedEventArgs e) @@ -65,6 +66,7 @@ namespace Client ReactToCommandline(); } + [MemberNotNull(nameof(StatusBarsOfSurvivor), nameof(StatusBarsOfHunter), nameof(StatusBarsOfCircumstance))] private void SetStatusBar() { StatusBarsOfSurvivor = new StatusBarOfSurvivor[4]; @@ -716,29 +718,21 @@ namespace Client isDataFixed[obj.PlayerId] = true; } } - if (StatusBarsOfSurvivor != null) + + for (int i = 0; i < GameData.numOfStudent; i++) { - for (int i = 0; i < GameData.numOfStudent; i++) - { - StatusBarsOfSurvivor[i].NewData(totalLife, totalDeath, coolTime); - } + StatusBarsOfSurvivor[i].NewData(totalLife, totalDeath, coolTime); } - if (StatusBarsOfHunter != null) + + StatusBarsOfHunter.NewData(totalLife, totalDeath, coolTime); + + for (int i = 0; i < GameData.numOfStudent; i++) { - StatusBarsOfHunter.NewData(totalLife, totalDeath, coolTime); + StatusBarsOfSurvivor[i].SetFontSize(12 * unitFontsize); } - // 完成窗口信息更新 - if (StatusBarsOfSurvivor != null) - { - for (int i = 0; i < GameData.numOfStudent; i++) - { - StatusBarsOfSurvivor[i].SetFontSize(12 * unitFontsize); - } - } - if (StatusBarsOfHunter != null) - StatusBarsOfHunter.SetFontSize(12 * unitFontsize); - if (StatusBarsOfCircumstance != null) - StatusBarsOfCircumstance.SetFontSize(12 * unitFontsize); + + StatusBarsOfHunter.SetFontSize(12 * unitFontsize); + StatusBarsOfCircumstance.SetFontSize(12 * unitFontsize); if (!isClientStocked) { try @@ -1054,6 +1048,11 @@ namespace Client { if (!isPlaybackMode && !isSpectatorMode) { + if (client is null) + { + return; + } + switch (e.Key) { case Key.W: @@ -1235,6 +1234,10 @@ namespace Client { if (!isPlaybackMode && !isSpectatorMode) { + if (client is null) + { + return; + } if (humanOrButcher && human != null) { AttackMsg msgJ = new() @@ -1385,7 +1388,7 @@ namespace Client // 以下为Mainwindow自定义属性 private readonly DispatcherTimer timer; // 定时器 private long counter; // 预留的取时间变量 - AvailableService.AvailableServiceClient client; + AvailableService.AvailableServiceClient? client; AsyncServerStreamingCall? responseStream; private StatusBarOfSurvivor[] StatusBarsOfSurvivor; private StatusBarOfHunter StatusBarsOfHunter;