| @@ -1,6 +1,8 @@ | |||
| using System.ComponentModel; | |||
| using System; | |||
| using System.Windows.Input; | |||
| using System.Globalization; | |||
| using System.Windows.Data; | |||
| namespace starter.viewmodel.common | |||
| { | |||
| @@ -66,4 +68,34 @@ namespace starter.viewmodel.common | |||
| } | |||
| } | |||
| } | |||
| public class RadioConverter : IValueConverter | |||
| { | |||
| public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | |||
| { | |||
| if (value == null || parameter == null) | |||
| { | |||
| return false; | |||
| } | |||
| 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) | |||
| { | |||
| if (value == null || parameter == null) | |||
| { | |||
| return null; | |||
| } | |||
| if ((bool)value) | |||
| { | |||
| return parameter.ToString(); | |||
| } | |||
| return null; | |||
| } | |||
| } | |||
| } | |||
| @@ -3,9 +3,12 @@ | |||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
| xmlns:local="clr-namespace:Installer" | |||
| xmlns:local="clr-namespace:Installer" xmlns:c="clr-namespace:starter.viewmodel.common" | |||
| mc:Ignorable="d" | |||
| Title="Installer" Window.SizeToContent="WidthAndHeight"> | |||
| <Window.Resources> | |||
| <c:RadioConverter x:Key="RadioConverter"/> | |||
| </Window.Resources> | |||
| <Grid> | |||
| <Grid.ColumnDefinitions> | |||
| <ColumnDefinition Width="40" /> | |||
| @@ -34,14 +37,14 @@ | |||
| <TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="5" Text="{Binding RouteBoxIntro}"/> | |||
| <TextBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="5" Name="RouteTxtBox" Text="{Binding Route}" Visibility="{Binding RouteBoxVis}"/> | |||
| <Button Grid.Row="3" Grid.Column="6" Name="GetRouteBtn" Content="Browse..." Command="{Binding ClickBrowseCommand}" Visibility="{Binding RouteBoxVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="7" Name="SetBtm" Content="Confirm" Command="{Binding ClickConfirmCommand}" Visibility="{Binding RouteBoxVis}"/> | |||
| <Button Grid.Row="3" Grid.Column="6" Name="GetRouteBtn" Content="选择文件夹" Command="{Binding ClickBrowseCommand}" Visibility="{Binding RouteBoxVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="7" Name="SetBtm" Content="确认并安装" Command="{Binding ClickConfirmCommand}" Visibility="{Binding RouteBoxVis}"/> | |||
| <Button Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" Name="UpdateBtn" Content="{Binding UpdateBtnCont}" Command="{Binding ClickUpdateCommand}" Visibility="{Binding MenuVis}" /> | |||
| <TextBlock Grid.Row="4" Grid.Column="2" Text="{Binding UpdateInfo}" Visibility="{Binding MenuVis}" /> | |||
| <Button Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="2" Name="MoveBtn" Content="Move" Command="{Binding ClickMoveCommand}" Visibility="{Binding MenuVis}" /> | |||
| <Button Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="2" Name="MoveBtn" Content="移动文件" Command="{Binding ClickMoveCommand}" Visibility="{Binding MenuVis}" /> | |||
| <Button Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" Name="UninstBtn" Content="UnInstall" Command="{Binding ClickUninstCommand}" Visibility="{Binding MenuVis}" /> | |||
| <Button Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" Name="UninstBtn" Content="卸载选手包" Command="{Binding ClickUninstCommand}" Visibility="{Binding MenuVis}" /> | |||
| <Button Grid.Row="7" Grid.Column="2" Grid.ColumnSpan="2" Name="MenuBackBtn" Content="回到登陆界面" Command="{Binding ClickBackCommand}" Visibility="{Binding MenuVis}" /> | |||
| <TextBlock Grid.Row="3" Grid.Column="4" Text="Processing" Grid.ColumnSpan="2" Visibility="{Binding ProgressVis}"/> | |||
| @@ -50,27 +53,40 @@ | |||
| <TextBlock Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="4" Text="操作完成!你可以继续操作或退出" Visibility="{Binding CompleteVis}"/> | |||
| <Button Grid.Row="6" Grid.Column="1" Name="BackBtn" Content="返回" Command="{Binding ClickBackCommand}" Visibility="{Binding CompleteVis}" Click="BackBtn_Click"/> | |||
| <Button Grid.Row="6" Grid.Column="4" Grid.ColumnSpan="2" Name="ExitBtn" Content="退出" Command="{Binding ClickExitCommand}" Visibility="{Binding CompleteVis}"/> | |||
| <TextBlock Grid.Row="3" Grid.Column="1" Text="账号:" Visibility="{Binding LoginVis}" /> | |||
| <TextBlock Grid.Row="5" Grid.Column="1" Text="密码:" Visibility="{Binding LoginVis}" /> | |||
| <TextBox Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="4" Name="Username" Visibility="{Binding LoginVis}" Text="{Binding Username}" /> | |||
| <TextBox Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="4" Name="Password" Visibility="{Binding LoginVis}" Text="{Binding Password}" /> | |||
| <StackPanel Grid.Row="2" Grid.Column="1" Grid.RowSpan="5" Grid.ColumnSpan="5"> | |||
| <Grid> | |||
| <Grid.RowDefinitions> | |||
| <RowDefinition Height="10"/> | |||
| <RowDefinition Height="20"/> | |||
| <RowDefinition Height="10"/> | |||
| <RowDefinition Height="20"/> | |||
| <RowDefinition Height="10"/> | |||
| <RowDefinition Height="15"/> | |||
| <RowDefinition Height="*"/> | |||
| </Grid.RowDefinitions> | |||
| <Grid.ColumnDefinitions> | |||
| <ColumnDefinition Width="60"/> | |||
| <ColumnDefinition Width="*"/> | |||
| </Grid.ColumnDefinitions> | |||
| <TextBlock Grid.Row="1" Grid.Column="0" Text="账号:" Visibility="{Binding LoginVis}" /> | |||
| <TextBlock Grid.Row="3" Grid.Column="0" Text="密码:" Visibility="{Binding LoginVis}" /> | |||
| <TextBox Grid.Row="1" Grid.Column="1" Name="Username" Visibility="{Binding LoginVis}" Text="{Binding Username}" /> | |||
| <TextBox Grid.Row="3" Grid.Column="1" Name="Password" Visibility="{Binding LoginVis}" Text="{Binding Password}" /> | |||
| <!--<CheckBox Grid.Row="5" Grid.Column="0" Visibility="{Binding LoginVis}">记住我</CheckBox>--> | |||
| <TextBlock Grid.Row="5" Grid.Column="1" Foreground="Red" Text=" 用户名或密码错误!" Visibility="{Binding LoginFailVis}"/> | |||
| </Grid> | |||
| </StackPanel> | |||
| <Button Grid.Row="7" Grid.Column="1" Name="Login" Content="登录" Command="{Binding ClickLoginCommand}" Visibility="{Binding LoginVis}"/> | |||
| <Button Grid.Row="7" Grid.Column="2" Name="Launch" Content="{Binding LaunchBtnCont}" Command="{Binding ClickLaunchCommand}" Visibility="{Binding LoginVis}"/> | |||
| <Button Grid.Row="7" Grid.Column="4" Grid.ColumnSpan="2" Name="Edit" Content="修改文件" Command="{Binding ClickEditCommand}" Visibility="{Binding LoginVis}"/> | |||
| <TextBlock Grid.Row="6" Grid.Column="1" Text="用户名或密码错误!" Visibility="{Binding LoginFailVis}"/> | |||
| <TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Text="你有已完成的比赛!" Visibility="{Binding MatchFinishedVis}"/> | |||
| <Button Grid.Row="3" Grid.Column="1" Name ="Upload" Content="{Binding UploadBtnCont}" Command="{Binding ClickUploadCommand}" Visibility="{Binding WebVis}"/> | |||
| <TextBlock Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding CodeName}" Visibility="{Binding UploadReadyVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="2" Name="ReUpload" Content="重新选择代码" Command="{Binding ReselectCommand}" Visibility="{Binding UploadReadyVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="2" Name="ReUpload" Content="放弃上传" Command="{Binding ClickReselectCommand}" Visibility="{Binding UploadReadyVis}" /> | |||
| <Button Grid.Row="6" Grid.Column="3" Grid.ColumnSpan="2" Content="退出登录" Command="{Binding ClickBackCommand}" Visibility="{Binding WebVis}" /> | |||
| <!--objects below are not enabled--> | |||
| <Button Grid.Row="5" Grid.Column="1" Name="Download" Content="下载回放" IsEnabled="False" Command="{Binding ClickDownloadCommand}" Visibility="{Binding CoverVis}" /> | |||
| <Button Grid.Row="7" Grid.Column="1" Name="Replay" Content="打开回放" IsEnabled="False" Command="{Binding ClickReplayCommand}" Visibility="{Binding CoverVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Content="申请对战" IsEnabled="False" Command="{Binding ClickRequestCommand}" Visibility="{Binding WebVis}" /> | |||
| <TextBox Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Text="暂不支持" IsEnabled="False" Visibility="{Binding WebVis}" /> | |||
| <StackPanel Grid.Row="5" Grid.Column="1" Grid.RowSpan="3" Grid.ColumnSpan="2"> | |||
| <Grid> | |||
| <Grid.RowDefinitions> | |||
| @@ -79,11 +95,18 @@ | |||
| <RowDefinition Height="15"/> | |||
| <RowDefinition Height="15"/> | |||
| </Grid.RowDefinitions> | |||
| <RadioButton GroupName="playerNum" Grid.Row="0" Visibility="{Binding UploadReadyVis}">玩家1</RadioButton> | |||
| <RadioButton GroupName="playerNum" Grid.Row="1" Visibility="{Binding UploadReadyVis}">玩家2</RadioButton> | |||
| <RadioButton GroupName="playerNum" Grid.Row="2" Visibility="{Binding UploadReadyVis}">玩家3</RadioButton> | |||
| <RadioButton GroupName="playerNum" Grid.Row="3" Visibility="{Binding UploadReadyVis}">玩家4</RadioButton> | |||
| <RadioButton GroupName="playerNum" Grid.Row="0" Visibility="{Binding UploadReadyVis}" IsChecked="{Binding PlayerNum,Mode=TwoWay,Converter={StaticResource RadioConverter},ConverterParameter=1}">玩家1</RadioButton> | |||
| <RadioButton GroupName="playerNum" Grid.Row="1" Visibility="{Binding UploadReadyVis}" IsChecked="{Binding PlayerNum,Mode=TwoWay,Converter={StaticResource RadioConverter},ConverterParameter=2}">玩家2</RadioButton> | |||
| <RadioButton GroupName="playerNum" Grid.Row="2" Visibility="{Binding UploadReadyVis}" IsChecked="{Binding PlayerNum,Mode=TwoWay,Converter={StaticResource RadioConverter},ConverterParameter=3}">玩家3</RadioButton> | |||
| <RadioButton GroupName="playerNum" Grid.Row="3" Visibility="{Binding UploadReadyVis}" IsChecked="{Binding PlayerNum,Mode=TwoWay,Converter={StaticResource RadioConverter},ConverterParameter=4}">玩家4</RadioButton> | |||
| </Grid> | |||
| </StackPanel> | |||
| <!--objects below are not enabled--> | |||
| <Button Grid.Row="5" Grid.Column="1" Name="Download" Content="下载回放" IsEnabled="False" Command="{Binding ClickDownloadCommand}" Visibility="{Binding CoverVis}" /> | |||
| <Button Grid.Row="7" Grid.Column="1" Name="Replay" Content="打开回放" IsEnabled="False" Command="{Binding ClickReplayCommand}" Visibility="{Binding CoverVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Content="申请对战" IsEnabled="False" Command="{Binding ClickRequestCommand}" Visibility="{Binding WebVis}" /> | |||
| <TextBox Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Text="暂不支持" IsEnabled="False" Visibility="{Binding WebVis}" /> | |||
| </Grid> | |||
| </Window> | |||
| @@ -49,6 +49,7 @@ namespace starter.viewmodel.settings | |||
| Password = ""; | |||
| updates = ""; | |||
| CodeRoute = ""; | |||
| PlayerNum = "nSelect"; | |||
| UploadReady = false; | |||
| LoginFailed = false; | |||
| } | |||
| @@ -166,7 +167,9 @@ namespace starter.viewmodel.settings | |||
| default: | |||
| return -8; | |||
| } | |||
| return await web.UploadFiles(client, CodeRoute, Language, "player_1"); | |||
| if (PlayerNum.Equals("nSelect")) | |||
| return -9; | |||
| return await web.UploadFiles(client, CodeRoute, Language, PlayerNum); | |||
| } | |||
| /// <summary> | |||
| /// Route of files | |||
| @@ -394,8 +397,8 @@ namespace Downloader | |||
| .Build(); // 创建 CosXmlConfig 对象 | |||
| // 永久密钥访问凭证 | |||
| string secretId = "***"; //"云 API 密钥 SecretId"; | |||
| string secretKey = "***"; //"云 API 密钥 SecretKey"; | |||
| string secretId = "***"; //"云 API 密钥 SecretId"; | |||
| string secretKey = "***"; //"云 API 密钥 SecretKey"; | |||
| long durationSecond = 1000; // 每次请求签名有效时长,单位为秒 | |||
| QCloudCredentialProvider cosCredentialProvider = new DefaultQCloudCredentialProvider( | |||
| @@ -1119,7 +1122,8 @@ namespace WebConnect | |||
| using FileStream fs = new FileStream(tarfile, FileMode.Open, FileAccess.Read); | |||
| using StreamReader sr = new StreamReader(fs); | |||
| content = sr.ReadToEnd(); | |||
| using (var response = await client.GetAsync($"https://api.eesast.com/static/player?team_id={await GetTeamId()}")) | |||
| string targetUrl = $"https://api.eesast.com/static/player?team_id={await GetTeamId()}"; | |||
| using (var response = await client.GetAsync(targetUrl)) | |||
| { | |||
| switch (response.StatusCode) | |||
| { | |||
| @@ -1343,7 +1347,7 @@ namespace WebConnect | |||
| // ""query"": ""query MyQuery {{contest_team_member(where: {{user_id: {{_eq: \""{Downloader.UserInfo._id}\""}}}}) {{ team_id }}}}"", | |||
| // ""variables"": {{}}, | |||
| // }}", null, "application/json"); | |||
| var content = new StringContent("{\"query\":\"query MyQuery {\\r\\n contest_team_member(where: {user_id: {_eq: \\\""+Downloader.UserInfo._id+"\\\"}}) {\\r\\n team_id\\r\\n }\\r\\n}\",\"variables\":{}}", null, "application/json"); | |||
| var content = new StringContent("{\"query\":\"query MyQuery {\\r\\n contest_team_member(where: {user_id: {_eq: \\\"" + Downloader.UserInfo._id + "\\\"}}) {\\r\\n team_id\\r\\n }\\r\\n}\",\"variables\":{}}", null, "application/json"); | |||
| request.Content = content; | |||
| var response = await client.SendAsync(request); | |||
| response.EnsureSuccessStatusCode(); | |||
| @@ -6,8 +6,7 @@ using System.Windows.Forms; | |||
| using Downloader; | |||
| using MessageBox = System.Windows.MessageBox; | |||
| using System.Configuration; | |||
| using WebConnect; | |||
| using System.Net.Http; | |||
| using System.Drawing.Design; | |||
| namespace starter.viewmodel.settings | |||
| { | |||
| @@ -135,6 +134,46 @@ namespace starter.viewmodel.settings | |||
| } | |||
| } | |||
| } | |||
| public int PlayerNum | |||
| { | |||
| get | |||
| { | |||
| int ans; | |||
| if (obj.PlayerNum.Equals("player_1")) | |||
| ans = 1; | |||
| else if (obj.PlayerNum.Equals("player_2")) | |||
| ans = 2; | |||
| else if (obj.PlayerNum.Equals("player_3")) | |||
| ans = 3; | |||
| else if (obj.PlayerNum.Equals("player_4")) | |||
| ans = 4; | |||
| else | |||
| ans = 0; | |||
| return ans; | |||
| } | |||
| set | |||
| { | |||
| switch (value) | |||
| { | |||
| case 1: | |||
| obj.PlayerNum = "player_1"; | |||
| break; | |||
| case 2: | |||
| obj.PlayerNum = "player_2"; | |||
| break; | |||
| case 3: | |||
| obj.PlayerNum = "player_3"; | |||
| break; | |||
| case 4: | |||
| obj.PlayerNum = "player_4"; | |||
| break; | |||
| default: | |||
| obj.PlayerNum = "nSelect"; | |||
| break; | |||
| } | |||
| this.RaisePropertyChanged("PlayerNum"); | |||
| } | |||
| } | |||
| public string Route | |||
| { | |||
| @@ -242,7 +281,7 @@ namespace starter.viewmodel.settings | |||
| { | |||
| get | |||
| { | |||
| return obj.UpdatePlanned ? "Update" : "Check Updates"; | |||
| return obj.UpdatePlanned ? "更新" : "检查更新"; | |||
| } | |||
| } | |||
| public string UpdateInfo | |||
| @@ -448,7 +487,9 @@ namespace starter.viewmodel.settings | |||
| } | |||
| else | |||
| { | |||
| obj.LoginFailed = false; | |||
| Status = SettingsModel.Status.web; | |||
| this.RaisePropertyChanged("CoverVis"); | |||
| } | |||
| this.RaisePropertyChanged("LoginFailVis"); | |||
| })); | |||
| @@ -530,38 +571,46 @@ namespace starter.viewmodel.settings | |||
| { | |||
| if (obj.UploadReady) | |||
| { | |||
| switch (await obj.Upload()) | |||
| if (obj.PlayerNum.Equals("nSelect")) | |||
| { | |||
| case -1: | |||
| MessageBox.Show("Token失效!", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); | |||
| break; | |||
| case -2: | |||
| MessageBox.Show("目标路径不存在!", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| case -3: | |||
| MessageBox.Show("服务器错误", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); | |||
| break; | |||
| case -4: | |||
| MessageBox.Show("您未登录或登录失效", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| Status = SettingsModel.Status.login; | |||
| break; | |||
| case -5: | |||
| MessageBox.Show("您未报名THUAI!", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); | |||
| break; | |||
| case -6: | |||
| MessageBox.Show("读取文件失败,请确认文件是否被占用", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| case -7: | |||
| MessageBox.Show("网络错误,请检查你的网络", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| case -8: | |||
| MessageBox.Show("不是c++或python源文件", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| MessageBox.Show("您还没有选择要上传的玩家身份", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| } | |||
| else | |||
| { | |||
| switch (await obj.Upload()) | |||
| { | |||
| case -1: | |||
| MessageBox.Show("Token失效!", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); | |||
| break; | |||
| case -2: | |||
| MessageBox.Show("目标路径不存在!", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| case -3: | |||
| MessageBox.Show("服务器错误", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); | |||
| break; | |||
| case -4: | |||
| MessageBox.Show("您未登录或登录失效", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| Status = SettingsModel.Status.login; | |||
| break; | |||
| case -5: | |||
| MessageBox.Show("您未报名THUAI!", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); | |||
| break; | |||
| case -6: | |||
| MessageBox.Show("读取文件失败,请确认文件是否被占用", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| case -7: | |||
| MessageBox.Show("网络错误,请检查你的网络", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| case -8: | |||
| MessageBox.Show("不是c++或python源文件", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); | |||
| break; | |||
| } | |||
| obj.CodeRoute = ""; | |||
| obj.UploadReady = false; | |||
| this.RaisePropertyChanged("UploadBtnCont"); | |||
| this.RaisePropertyChanged("UploadReadyVis"); | |||
| this.RaisePropertyChanged("CoverVis"); | |||
| } | |||
| obj.CodeRoute = ""; | |||
| obj.UploadReady = false; | |||
| this.RaisePropertyChanged("UploadBtnCont"); | |||
| this.RaisePropertyChanged("UploadReadyVis"); | |||
| } | |||
| else | |||
| { | |||
| @@ -572,6 +621,7 @@ namespace starter.viewmodel.settings | |||
| this.RaisePropertyChanged("UploadBtnCont"); | |||
| this.RaisePropertyChanged("UploadReadyVis"); | |||
| this.RaisePropertyChanged("CodeName"); | |||
| this.RaisePropertyChanged("CoverVis"); | |||
| } | |||
| else | |||
| { | |||
| @@ -583,6 +633,26 @@ namespace starter.viewmodel.settings | |||
| return clickUploadCommand; | |||
| } | |||
| } | |||
| private BaseCommand clickReselectCommand; | |||
| public BaseCommand ClickReselectCommand | |||
| { | |||
| get | |||
| { | |||
| if (clickReselectCommand == null) | |||
| { | |||
| clickReselectCommand = new BaseCommand(new Action<object>(o => | |||
| { | |||
| obj.CodeRoute = ""; | |||
| obj.UploadReady = false; | |||
| this.RaisePropertyChanged("UploadBtnCont"); | |||
| this.RaisePropertyChanged("UploadReadyVis"); | |||
| this.RaisePropertyChanged("CodeName"); | |||
| this.RaisePropertyChanged("CoverVis"); | |||
| })); | |||
| } | |||
| return clickReselectCommand; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -164,7 +164,7 @@ namespace GameClass.GameObj | |||
| ap = value; | |||
| } | |||
| } | |||
| public override int Speed => 4300; | |||
| public override int Speed => (int)(GameData.basicBulletMoveSpeed * 43 / 37); | |||
| public override bool IsRemoteAttack => false; | |||
| public override int CastTime => 0; | |||
| @@ -296,6 +296,27 @@ namespace GameClass.GameObj | |||
| } | |||
| return GameObjForInteract; | |||
| } | |||
| public GameObj? PartInTheSameCell(XY Pos, GameObjType gameObjType) | |||
| { | |||
| GameObj? GameObjForInteract = null; | |||
| GameObjLockDict[gameObjType].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (GameObj gameObj in GameObjDict[gameObjType]) | |||
| { | |||
| if (GameData.PartInTheSameCell(gameObj.Position, Pos)) | |||
| { | |||
| GameObjForInteract = gameObj; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[gameObjType].ExitReadLock(); | |||
| } | |||
| return GameObjForInteract; | |||
| } | |||
| public GameObj? OneForInteractInACross(XY Pos, GameObjType gameObjType) | |||
| { | |||
| GameObj? GameObjForInteract = null; | |||
| @@ -55,7 +55,7 @@ namespace Gaming | |||
| public bool Fix(Student player)// 自动检查有无发电机可修 | |||
| { | |||
| if ((!player.Commandable()) || player.PlayerState == PlayerStateType.Fixing) | |||
| if (player.CharacterType == CharacterType.Teacher || (!player.Commandable()) || player.PlayerState == PlayerStateType.Fixing) | |||
| return false; | |||
| Generator? generatorForFix = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator); | |||
| @@ -368,7 +368,7 @@ namespace Gaming | |||
| if (!(player.Commandable()) || player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor) | |||
| return false; | |||
| Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door); | |||
| if (doorToLock == null || doorToLock.OpenOrLockDegree > 0) | |||
| if (doorToLock == null || doorToLock.OpenOrLockDegree > 0 || gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character) != null) | |||
| return false; | |||
| bool flag = false; | |||
| foreach (Prop prop in player.PropInventory) | |||
| @@ -403,7 +403,8 @@ namespace Gaming | |||
| loopCondition: () => flag && player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor, | |||
| loopToDo: () => | |||
| { | |||
| flag = ((gameMap.OneInTheSameCell(doorToLock.Position, GameObjType.Character)) == null); | |||
| flag = ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) == null); | |||
| Preparation.Utility.Debugger.Output(doorToLock, flag.ToString()); | |||
| doorToLock.OpenOrLockDegree += GameData.frameDuration * player.SpeedOfOpeningOrLocking; | |||
| }, | |||
| timeInterval: GameData.frameDuration, | |||
| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using Preparation.Interface; | |||
| using System; | |||
| using System.Net.NetworkInformation; | |||
| namespace Preparation.Utility | |||
| @@ -68,6 +69,11 @@ namespace Preparation.Utility | |||
| { | |||
| return PosGridToCellX(pos1) == PosGridToCellX(pos2) && PosGridToCellY(pos1) == PosGridToCellY(pos2); | |||
| } | |||
| public static bool PartInTheSameCell(XY pos1, XY pos2) | |||
| { | |||
| return Math.Abs((pos1 - pos2).x) < characterRadius + (numOfPosGridPerCell / 2) | |||
| && Math.Abs((pos1 - pos2).y) < characterRadius + (numOfPosGridPerCell / 2); | |||
| } | |||
| public static bool ApproachToInteract(XY pos1, XY pos2) | |||
| { | |||
| if (pos1 == pos2) return false; | |||
| @@ -83,10 +83,9 @@ namespace Server | |||
| private void SaveGameResult(string path) | |||
| { | |||
| Dictionary<string, int> result = new Dictionary<string, int>(); | |||
| for (int i = 0; i < TeamCount; i++) | |||
| { | |||
| result.Add("Team" + i.ToString(), GetTeamScore(i)); //Team待修改 | |||
| } | |||
| int[] score = GetScore(); | |||
| result.Add("Student", score[0]); | |||
| result.Add("Tricker", score[1]); | |||
| JsonSerializer serializer = new JsonSerializer(); | |||
| using (StreamWriter sw = new StreamWriter(path)) | |||
| { | |||
| @@ -99,10 +98,9 @@ namespace Server | |||
| protected virtual void SendGameResult() // 天梯的 Server 给网站发消息记录比赛结果 | |||
| { | |||
| var scores = new JObject[options.TeamCount]; | |||
| for (ushort i = 0; i < options.TeamCount; ++i) | |||
| { | |||
| scores[i] = new JObject { ["team_id"] = i.ToString(), ["score"] = GetTeamScore(i) }; | |||
| } // Team待修改 | |||
| int[] score = GetScore(); | |||
| scores[0] = new JObject { ["team_name"] = "Student", ["score"] = score[0] }; | |||
| scores[1] = new JObject { ["team_name"] = "Tricker", ["score"] = score[1] }; | |||
| httpSender?.SendHttpRequest | |||
| ( | |||
| new JObject | |||
| @@ -166,9 +164,24 @@ namespace Server | |||
| kvp.Value.Item2.Wait(); | |||
| } | |||
| } | |||
| public int GetTeamScore(long teamID) | |||
| public int[] GetScore() | |||
| { | |||
| return game.GetTeamScore(teamID); | |||
| int[] score = new int[2]; // 0代表Student,1代表Tricker | |||
| game.GameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (Character character in game.GameMap.GameObjDict[GameObjType.Character]) | |||
| { | |||
| if (!character.IsGhost()) score[0] += character.Score; | |||
| else score[1] += character.Score; | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| game.GameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||
| } | |||
| return score; | |||
| } | |||
| private int PlayerIDToTeamID(long playerID) | |||
| @@ -202,22 +215,9 @@ namespace Server | |||
| msg.SubjectFinished = (int)game.GameMap.NumOfRepairedGenerators; | |||
| msg.StudentGraduated = (int)game.GameMap.NumOfEscapedStudent; | |||
| msg.StudentQuited = (int)game.GameMap.NumOfDeceasedStudent; | |||
| msg.StudentScore = 0; | |||
| msg.TrickerScore = 0; | |||
| game.GameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (Character character in game.GameMap.GameObjDict[GameObjType.Character]) | |||
| { | |||
| if (!character.IsGhost()) msg.StudentScore += character.Score; | |||
| else msg.TrickerScore += character.Score; | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| game.GameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||
| } | |||
| int[] score = GetScore(); | |||
| msg.StudentScore = score[0]; | |||
| msg.TrickerScore = score[1]; | |||
| //msg.GateOpened | |||
| //msg.HiddenGateRefreshed | |||
| //msg.HiddenGateOpened | |||
| @@ -42,6 +42,12 @@ namespace Server | |||
| gameServer.WaitForEnd(); | |||
| Console.WriteLine("Server end!"); | |||
| server.ShutdownAsync().Wait(); | |||
| Thread.Sleep(50); | |||
| Console.WriteLine(""); | |||
| Console.WriteLine("=================== Final Score ===================="); | |||
| Console.WriteLine($"Studnet: {gameServer.GetScore()[0]}"); | |||
| Console.WriteLine($"Tricker: {gameServer.GetScore()[1]}"); | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| @@ -65,9 +65,9 @@ namespace Server | |||
| //Console.WriteLine("Send!"); | |||
| } | |||
| } | |||
| catch (Exception ex) | |||
| catch (Exception) | |||
| { | |||
| Console.WriteLine(ex); | |||
| //Console.WriteLine(ex); | |||
| } | |||
| finally | |||
| { | |||
| @@ -97,7 +97,6 @@ namespace Server | |||
| if (newPlayerID == GameObj.invalidID) | |||
| return; | |||
| communicationToGameID[request.PlayerId] = newPlayerID; | |||
| // 内容待修改 | |||
| var temp = (new SemaphoreSlim(0, 1), new SemaphoreSlim(0, 1)); | |||
| bool start = false; | |||
| Console.WriteLine($"Id: {request.PlayerId} joins."); | |||
| @@ -172,7 +171,6 @@ namespace Server | |||
| } | |||
| var gameID = communicationToGameID[request.PlayerId]; | |||
| game.MovePlayer(gameID, (int)request.TimeInMilliseconds, request.Angle); | |||
| // 之后game.MovePlayer可能改为bool类 | |||
| moveRes.ActSuccess = true; | |||
| if (!game.GameMap.Timer.IsGaming) moveRes.ActSuccess = false; | |||
| return Task.FromResult(moveRes); | |||
| @@ -4,13 +4,6 @@ | |||
| - *斜体表示Logic底层尚未(完全)实现* | |||
| - []表示待决定 | |||
| ## 游戏简介 | |||
| - 1位捣蛋鬼对抗4位学生的非对称竞技模式 | |||
| - [本届THUAI电子系赛道为以4名同学和1名捣蛋鬼的求学与阻挠展开的非对称竞技模式,同学需要完成足够的家庭作业和考试,相互督促以避免沉迷娱乐生活,利用道具地形躲避捣蛋鬼的各种干扰诱惑,完成学业;捣蛋鬼则要极力阻止。] | |||
| - [我们的设计是一个非对称游戏,类似第五人格,分为学生、捣蛋鬼两个阵营。在游戏中,学生修完若干课程之后通过考试即可顺利毕业,捣蛋鬼试图干扰学生使其沉迷游戏,以致于无法修完规定课程,直至挂科、退学。] | |||
| [对于选手来说,需要提前制定好学生的学习方案以抵御对方捣蛋鬼的干扰,类似地,也需要制定好捣蛋鬼的行动策略以影响对方学生的学习,也即每队至少要写好两份代码以执行不同阵营的不同策略。] | |||
| [当一局比赛结束(场上的学生有且仅有两种状态:退学或毕业)时,分别记录双方总得分;之后双方换边进行下半场比赛。最终将每队的学生方、捣蛋鬼方的得分相加,比较总得分判断胜负。] | |||
| ## 简要规则 | |||
| ### 地图 | |||
| @@ -21,29 +14,30 @@ | |||
| - 略 | |||
| - 地图上的每个格子有自己的区域类型:陆地、墙、草地、电机、出口、紧急出口、门、窗、箱子 | |||
| ### 人物状态 | |||
| 游戏人物共有17种不可叠加的状态:(加^为学生独有) | |||
| 1.普通状态 | |||
| 2^.学习 | |||
| 3^.被治疗 | |||
| 4^.在治疗 | |||
| 5.开或锁门 | |||
| 6.翻箱 | |||
| 7.使用技能 | |||
| 8^.正在毕业 | |||
| 9^.唤醒他人中 | |||
| 10^.被唤醒中(从沉迷状态中) | |||
| 11^.沉迷 | |||
| 12^.退学 | |||
| 13^.毕业 | |||
| 14.被眩晕 | |||
| 15.前摇 | |||
| 16.后摇 | |||
| 17.翻窗 | |||
| 其中后8项为不可行动状态 | |||
| -不加声明,不可行动状态中的玩家各项指令是无效的 | |||
| ### 人物 | |||
| - 人物半径为800 | |||
| - 游戏人物共有17种不可叠加的状态:(加^为学生独有) | |||
| 1. 普通状态 | |||
| 2. 学习^ | |||
| 3. 被治疗^ | |||
| 4. 在治疗^ | |||
| 5. 开或锁门 | |||
| 6. 翻箱 | |||
| 7. 使用技能 | |||
| 8. 正在毕业^ | |||
| 9. 唤醒他人中^ | |||
| 10. 被唤醒中(从沉迷状态中^ | |||
| 11. 沉迷^ | |||
| 12. 退学^ | |||
| 13. 毕业^ | |||
| 14. 被眩晕 | |||
| 15. 前摇 | |||
| 16. 后摇 | |||
| 17. 翻窗 | |||
| - 其中后8项为不可行动状态 | |||
| - 不加声明,不可行动状态中的玩家各项指令是无效的 | |||
| ### 交互 | |||
| - 除了翻窗,交互目标与交互者在一个九宫格内则为可交互 | |||
| @@ -265,7 +259,6 @@ | |||
| ## 细则 | |||
| ### 特殊说明 | |||
| - 不加说明,这里“学生”往往包括职业“教师” | |||
| ### 初始状态 | |||
| @@ -299,118 +292,11 @@ | |||
| - 爬窗:从窗一侧边缘中点到另一侧格子中心,位置渐移,时间=距离/爬窗速度。中断时,停留在另一侧格子中心 | |||
| ### 箱子 | |||
| - 地图上有8个箱子 | |||
| - 同一时刻只允许一人进行开启 | |||
| - 未开启完成的箱子在下一次需要重新开始开启。 | |||
| - 箱子开启后其中道具才可以被观测和拿取 | |||
| ## 游戏内Logic底层的枚举类型、类与属性 | |||
| - 底层实现中的属性,不代表界面全部都需要展示,也可能需要额外展示信息 | |||
| - 只展示外部需要的属性,部分属性被省略 | |||
| ### 物体 | |||
| - 位置 | |||
| - 位置地形 | |||
| - ID | |||
| - 类型 | |||
| - 面向角度 | |||
| - 形状 | |||
| - 半径 | |||
| - 是否可移动 | |||
| - 是否在移动 | |||
| - 移动速度 | |||
| ### 人物:物体 | |||
| - 装弹CD | |||
| - 持有子弹数量 | |||
| - 血量 | |||
| - 最大血量 | |||
| - 玩家状态(不可叠加) | |||
| - Bgm(字典) | |||
| - 得分 | |||
| - 当前子弹类型 | |||
| - 原始子弹类型 | |||
| - 持有道具 (最多三个)(数组) | |||
| - 是否隐身 | |||
| - 队伍ID | |||
| - 玩家ID | |||
| - 当前Buff | |||
| - 职业类型 | |||
| - 拥有的被动技能(列表) | |||
| - 拥有的主动技能(列表) | |||
| - 各个主动技能CD(字典) | |||
| - 警戒半径 | |||
| - double 隐蔽度 | |||
| - 翻窗时间 | |||
| - 开锁门速度 | |||
| - 开箱速度 | |||
| - 视野范围 | |||
| ### 学生:人物 | |||
| - 修理电机速度 | |||
| - 治疗速度 | |||
| - 沉迷游戏程度 | |||
| - 最大沉迷游戏程度 | |||
| - 被治疗程度 | |||
| - 被救援程度 | |||
| ### 搞蛋鬼:人物 | |||
| 无 | |||
| ### 队伍: | |||
| - 队伍ID | |||
| - 队伍得分 | |||
| - 队伍成员 | |||
| ### 所有物: | |||
| - 主人 | |||
| ### 子弹:所有物 | |||
| - 子弹攻击范围 | |||
| - 子弹爆炸范围 | |||
| - 子弹攻击力 | |||
| - 是否可以穿墙 | |||
| - 是否为远程攻击 | |||
| - 移动速度 | |||
| - 子弹类型 | |||
| ### 爆炸中的子弹:物体 | |||
| - 原来的子弹ID | |||
| - 爆炸范围 | |||
| - 子弹类型 | |||
| ### 道具:所有物 | |||
| - 道具类型 | |||
| ### 被捡起的道具:物体 | |||
| - 原来的道具ID | |||
| - 道具类型 | |||
| ### 出口:物体 | |||
| - 电力供应(是否可以被打开) | |||
| - 开启进度 | |||
| ### 紧急出口:物体 | |||
| - 是否显现 | |||
| - 是否打开 | |||
| ### 墙:物体 | |||
| ### 窗:物体 | |||
| - 正在翻窗的人 | |||
| ### 箱子:物体 | |||
| - 开箱进度 | |||
| ### 门:物体 | |||
| - 属于那个教学区 | |||
| - 是否锁上 | |||
| - 开锁门进度 | |||
| - 不提供是否可以锁上的属性 | |||
| ### 电机(建议称为homework):物体 | |||
| - 修理程度 | |||
| ## 键鼠控制 | |||
| | 键位 | 效果 | | |||