829 lines
31 KiB
C#
829 lines
31 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using AdminService.GameConfigs;
|
|
using ChessGameDomain;
|
|
using Common;
|
|
using CommonDomain;
|
|
using CommonDomain.Enum;
|
|
using CommonInfrastructure;
|
|
using DotNetCore.CAP;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Logging;
|
|
using MongoRepository;
|
|
using RedisService;
|
|
using RedisService.Param;
|
|
using UserDomain.Entity;
|
|
|
|
namespace AdminApi.GameConfigs
|
|
{
|
|
[ApiController, Route("adminapi/Admin/[controller]")]
|
|
[Authorize]
|
|
public class RoomController : BaseController
|
|
{
|
|
private readonly IRedisService _redisService;
|
|
private readonly IGameConfigService _gameConfigService;
|
|
private readonly ICapPublisher _capPublisher;
|
|
private readonly IMongoBaseRepository<UserEntity> _userMongo;
|
|
private readonly ILogger<RoomController> _logger;
|
|
|
|
public RoomController(IRedisService redisService, IGameConfigService gameConfigService, ICapPublisher capPublisher, IMongoBaseRepository<UserEntity> userMongo, ILogger<RoomController> logger)
|
|
{
|
|
_redisService = redisService;
|
|
_gameConfigService = gameConfigService;
|
|
_capPublisher = capPublisher;
|
|
_userMongo = userMongo;
|
|
_logger = logger;
|
|
}
|
|
|
|
[HttpGet("GetAllRooms")]
|
|
public async Task<PageResponse<RedisGameRoom>> GetAllRooms(
|
|
int pageIndex = 1,
|
|
int pageSize = 20,
|
|
int? roomLevel = null,
|
|
string? gameType = null,
|
|
string? sortField = null,
|
|
string? sortOrder = "desc")
|
|
{
|
|
var rooms = GetAllRoomsFromRedis()?.ToList() ?? new List<RedisGameRoom>();
|
|
|
|
foreach (var room in rooms)
|
|
{
|
|
if (room?.Players != null && room.Players.Count > 1)
|
|
room.Players = room.Players.OrderBy(p => p.Position).ToList();
|
|
}
|
|
|
|
if (roomLevel.HasValue)
|
|
{
|
|
rooms = rooms.Where(r => r != null && r.RoomLevel == roomLevel.Value).ToList();
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(gameType) && int.TryParse(gameType, out var gameTypeValue))
|
|
{
|
|
rooms = rooms.Where(r => r != null && (int)r.GameType == gameTypeValue).ToList();
|
|
}
|
|
|
|
var total = rooms.Count;
|
|
|
|
if (!string.IsNullOrEmpty(sortField))
|
|
{
|
|
switch (sortField.ToLower())
|
|
{
|
|
case "currentonline":
|
|
rooms = sortOrder?.ToLower() == "asc"
|
|
? rooms.OrderBy(r => r.CurrentOnlinePlayerCount).ToList()
|
|
: rooms.OrderByDescending(r => r.CurrentOnlinePlayerCount).ToList();
|
|
break;
|
|
case "robotcount":
|
|
rooms = sortOrder?.ToLower() == "asc"
|
|
? rooms.OrderBy(r => r.RobotCount).ToList()
|
|
: rooms.OrderByDescending(r => r.RobotCount).ToList();
|
|
break;
|
|
case "roomlevel":
|
|
rooms = sortOrder?.ToLower() == "asc"
|
|
? rooms.OrderBy(r => r.RoomLevel).ToList()
|
|
: rooms.OrderByDescending(r => r.RoomLevel).ToList();
|
|
break;
|
|
default:
|
|
rooms = rooms.OrderByDescending(r => r.RoomId).ToList();
|
|
break;
|
|
}
|
|
}
|
|
|
|
var pagedRooms = rooms.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
|
|
|
|
return this.ToPageResult(pagedRooms, total);
|
|
}
|
|
|
|
[HttpGet("GetAllChessRooms")]
|
|
public async Task<PageResponse<ChessGameRoom>> GetAllChessRooms(
|
|
int pageIndex = 1,
|
|
int pageSize = 20,
|
|
int? state = null,
|
|
int? gameType = null)
|
|
{
|
|
var rooms = _redisService.GetAllChessRooms()?.ToList();
|
|
if (state.HasValue)
|
|
{
|
|
rooms = rooms.Where(r => r != null && r.state == state.Value).ToList();
|
|
}
|
|
|
|
if (gameType.HasValue)
|
|
{
|
|
rooms = rooms.Where(r => r != null && r.gameType == gameType.Value).ToList();
|
|
}
|
|
|
|
var total = rooms.Count;
|
|
|
|
rooms = rooms.OrderByDescending(r => r.CreateTime).ToList();
|
|
|
|
var pagedRooms = rooms.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
|
|
|
|
return this.ToPageResult(pagedRooms, total);
|
|
}
|
|
|
|
[HttpGet("GetChessRoomDetail")]
|
|
public async Task<BaseResponse<ChessGameRoom>> GetChessRoomDetail(string roomId)
|
|
{
|
|
var room = _redisService.GetChessRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<ChessGameRoom>("房间不存在");
|
|
|
|
return this.ToResult(room);
|
|
}
|
|
|
|
[HttpGet("ClearChessRoom")]
|
|
public async Task<BaseResponse<string>> ClearChessRoom(string roomId)
|
|
{
|
|
var room = _redisService.GetChessRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
|
|
int playerCount = 0;
|
|
foreach (var user in room.users.ToList())
|
|
{
|
|
try
|
|
{
|
|
var userRedis = _redisService.GetRedisUserCId(user.userId);
|
|
if (userRedis != null)
|
|
{
|
|
userRedis.CId = "";
|
|
_redisService.SetRedisUserCId(userRedis);
|
|
}
|
|
playerCount++;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "管理员清空象棋房间 清理userRedis失败 roomId={RoomId} userId={UserId}", roomId, user.userId);
|
|
}
|
|
}
|
|
|
|
room.users.Clear();
|
|
room.state = 0;
|
|
room.robotCount = 0;
|
|
room.gold = 0;
|
|
room.gameType = 0;
|
|
room.password = "";
|
|
room.IsGameEnded = false;
|
|
room.EndGameRequests?.Clear();
|
|
room.PendingWinUserId = null;
|
|
room.TimeoutLoserUserId = "";
|
|
room.LastActiveTime = 0;
|
|
_redisService.SetChessRoom(room);
|
|
|
|
return this.ToResult($"已清空房间 {roomId} 的所有玩家({playerCount} 人)");
|
|
}
|
|
|
|
[HttpGet("KickChessPlayer")]
|
|
public async Task<BaseResponse<string>> KickChessPlayer(string roomId, string userId)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(roomId) || string.IsNullOrWhiteSpace(userId))
|
|
return this.ToFailResult<string>("房间ID和玩家ID不能为空");
|
|
|
|
var room = _redisService.GetChessRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
if (room.state == 2)
|
|
return this.ToFailResult<string>("游戏进行中不能直接踢人,请先结束对局");
|
|
if (room.users?.Any(u => u.userId == userId) != true)
|
|
return this.ToFailResult<string>("玩家不在该房间中");
|
|
|
|
await _capPublisher.PublishAsync(TopicKeys.后台踢出象棋玩家, new AdminKickChessPlayerMessage
|
|
{
|
|
RoomId = roomId,
|
|
UserId = userId,
|
|
Reason = "被管理员移出房间"
|
|
});
|
|
|
|
return this.ToResult("踢人指令已提交");
|
|
}
|
|
|
|
[HttpGet("GetChessRoomStatistics")]
|
|
public async Task<BaseResponse<ChessRoomStatistics>> GetChessRoomStatistics()
|
|
{
|
|
var rooms = _redisService.GetAllChessRooms() ?? new List<ChessGameRoom>();
|
|
|
|
var stats = new ChessRoomStatistics
|
|
{
|
|
TotalRooms = rooms.Count,
|
|
EmptyRooms = rooms.Count(r => r.state == 0 &&
|
|
(r.users == null || !r.users.Any(u => u != null && !u.IsLeave)) &&
|
|
r.robotCount == 0),
|
|
WaitingRooms = rooms.Count(r => r.state == 1),
|
|
PlayingRooms = rooms.Count(r => r.state == 2),
|
|
FinishedRooms = rooms.Count(r => r.state == 3),
|
|
TotalPlayers = rooms.SelectMany(r => r.users ?? new List<RedisChessGameUser>()).Count(),
|
|
BlackSidePlayers = rooms.SelectMany(r => r.users ?? new List<RedisChessGameUser>()).Count(u => u.type == 1),
|
|
RedSidePlayers = rooms.SelectMany(r => r.users ?? new List<RedisChessGameUser>()).Count(u => u.type == 2)
|
|
};
|
|
|
|
stats.EmptyRoomRate = stats.TotalRooms == 0
|
|
? 0
|
|
: Math.Round(stats.EmptyRooms * 100.0 / stats.TotalRooms, 2);
|
|
|
|
return this.ToResult(stats);
|
|
}
|
|
|
|
[HttpGet("DeleteChessRoom")]
|
|
public async Task<BaseResponse<string>> DeleteChessRoom(string roomId)
|
|
{
|
|
var room = _redisService.GetChessRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
|
|
_redisService.RemoveChessRoom(roomId);
|
|
|
|
return this.ToResult("已删除房间 " + roomId);
|
|
}
|
|
|
|
[HttpGet("AddChessRobot")]
|
|
public async Task<BaseResponse<string>> AddChessRobot(string roomId, int count)
|
|
{
|
|
var room = _redisService.GetChessRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
|
|
var realPlayers = room.users?.Where(u => u != null && !u.IsLeave).ToList();
|
|
if (realPlayers != null && realPlayers.Count > 0)
|
|
return this.ToFailResult<string>("房间有真人玩家,不能修改机器人数量");
|
|
|
|
room.robotCount += count;
|
|
ApplyRobotStateRule(room);
|
|
_redisService.SetChessRoom(room);
|
|
|
|
return this.ToResult("添加成功");
|
|
}
|
|
|
|
[HttpGet("SetChessRobot")]
|
|
public async Task<BaseResponse<string>> SetChessRobot(string roomId, int count)
|
|
{
|
|
var room = _redisService.GetChessRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
|
|
var realPlayers = room.users?.Where(u => u != null && !u.IsLeave).ToList();
|
|
if (realPlayers != null && realPlayers.Count > 0)
|
|
return this.ToFailResult<string>("房间有真人玩家,不能修改机器人数量");
|
|
|
|
room.robotCount = Math.Clamp(count, 0, 2);
|
|
ApplyRobotStateRule(room);
|
|
_redisService.SetChessRoom(room);
|
|
|
|
return this.ToResult("设置成功");
|
|
}
|
|
|
|
[HttpGet("GetRoomDetail")]
|
|
public async Task<BaseResponse<RedisGameRoom>> GetRoomDetail(string roomId)
|
|
{
|
|
var room = _redisService.GetGameRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<RedisGameRoom>("房间不存在");
|
|
|
|
return this.ToResult(room);
|
|
}
|
|
|
|
[HttpGet("GetUserRoomRealtime")]
|
|
[ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
|
|
public async Task<BaseResponse<UserRoomRealtimeDto>> GetUserRoomRealtime(string userId)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(userId))
|
|
return this.ToFailResult<UserRoomRealtimeDto>("用户ID不能为空");
|
|
|
|
var dto = new UserRoomRealtimeDto { Found = true };
|
|
|
|
var user = await _userMongo.FindByIdAsync(userId);
|
|
var factor = user?.PlayerFactor ?? new PlayerFactor();
|
|
|
|
dto.Gold = user?.Assets?.Gold ?? 0;
|
|
dto.TotalRechargeGold = user?.Static?.TotalRechargeGold ?? 0;
|
|
|
|
RedisGameRoom? matchedRoom = null;
|
|
RedisGamePlayer? matchedPlayer = null;
|
|
var session = _redisService.GetRedisUserCId(userId);
|
|
if (!string.IsNullOrWhiteSpace(session?.RoomId))
|
|
{
|
|
matchedRoom = _redisService.GetGameRoom(session.RoomId);
|
|
matchedPlayer = matchedRoom?.Players?
|
|
.FirstOrDefault(p => p != null && !p.IsBot && p.UserId == userId);
|
|
}
|
|
|
|
if (matchedPlayer == null)
|
|
{
|
|
var fallback = _redisService.GetGameRoomAllList()
|
|
.Where(r => r != null && r.Players != null)
|
|
.SelectMany(r => r.Players.Select(p => new { Room = r, Player = p }))
|
|
.FirstOrDefault(x => x.Player != null && !x.Player.IsBot && x.Player.UserId == userId);
|
|
matchedRoom = fallback?.Room;
|
|
matchedPlayer = fallback?.Player;
|
|
}
|
|
|
|
if (matchedRoom != null && matchedPlayer != null)
|
|
{
|
|
var room = matchedRoom;
|
|
var player = matchedPlayer;
|
|
dto.InRoom = true;
|
|
dto.RoomId = room.RoomId;
|
|
dto.RoomName = room.RoomName;
|
|
dto.GameType = (int)room.GameType;
|
|
dto.GameTypeName = room.GameType.ToString();
|
|
dto.RoomLevel = room.RoomLevel;
|
|
dto.RoomPartition = room.RoomPartition;
|
|
dto.RoomNumber = room.RoomNumber;
|
|
dto.SystemFactor = room.SystemFactor;
|
|
dto.CurrentOnlinePlayerCount = room.CurrentOnlinePlayerCount;
|
|
dto.RobotCount = room.RobotCount;
|
|
dto.Position = player.Position;
|
|
dto.UserName = player.UserName;
|
|
dto.UserNumber = player.UserNumber;
|
|
dto.Gold = player.Gold;
|
|
dto.MaxGold = player.MaxGold;
|
|
dto.BeginCoin = player.BeginCoin;
|
|
dto.CannonMultiple = player.CannonMultiple;
|
|
dto.CannonId = player.CannonId;
|
|
dto.State = player.State;
|
|
dto.IsAfk = player.IsAfk;
|
|
dto.TotalRechargeGold = player.TotalRechargeGold;
|
|
|
|
var delta = player.Gold - player.BeginCoin;
|
|
dto.WinGold = delta > 0 ? delta : 0;
|
|
dto.LoseGold = delta < 0 ? -delta : 0;
|
|
|
|
var realtimeFactor = player.PlayerFactor ?? new PlayerFactor();
|
|
if (realtimeFactor.ViolateValue > 0)
|
|
factor.ViolateValue = realtimeFactor.ViolateValue;
|
|
}
|
|
|
|
dto.IsBlack = factor.IsBlack;
|
|
dto.IsIgnore = factor.IsIgnore;
|
|
dto.ViolateValue = factor.ViolateValue;
|
|
dto.AdditionalFactor = factor.AdditionalFactor;
|
|
dto.MissRate = factor.MissRate;
|
|
dto.CompensateQuota = factor.CompensateQuota;
|
|
dto.CompensateStartGold = factor.CompensateStartGold;
|
|
dto.CompensateTargetGold = factor.CompensateTargetGold;
|
|
if (factor.CompensateQuota <= 0)
|
|
dto.CompensateRemainingQuota = 0;
|
|
else
|
|
dto.CompensateRemainingQuota = factor.CompensateTargetGold > 0
|
|
? Math.Max(0, factor.CompensateTargetGold - dto.Gold)
|
|
: Math.Max(0, factor.CompensateQuota);
|
|
dto.PenaltyQuota = factor.PenaltyQuota;
|
|
dto.StartingBonus = factor.StartingBonus;
|
|
dto.CompensateRateBoss = factor.CompensateRate?.BossRate ?? 0;
|
|
dto.CompensateRateGold = factor.CompensateRate?.GoldRate ?? 0;
|
|
dto.CompensateRateSpecial = factor.CompensateRate?.SpecialRate ?? 0;
|
|
dto.CompensateRateOrdinary = factor.CompensateRate?.Ordinary ?? 0;
|
|
dto.PenaltyRateBoss = factor.PenaltyRate?.BossRate ?? 0;
|
|
dto.PenaltyRateGold = factor.PenaltyRate?.GoldRate ?? 0;
|
|
dto.PenaltyRateSpecial = factor.PenaltyRate?.SpecialRate ?? 0;
|
|
dto.PenaltyRateOrdinary = factor.PenaltyRate?.Ordinary ?? 0;
|
|
|
|
return this.ToResult(dto);
|
|
}
|
|
|
|
[HttpGet("AddRobot")]
|
|
public async Task<BaseResponse<string>> AddRobot(string roomId, int count)
|
|
{
|
|
var room = _redisService.GetGameRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
|
|
if (count < 0)
|
|
return this.ToFailResult<string>("机器人增加数量不能小于0");
|
|
|
|
var realPlayerCount = room.Players?.Count(p => !p.IsBot) ?? room.CurrentOnlinePlayerCount;
|
|
room.CurrentOnlinePlayerCount = realPlayerCount;
|
|
room.RobotCount = Math.Clamp(room.RobotCount + count, 0, Math.Max(0, room.MaxPlayerCount - realPlayerCount));
|
|
if (room.Players != null)
|
|
{
|
|
var excessBots = room.Players.Where(p => p.IsBot).Skip(room.RobotCount).ToList();
|
|
foreach (var bot in excessBots)
|
|
{
|
|
_redisService.ClearBulletIds(roomId, bot.UserId);
|
|
room.Players.Remove(bot);
|
|
}
|
|
room.RobotCount = Math.Max(room.RobotCount, room.Players.Count(p => p.IsBot));
|
|
}
|
|
_redisService.SetGameRoom(room);
|
|
|
|
return this.ToResult($"已为房间 {roomId} 添加 {count} 个机器人");
|
|
}
|
|
|
|
[HttpGet("SetRobotCount")]
|
|
public async Task<BaseResponse<string>> SetRobotCount(string roomId, int count)
|
|
{
|
|
var room = _redisService.GetGameRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
|
|
if (count < 0)
|
|
return this.ToFailResult<string>("机器人数量不能小于0");
|
|
|
|
var realPlayerCount = room.Players?.Count(p => !p.IsBot) ?? room.CurrentOnlinePlayerCount;
|
|
room.CurrentOnlinePlayerCount = realPlayerCount;
|
|
room.RobotCount = Math.Clamp(count, 0, Math.Max(0, room.MaxPlayerCount - realPlayerCount));
|
|
if (room.Players != null)
|
|
{
|
|
var excessBots = room.Players.Where(p => p.IsBot).Skip(room.RobotCount).ToList();
|
|
foreach (var bot in excessBots)
|
|
{
|
|
_redisService.ClearBulletIds(roomId, bot.UserId);
|
|
room.Players.Remove(bot);
|
|
}
|
|
room.RobotCount = Math.Max(room.RobotCount, room.Players.Count(p => p.IsBot));
|
|
}
|
|
_redisService.SetGameRoom(room);
|
|
|
|
return this.ToResult($"已将房间 {roomId} 的机器人数量设置为 {count}");
|
|
}
|
|
|
|
[HttpGet("RegenerateAllBotIds")]
|
|
public async Task<BaseResponse<string>> RegenerateAllBotIds()
|
|
{
|
|
var rooms = GetAllRoomsFromRedis()?.ToList() ?? new List<RedisGameRoom>();
|
|
int totalBots = 0;
|
|
|
|
foreach (var room in rooms)
|
|
{
|
|
if (room?.Players == null || room.Players.Count == 0)
|
|
continue;
|
|
|
|
var bots = room.Players.Where(p => p.IsBot).ToList();
|
|
if (bots.Count == 0)
|
|
continue;
|
|
|
|
foreach (var bot in bots)
|
|
{
|
|
var oldUserId = bot.UserId;
|
|
bot.UserId = Guid.NewGuid().ToString("N");
|
|
bot.UserNumber = Common.Utils.RandomHelper.RandomNumbers(8);
|
|
totalBots++;
|
|
}
|
|
|
|
_redisService.SetGameRoom(room);
|
|
}
|
|
|
|
|
|
return this.ToResult($"已刷新 {totalBots} 个机器人编号(涉及 {rooms.Count(r => r?.Players?.Any(p => p.IsBot) == true)} 个房间)");
|
|
}
|
|
|
|
[HttpGet("ClearRoom")]
|
|
public async Task<BaseResponse<string>> ClearRoom(string roomId)
|
|
{
|
|
var room = _redisService.GetGameRoom(roomId);
|
|
if (room == null)
|
|
return this.ToFailResult<string>("房间不存在");
|
|
|
|
int success = 0, fail = 0;
|
|
|
|
foreach (var player in room.Players.Where(p => !p.IsBot).ToList())
|
|
{
|
|
try
|
|
{
|
|
await _capPublisher.PublishAsync(TopicKeys.游戏金币结算, new
|
|
{
|
|
UserId = player.UserId,
|
|
BeforeGold = player.BeginCoin,
|
|
AfterGold = player.Gold,
|
|
Remark = "管理员清空房间结算",
|
|
RoomName = room.RoomName ?? "",
|
|
RoomInfo = room.RoomId ?? ""
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "管理员清空房间 CAP 结算失败 roomId={RoomId} userId={UserId}", roomId, player.UserId);
|
|
}
|
|
|
|
try { _redisService.ClearBulletIds(roomId, player.UserId); }
|
|
catch (Exception ex) { _logger.LogError(ex, "管理员清空房间 清理子弹失败 roomId={RoomId} userId={UserId}", roomId, player.UserId); }
|
|
|
|
try
|
|
{
|
|
var userRedis = _redisService.GetRedisUserCId(player.UserId);
|
|
if (userRedis != null && userRedis.RoomId == roomId)
|
|
{
|
|
userRedis.RoomId = "";
|
|
userRedis.CId = "";
|
|
_redisService.SetRedisUserCId(userRedis);
|
|
}
|
|
success++;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "管理员清空房间 清理userRedis失败 roomId={RoomId} userId={UserId}", roomId, player.UserId);
|
|
fail++;
|
|
}
|
|
}
|
|
|
|
foreach (var player in room.Players.Where(p => p.IsBot).ToList())
|
|
{
|
|
try { _redisService.ClearBulletIds(roomId, player.UserId); }
|
|
catch { }
|
|
}
|
|
|
|
var robotCount = room.RobotCount;
|
|
room.Players.Clear();
|
|
room.CurrentOnlinePlayerCount = 0;
|
|
room.RobotCount = Math.Clamp(robotCount, 0, room.MaxPlayerCount);
|
|
_redisService.SetGameRoom(room);
|
|
|
|
var msg = fail > 0
|
|
? $"已清空房间 {roomId}:成功 {success} 人,失败 {fail} 人"
|
|
: $"已清空房间 {roomId} 的所有玩家({success} 人)";
|
|
return this.ToResult(msg);
|
|
}
|
|
|
|
[HttpGet("GetRoomStatistics")]
|
|
public async Task<BaseResponse<RoomStatistics>> GetRoomStatistics()
|
|
{
|
|
var rooms = GetAllRoomsFromRedis();
|
|
if (rooms == null || rooms.Count() == 0)
|
|
{
|
|
return this.ToResult(new RoomStatistics());
|
|
}
|
|
var stats = new RoomStatistics
|
|
{
|
|
TotalRooms = rooms?.Count()?? 0,
|
|
TotalPlayers = rooms?.Where(_=>_!=null).Sum(r => r.CurrentOnlinePlayerCount) ?? 0,
|
|
TotalRobots = rooms?.Where(_ => _ != null).Sum(r => r.RobotCount) ?? 0
|
|
};
|
|
|
|
if (rooms != null && rooms.Count() > 0)
|
|
{
|
|
stats.RoomsByLevel = rooms.Where(_ => _ != null).GroupBy(r => r.RoomLevel)
|
|
.ToDictionary(g => g.Key, g => g.Count());
|
|
|
|
stats.RoomsByType = rooms.Where(_ => _ != null).GroupBy(r => r.GameType.ToString())
|
|
.ToDictionary(g => g.Key, g => g.Count());
|
|
}
|
|
|
|
return this.ToResult(stats);
|
|
}
|
|
|
|
[HttpGet("RepairChessRooms")]
|
|
public async Task<BaseResponse<string>> RepairChessRooms()
|
|
{
|
|
var rooms = _redisService.GetAllChessRooms();
|
|
if (rooms == null || rooms.Count == 0)
|
|
return this.ToFailResult<string>("没有象棋房间");
|
|
|
|
int fixedCount = 0;
|
|
foreach (var room in rooms)
|
|
{
|
|
if (room.users != null && room.users.Any(u => !u.IsLeave))
|
|
continue;
|
|
|
|
ApplyRobotStateRule(room);
|
|
_redisService.SetChessRoom(room);
|
|
fixedCount++;
|
|
}
|
|
|
|
return this.ToResult($"已修复 {fixedCount} 个象棋房间");
|
|
}
|
|
|
|
[HttpGet("InitRooms")]
|
|
public async Task<BaseResponse<string>> InitRooms()
|
|
{
|
|
_redisService.RemoveGameRoomAll();
|
|
_redisService.ClearAllChessRooms();
|
|
await _gameConfigService.InitRoom();
|
|
|
|
var config = await _gameConfigService.Get();
|
|
var chessRoomConfigs = config?.RoomConfigs.Where(c => c.GameType == GameTypeEnum.中国象棋).ToList();
|
|
if (chessRoomConfigs != null)
|
|
{
|
|
foreach (var roomConfig in chessRoomConfigs)
|
|
{
|
|
for (int y = 1; y <= roomConfig.RoomPartitionNum; y++)
|
|
{
|
|
for (int i = 0; i < roomConfig.RoomCount; i++)
|
|
{
|
|
var room = new ChessGameRoom
|
|
{
|
|
RoomId = $"{(int)GameTypeEnum.中国象棋}{y}{i.ToString("00")}",
|
|
CreateTime = DateTime.Now,
|
|
createUserId = "",
|
|
gameType = 0,
|
|
gold = roomConfig.RoomGoldLimit,
|
|
Id = Guid.NewGuid().ToString(),
|
|
users = new List<RedisChessGameUser>(),
|
|
EndGameRequests = new Dictionary<string, long>(),
|
|
LastActiveTime = 0,
|
|
TimeoutSeconds = 60,
|
|
robotCount = 0
|
|
};
|
|
ApplyRobotStateRule(room);
|
|
_redisService.SetChessRoom(room);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return this.ToResult("房间初始化成功");
|
|
}
|
|
|
|
[HttpGet("ReInitChessRooms")]
|
|
public async Task<BaseResponse<string>> ReInitChessRooms()
|
|
{
|
|
var config = await _gameConfigService.Get();
|
|
var chessConfig = config?.ChessConfig;
|
|
if (chessConfig == null)
|
|
return this.ToFailResult<string>("象棋配置不存在");
|
|
|
|
_redisService.ClearAllChessRooms();
|
|
|
|
var chessRoomConfigs = config.RoomConfigs.Where(c => c.GameType == GameTypeEnum.中国象棋).ToList();
|
|
if (chessRoomConfigs.Count == 0)
|
|
return this.ToFailResult<string>("未找到象棋房间配置");
|
|
|
|
int count = 0;
|
|
foreach (var roomConfig in chessRoomConfigs)
|
|
{
|
|
for (int y = 1; y <= roomConfig.RoomPartitionNum; y++)
|
|
{
|
|
for (int i = 0; i < roomConfig.RoomCount; i++)
|
|
{
|
|
var room = new ChessGameRoom
|
|
{
|
|
RoomId = $"{(int)GameTypeEnum.中国象棋}{y}{i.ToString("00")}",
|
|
CreateTime = DateTime.Now,
|
|
createUserId = "",
|
|
gameType = 0,
|
|
gold = roomConfig.RoomGoldLimit,
|
|
Id = Guid.NewGuid().ToString(),
|
|
users = new List<RedisChessGameUser>(),
|
|
EndGameRequests = new Dictionary<string, long>(),
|
|
LastActiveTime = 0,
|
|
TimeoutSeconds = 60,
|
|
robotCount = 0
|
|
};
|
|
ApplyRobotStateRule(room);
|
|
_redisService.SetChessRoom(room);
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return this.ToResult($"象棋房间已重新初始化,共 {count} 个房间");
|
|
}
|
|
|
|
private IEnumerable<RedisGameRoom> GetAllRoomsFromRedis()
|
|
{
|
|
|
|
return _redisService.GetGameRoomAllList();
|
|
}
|
|
|
|
private static void ApplyRobotStateRule(ChessGameRoom room)
|
|
{
|
|
var userCount = room.users?.Count ?? 0;
|
|
var totalCount = userCount + room.robotCount;
|
|
|
|
if (totalCount == 0)
|
|
{
|
|
room.state = 0;
|
|
room.password = "";
|
|
}
|
|
else if (totalCount == 1)
|
|
{
|
|
room.state = 1;
|
|
if (string.IsNullOrEmpty(room.password))
|
|
room.password = Random.Shared.Next(100000, 999999).ToString();
|
|
}
|
|
else
|
|
{
|
|
room.state = 2;
|
|
if (string.IsNullOrEmpty(room.password))
|
|
room.password = Random.Shared.Next(100000, 999999).ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RoomStatistics
|
|
{
|
|
public int TotalRooms { get; set; } = 0;
|
|
|
|
public int TotalPlayers { get; set; } = 0;
|
|
|
|
public int TotalRobots { get; set; } = 0;
|
|
|
|
public Dictionary<int, int> RoomsByLevel { get; set; } = new();
|
|
|
|
public Dictionary<string, int> RoomsByType { get; set; } = new();
|
|
}
|
|
|
|
public class ChessRoomStatistics
|
|
{
|
|
public int TotalRooms { get; set; } = 0;
|
|
|
|
public int EmptyRooms { get; set; } = 0;
|
|
|
|
public double EmptyRoomRate { get; set; } = 0;
|
|
|
|
public int WaitingRooms { get; set; } = 0;
|
|
|
|
public int PlayingRooms { get; set; } = 0;
|
|
|
|
public int FinishedRooms { get; set; } = 0;
|
|
|
|
public int TotalPlayers { get; set; } = 0;
|
|
|
|
public int BlackSidePlayers { get; set; } = 0;
|
|
|
|
public int RedSidePlayers { get; set; } = 0;
|
|
}
|
|
|
|
public class UserRoomRealtimeDto
|
|
{
|
|
public bool Found { get; set; } = false;
|
|
|
|
public bool InRoom { get; set; } = false;
|
|
|
|
public long WinGold { get; set; } = 0;
|
|
|
|
public long LoseGold { get; set; } = 0;
|
|
|
|
public string RoomId { get; set; } = string.Empty;
|
|
|
|
public string RoomName { get; set; } = string.Empty;
|
|
|
|
public int GameType { get; set; }
|
|
|
|
public string GameTypeName { get; set; } = string.Empty;
|
|
|
|
public int RoomLevel { get; set; }
|
|
|
|
public int RoomPartition { get; set; }
|
|
|
|
public int RoomNumber { get; set; }
|
|
|
|
public double SystemFactor { get; set; } = 1.0;
|
|
|
|
public int CurrentOnlinePlayerCount { get; set; }
|
|
|
|
public int RobotCount { get; set; }
|
|
|
|
public int Position { get; set; }
|
|
|
|
public string UserName { get; set; } = string.Empty;
|
|
|
|
public string UserNumber { get; set; } = string.Empty;
|
|
|
|
public long Gold { get; set; }
|
|
|
|
public long BeginCoin { get; set; }
|
|
|
|
public long MaxGold { get; set; }
|
|
|
|
public int CannonMultiple { get; set; }
|
|
|
|
public string CannonId { get; set; } = string.Empty;
|
|
|
|
public int State { get; set; }
|
|
|
|
public bool IsAfk { get; set; }
|
|
|
|
public long TotalRechargeGold { get; set; }
|
|
|
|
public bool IsBlack { get; set; }
|
|
|
|
public bool IsIgnore { get; set; }
|
|
|
|
public double ViolateValue { get; set; }
|
|
|
|
public double AdditionalFactor { get; set; }
|
|
|
|
public double MissRate { get; set; }
|
|
|
|
public int CompensateQuota { get; set; }
|
|
|
|
public long CompensateStartGold { get; set; }
|
|
|
|
public long CompensateTargetGold { get; set; }
|
|
|
|
public long CompensateRemainingQuota { get; set; }
|
|
|
|
public int PenaltyQuota { get; set; }
|
|
|
|
public long StartingBonus { get; set; }
|
|
|
|
public double CompensateRateBoss { get; set; }
|
|
|
|
public double CompensateRateGold { get; set; }
|
|
|
|
public double CompensateRateSpecial { get; set; }
|
|
|
|
public double CompensateRateOrdinary { get; set; }
|
|
|
|
public double PenaltyRateBoss { get; set; }
|
|
|
|
public double PenaltyRateGold { get; set; }
|
|
|
|
public double PenaltyRateSpecial { get; set; }
|
|
|
|
public double PenaltyRateOrdinary { get; set; }
|
|
}
|
|
}
|