public PendingGame(string[] userIds, Server server, RiichiGame log) { UserIds = userIds; Log = log; Server = server; usersOk = new HashSet <string>(); usersNo = new HashSet <string>(); }
public static RiichiGame ParseTenhouFormatGame(string payload, GameType gameType) { JsonTextReader reader = new JsonTextReader(new StringReader(payload)); reader.Read(); if (reader.TokenType != JsonToken.StartObject) { throw new System.Exception(); } var game = new RiichiGame(); game.FullLog = payload; reader.Read(); game.GameType = gameType; game.Ver = ParseStrProp("ver", reader); game.Ref = ParseStrProp("ref", reader); game.Rounds = ParseLog(reader); game.Ratingc = ParseStrProp("ratingc", reader); game.Rule = ParseRule(reader); game.Lobby = ParseIntProp("lobby", reader); game.Dan = ParseStrArray(reader, "dan"); game.Rate = ParseFloatArray(reader, "rate"); game.Sx = ParseStrArray(reader, "sx"); var sc = ParseStrArray(reader, "sc"); game.FinalScores = GetScores(sc); game.FinalRankDeltas = GetRanks(sc); game.Names = ParseStrArray(reader, "name"); try { game.UserIds = ParseStrArray(reader, "mjsoulId"); game.Title = ParseStrArray(reader, "title"); } catch { game.UserIds = new string[game.Names.Length]; } return(game); }
public static (Game, List <Ranking>) RecordOnlineGame(RiichiGame gameLog, Server serverWithUsers) { var dbCon = DBConnection.Instance(); var logId = gameLog.Ref; var fullLog = gameLog.FullLog; var gameType = gameLog.GameType; var playerNames = gameLog.Names; var playerMjIds = gameLog.UserIds; //mahjongsoul internal Ids var scores = gameLog.FinalScores; var userList = serverWithUsers.Users; var platform = gameLog.GameType; // TODO feed timestamp from game data if (playerNames.Length < 4) { throw new Exception("No sanma allowed"); } var nameIdScorePos = new List <(string, string, int, int)>(); //0=start east, 1=start south,... for (int i = 0; i < 4; i++) { nameIdScorePos.Add((playerNames[i], playerMjIds[i], scores[i], i)); } // We sort them by comparing their scores minus their initial pos, since initPos<<<score it's ok, I guess? nameIdScorePos.Sort((tuple1, tuple2) => (tuple2.Item3 - tuple2.Item4).CompareTo((tuple1.Item3 - tuple1.Item4))); int[] sortedScores = nameIdScorePos.Select(x => x.Item3).ToArray(); string[] sortedNames = nameIdScorePos.Select(x => x.Item1).ToArray(); string[] sortedMjIds = nameIdScorePos.Select(x => x.Item2).ToArray(); string[] sortedPlayerIds = new string[4]; List <int> toRecordMjId = new List <int>(); for (int i = 0; i < 4; i++) { User user = null; switch (gameType) { //Get the User objects from the Name or Ids present in the log case GameType.Mahjsoul: user = userList.Find(x => x.MahjsoulUserId == sortedMjIds[i]); if (user == null) { user = userList.Find(x => x.MahjsoulName == sortedNames[i]); toRecordMjId.Add(i); } break; case GameType.Tenhou: user = userList.Find(x => x.TenhouName == sortedNames[i]); break; default: throw (new Exception("Bad game type, can't record")); } if (user == null) { throw (new Exception($"couldn't find player with this name on the server: {sortedNames[i]}")); } sortedPlayerIds[i] = user.Id; } if (dbCon.IsConnect()) { using var command = SqlClientFactory.Instance.CreateCommand(); command.Connection = dbCon.Connection; command.CommandText = $"INSERT INTO {GameTableName} ({User1IdCol}, {User2IdCol}, {User3IdCol}, {User4IdCol}, {User1ScoreCol}, {User2ScoreCol}, {User3ScoreCol}, {User4ScoreCol}, {IdCol}, {FullLogIdCol}, {PlatformCol}, {ServerIdCol}) " + $"VALUES (@playerId1, @playerId2, @playerId3, @playerId4, {sortedScores[0]}, {sortedScores[1]}, {sortedScores[2]}, {sortedScores[3]}, @logId, @fullLog, @platform, @serverId);"; command.CommandType = CommandType.Text; command.Parameters.Add(new SqlParameter("@playerId1", SqlDbType.NVarChar) { Value = sortedPlayerIds[0] }); command.Parameters.Add(new SqlParameter("@playerId2", SqlDbType.NVarChar) { Value = sortedPlayerIds[1] }); command.Parameters.Add(new SqlParameter("@playerId3", SqlDbType.NVarChar) { Value = sortedPlayerIds[2] }); command.Parameters.Add(new SqlParameter("@playerId4", SqlDbType.NVarChar) { Value = sortedPlayerIds[3] }); command.Parameters.Add(new SqlParameter("@fullLog", SqlDbType.NVarChar) { Value = fullLog }); command.Parameters.Add(new SqlParameter("@logId", SqlDbType.NVarChar) { Value = logId }); command.Parameters.Add(new SqlParameter("@platform", SqlDbType.NVarChar) { Value = platform }); command.Parameters.Add(new SqlParameter("@serverId", SqlDbType.NVarChar) { Value = serverWithUsers.Id }); command.ExecuteNonQuery(); //Add the majsouldID to the new users: foreach (var idx in toRecordMjId) { UserDbService.SetMahjsoulUserId(sortedPlayerIds[idx], sortedMjIds[idx]); } var config = LeagueConfigDbService.GetLeagueConfig(serverWithUsers.LeagueConfigId); var game = GetGameFromLogId(logId, serverWithUsers); var rankings = RankingDbService.UpdateRankings(game, config); return(game, rankings); } throw (new DbConnectionException()); }
//Checks if a log is compatible with a player base private async Task <List <User> > GetUsersFromLog(RiichiGame log, List <User> users, CommandContext ctx) { int nbPlayers = log.Names.Length; List <string> notFound = new List <string>(); List <User> foundUsers = new List <User>(); for (int i = 0; i < nbPlayers; i++) { User foundUser = null; foreach (var user in users) { switch (log.GameType) { case GameType.Mahjsoul: bool matchName = user.MahjsoulName != null && user.MahjsoulName == log.Names[i]; bool matchId = user.MahjsoulUserId != null && user.MahjsoulUserId == log.UserIds[i]; if (matchId && !matchName) { UserDbService.SetMahjsoulName(user.Id, log.Names[i]); await ctx.RespondAsync($"Detected Bad user name for <@{user.Id}>. Changed from {user.MahjsoulName} to {log.Names[i]}, don't thank me ;)"); } if (matchName && !matchId) { UserDbService.SetMahjsoulUserId(user.Id, log.UserIds[i]); } if (matchName || matchId) { foundUser = user; } break; case GameType.Tenhou: if (user.TenhouName != null && user.TenhouName == log.Names[i]) { foundUser = user; } break; default: throw new Exception("Unsupported game type"); } if (foundUser != null) { break; } } if (foundUser == null) { notFound.Add(log.Names[i]); } else { foundUsers.Add(foundUser); } } if (notFound.Count > 0) { { throw new Exception($"The log has names that do not match with any players: {string.Join(", ", notFound)}"); } } return(foundUsers); }