Пример #1
0
        public async Task<IActionResult> PostSubmitModular()
        {
            if (!Directory.Exists("data/replays"))
                Directory.CreateDirectory("data/replays");
            
            string encScore = Request.Form["score"];
            string iv = Request.Form["iv"];
            string osuver = Request.Form["osuver"];
            string passwd = Request.Form["pass"];

            var (pass, score) = ScoreSubmissionParser.ParseScore(encScore, iv, osuver);
            var dbUser = await DbUser.GetDbUser(_ctx, score.UserName);

            if (dbUser == null)
                return Ok("error: pass");
            
            if (!dbUser.IsPassword(passwd))
                return Ok("error: pass");

            if (!_ps.TryGet(dbUser.Id, out var pr))
                return Ok("error: pass"); // User not logged in in Bancho!

            if (!pass || !RankedMods.IsRanked(score.Mods))
            {
                var lb = await DbLeaderboard.GetLeaderboardAsync(_ctx, dbUser);

                lb.IncreasePlaycount(score.PlayMode);
                lb.IncreaseScore((ulong) score.TotalScore, false, score.PlayMode);

                await lb.SaveChanges(_ctx);
                
                // Send to other People
                await _ev.RunEvent(
                    EventType.BanchoUserStatsRequest,
                    new BanchoUserStatsRequestArgs {UserIds = new List<int> {score.Id}, Pr = pr}
                );

                // Send to self
                await _ev.RunEvent(
                    EventType.BanchoSendUserStatus,
                    new BanchoSendUserStatusArgs {Status = pr.Status, Pr = pr}
                );

                return Ok("Thanks for your hard work! onii-chyan~"); // even though, we're Sora, we can still be cute!
            }

            var replayFileData = Request.Form.Files.GetFile("score");

            var dbScore = new DbScore
            {
                Accuracy = score.ComputeAccuracy(),
                Count100 = score.Count100,
                Count50 = score.Count50,
                Count300 = score.Count300,
                Date = score.Date,
                Mods = score.Mods,
                CountGeki = score.CountGeki,
                CountKatu = score.CountKatu,
                CountMiss = score.CountMiss,
                FileMd5 = score.FileMd5,
                MaxCombo = score.MaxCombo,
                PlayMode = score.PlayMode,
                ScoreOwner = dbUser,
                TotalScore = score.TotalScore,
                UserId = dbUser.Id
            };

            await _pisstaube.DownloadBeatmapAsync(dbScore.FileMd5);

            await using (var m = new MemoryStream())
            {
                replayFileData.CopyTo(m);
                m.Position = 0;
                dbScore.ReplayMd5 = Hex.ToHex(Crypto.GetMd5(m)) ?? string.Empty;
                if (!string.IsNullOrEmpty(dbScore.ReplayMd5))
                {
                    await using var replayFile = System.IO.File.Create($"data/replays/{dbScore.ReplayMd5}");
                    m.Position = 0;
                    m.WriteTo(replayFile);
                    m.Close();
                    replayFile.Close();
                }
            }

            dbScore.PerformancePoints = dbScore.ComputePerformancePoints();

            var oldScore = await DbScore.GetLatestScore(_ctx, dbScore);

            var oldLb = await DbLeaderboard.GetLeaderboardAsync(_ctx, dbScore.ScoreOwner);
            var oldStdPos = oldLb.GetPosition(_ctx, dbScore.PlayMode);
            
            var oldAcc = oldLb.GetAccuracy(_ctx, dbScore.PlayMode);
            double newAcc;

            if (oldScore != null && oldScore.TotalScore <= dbScore.TotalScore)
            {
                _ctx.Remove(oldScore);
                System.IO.File.Delete($"data/replays/{oldScore.ReplayMd5}");

                await DbScore.InsertScore(_ctx, dbScore);
            }
            else if (oldScore == null)
            {
                await DbScore.InsertScore(_ctx, dbScore);
            }
            else
            {
                System.IO.File.Delete($"data/replays/{oldScore.ReplayMd5}");
            }

            var newlb = await DbLeaderboard.GetLeaderboardAsync(_ctx, dbScore.ScoreOwner);

            newlb.IncreasePlaycount(dbScore.PlayMode);
            newlb.IncreaseScore((ulong) dbScore.TotalScore, true, dbScore.PlayMode);
            newlb.IncreaseScore((ulong) dbScore.TotalScore, false, dbScore.PlayMode);

            newlb.UpdatePp(_ctx, dbScore.PlayMode);

            await newlb.SaveChanges(_ctx);

            var newStdPos = newlb.GetPosition(_ctx, dbScore.PlayMode);
            newAcc = newlb.GetAccuracy(_ctx, dbScore.PlayMode);

            var newScore = await DbScore.GetLatestScore(_ctx, dbScore);

            var set = await _pisstaube.FetchBeatmapSetAsync(dbScore.FileMd5);

            var bm = set?.ChildrenBeatmaps.First(x => x.FileMD5 == dbScore.FileMd5) ?? new Beatmap();

            ulong oldRankedScore;
            ulong newRankedScore;

            double oldPp;
            double newPp;

            switch (dbScore.PlayMode)
            {
                case PlayMode.Osu:
                    oldRankedScore = oldLb.RankedScoreOsu;
                    newRankedScore = newlb.RankedScoreOsu;

                    oldPp = oldLb.PerformancePointsOsu;
                    newPp = newlb.PerformancePointsOsu;
                    break;
                case PlayMode.Taiko:
                    oldRankedScore = oldLb.RankedScoreTaiko;
                    newRankedScore = newlb.RankedScoreTaiko;

                    oldPp = oldLb.PerformancePointsTaiko;
                    newPp = newlb.PerformancePointsTaiko;
                    break;
                case PlayMode.Ctb:
                    oldRankedScore = oldLb.RankedScoreCtb;
                    newRankedScore = newlb.RankedScoreCtb;

                    oldPp = oldLb.PerformancePointsCtb;
                    newPp = newlb.PerformancePointsCtb;
                    break;
                case PlayMode.Mania:
                    oldRankedScore = oldLb.RankedScoreMania;
                    newRankedScore = newlb.RankedScoreMania;

                    oldPp = oldLb.PerformancePointsMania;
                    newPp = newlb.PerformancePointsMania;
                    break;
                default:
                    return Ok("");
            }

            var newScorePosition = newScore != null ? await newScore.Position(_ctx) : 0;
            var oldScorePosition = oldScore != null ? await oldScore.Position(_ctx) : 0;
            
            if (newScorePosition == 1)
                _sora.SendMessage(
                    $"[http://{_config.Server.ScreenShotHostname}/{dbScore.ScoreOwner.Id} {dbScore.ScoreOwner.UserName}] " +
                    $"has reached #1 on [https://osu.ppy.sh/b/{bm.BeatmapID} {set?.Title} [{bm.DiffName}]] " +
                    $"using {ModUtil.ToString(newScore.Mods)} " +
                    $"Good job! +{newScore.PerformancePoints:F}PP",
                    "#announce",
                    false
                );

            Logger.Info(
                $"{LCol.RED}{dbScore.ScoreOwner.UserName}",
                $"{LCol.PURPLE}( {dbScore.ScoreOwner.Id} ){LCol.WHITE}",
                $"has just submitted a Score! he earned {LCol.BLUE}{newScore?.PerformancePoints:F}PP",
                $"{LCol.WHITE}with an Accuracy of {LCol.RED}{newScore?.Accuracy * 100:F}",
                $"{LCol.WHITE}on {LCol.YELLOW}{set?.Title} [{bm.DiffName}]",
                $"{LCol.WHITE}using {LCol.BLUE}{ModUtil.ToString(newScore?.Mods ?? Mod.None)}"
            );

            var bmChart = new Chart(
                "beatmap",
                "Beatmap Ranking",
                $"https://osu.ppy.sh/b/{bm.BeatmapID}",
                oldScorePosition,
                newScorePosition,
                oldScore?.MaxCombo ?? 0,
                newScore?.MaxCombo ?? 0,
                oldScore?.Accuracy * 100 ?? 0,
                newScore?.Accuracy * 100 ?? 0,
                (ulong) (oldScore?.TotalScore ?? 0),
                (ulong) (newScore?.TotalScore ?? 0),
                oldScore?.PerformancePoints ?? 0,
                newScore?.PerformancePoints ?? 0,
                newScore?.Id ?? 0
            );

            var overallChart = new Chart(
                "overall",
                "Global Ranking",
                $"https://osu.ppy.sh/u/{dbUser.Id}",
                (int) oldStdPos,
                (int) newStdPos,
                0,
                0,
                oldAcc * 100,
                newAcc * 100,
                oldRankedScore,
                newRankedScore,
                oldPp,
                newPp,
                newScore?.Id ?? 0,
                AchievementProcessor.ProcessAchievements(
                    _ctx, dbScore.ScoreOwner, score, bm, set, oldLb, newlb
                )
            );

            pr["LB"] = newlb;
            pr.Stats.Accuracy = (float) newlb.GetAccuracy(_ctx, score.PlayMode);
            pr.Stats.Position = newlb.GetPosition(_ctx, score.PlayMode);
            switch (score.PlayMode)
            {
                case PlayMode.Osu:
                    pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsOsu;
                    pr.Stats.TotalScore = (ushort) newlb.TotalScoreOsu;
                    pr.Stats.RankedScore = (ushort) newlb.RankedScoreOsu;
                    pr.Stats.PlayCount = (ushort) newlb.PlayCountOsu;
                    break;
                case PlayMode.Taiko:
                    pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsTaiko;
                    pr.Stats.TotalScore = (ushort) newlb.TotalScoreTaiko;
                    pr.Stats.RankedScore = (ushort) newlb.RankedScoreTaiko;
                    pr.Stats.PlayCount = (ushort) newlb.PlayCountTaiko;
                    break;
                case PlayMode.Ctb:
                    pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsCtb;
                    pr.Stats.TotalScore = (ushort) newlb.TotalScoreCtb;
                    pr.Stats.RankedScore = (ushort) newlb.RankedScoreCtb;
                    pr.Stats.PlayCount = (ushort) newlb.PlayCountCtb;
                    break;
                case PlayMode.Mania:
                    pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsMania;
                    pr.Stats.TotalScore = (ushort) newlb.TotalScoreMania;
                    pr.Stats.RankedScore = (ushort) newlb.RankedScoreMania;
                    pr.Stats.PlayCount = (ushort) newlb.PlayCountMania;
                    break;
            }
            
            // Send to other People
            await _ev.RunEvent(
                EventType.BanchoUserStatsRequest,
                new BanchoUserStatsRequestArgs {UserIds = new List<int> {score.Id}, Pr = pr}
            );

            // Send to self
            await _ev.RunEvent(
                EventType.BanchoSendUserStatus,
                new BanchoSendUserStatusArgs {Status = pr.Status, Pr = pr}
            );

            return Ok(
                $"beatmapId:{bm.BeatmapID}|beatmapSetId:{bm.ParentSetID}|beatmapPlaycount:0|beatmapPasscount:0|approvedDate:\n\n" +
                bmChart.ToOsuString() + "\n" + overallChart.ToOsuString()
            );
        }
Пример #2
0
        public async Task <IActionResult> PostSubmitModular()
        {
            string score  = Request.Form["score"];
            string iv     = Request.Form["iv"];
            string osuver = Request.Form["osuver"];
            string pass   = Request.Form["pass"];

            var(b, scores) = ScoreSubmissionParser.ParseScore(_factory, score, iv, osuver);

            if (scores.UserId == -1)
            {
                return(Ok("error: pass"));
            }

            if (scores.ScoreOwner == null)
            {
                scores.ScoreOwner = Users.GetUser(_factory, scores.UserId);
            }

            if (scores.ScoreOwner == null)
            {
                return(Ok("error: pass"));
            }

            if (!scores.ScoreOwner.IsPassword(pass))
            {
                return(Ok("error: pass"));
            }

            var isRelaxing = (scores.Mods & Mod.Relax) != 0;
            var pr         = _ps.GetPresence(scores.ScoreOwner.Id);

            if (!b || !RankedMods.IsRanked(scores.Mods))
            {
                if (isRelaxing)
                {
                    var rx = LeaderboardRx.GetLeaderboard(_factory, scores.ScoreOwner);
                    rx.IncreasePlaycount(_factory, scores.PlayMode);
                    rx.IncreaseScore(_factory, (ulong)scores.TotalScore, false, scores.PlayMode);
                }
                else
                {
                    var std = LeaderboardStd.GetLeaderboard(_factory, scores.ScoreOwner);
                    std.IncreasePlaycount(_factory, scores.PlayMode);
                    std.IncreaseScore(_factory, (ulong)scores.TotalScore, false, scores.PlayMode);
                }

                await _ev.RunEvent(
                    EventType.BanchoUserStatsRequest,
                    new BanchoUserStatsRequestArgs { userIds = new List <int> {
                                                         scores.ScoreOwner.Id
                                                     }, pr = pr }
                    );

                return(Ok("Thanks for your hard work!"));
            }

            /*
             * switch (scores.PlayMode)
             * {
             *  case PlayMode.Osu:
             *      oppai op = new oppai(BeatmapDownloader.GetBeatmap(scores.FileMd5, _config));
             *      op.SetAcc((int) scores.Count300, (int) scores.Count50, (int) scores.CountMiss);
             *      op.SetCombo(scores.MaxCombo);
             *      op.SetMods(scores.Mods);
             *      op.Calculate();
             *
             *      scores.PeppyPoints = op.GetPP();
             *      Logger.Info("Peppy Points:", scores.PeppyPoints);
             *      break;
             * }
             */

            var ReplayFile = Request.Form.Files.GetFile("score");

            if (!Directory.Exists("data/replays"))
            {
                Directory.CreateDirectory("data/replays");
            }

            await using (var m = new MemoryStream())
            {
                ReplayFile.CopyTo(m);
                m.Position       = 0;
                scores.ReplayMd5 = Hex.ToHex(Crypto.GetMd5(m)) ?? string.Empty;
                if (!string.IsNullOrEmpty(scores.ReplayMd5))
                {
                    await using (var replayFile = System.IO.File.Create($"data/replays/{scores.ReplayMd5}"))
                    {
                        m.Position = 0;
                        m.WriteTo(replayFile);
                        m.Close();
                        replayFile.Close();
                    }
                }
            }

            BeatmapDownloader.GetBeatmap(scores.FileMd5, _config);

            if (isRelaxing)
            {
                scores.Mods -= Mod.Relax;
            }
            scores.PeppyPoints = PerformancePointsProcessor.Compute(scores);
            if (isRelaxing)
            {
                scores.Mods |= Mod.Relax;
            }

            var oldScore = Scores.GetScores(
                _factory,
                scores.FileMd5,
                scores.ScoreOwner,
                scores.PlayMode,
                isRelaxing,
                false,
                false,
                false,
                scores.Mods,
                true
                ).FirstOrDefault();

            var oldStd    = LeaderboardStd.GetLeaderboard(_factory, scores.ScoreOwner);
            var oldStdPos = oldStd.GetPosition(_factory, scores.PlayMode);

            if (oldScore != null && oldScore.TotalScore <= scores.TotalScore)
            {
                using var db = _factory.GetForWrite();
                db.Context.Scores.Remove(oldScore);
                System.IO.File.Delete($"data/replays/{oldScore.ReplayMd5}");

                Scores.InsertScore(_factory, scores);
            }
            else if (oldScore == null)
            {
                Scores.InsertScore(_factory, scores);
            }
            else
            {
                System.IO.File.Delete($"data/replays/{scores.ReplayMd5}");
            }

            if (isRelaxing)
            {
                var rx = LeaderboardRx.GetLeaderboard(_factory, scores.ScoreOwner);
                rx.IncreasePlaycount(_factory, scores.PlayMode);
                rx.IncreaseCount300(_factory, scores.Count300, scores.PlayMode);
                rx.IncreaseCount100(_factory, scores.Count100, scores.PlayMode);
                rx.IncreaseCount50(_factory, scores.Count50, scores.PlayMode);
                rx.IncreaseCountMiss(_factory, scores.CountMiss, scores.PlayMode);
                rx.IncreaseScore(_factory, (ulong)scores.TotalScore, true, scores.PlayMode);
                rx.IncreaseScore(_factory, (ulong)scores.TotalScore, false, scores.PlayMode);

                rx.UpdatePP(_factory, scores.PlayMode);

                pr.LeaderboardRx = rx;
                await _ev.RunEvent(
                    EventType.BanchoUserStatsRequest,
                    new BanchoUserStatsRequestArgs { userIds = new List <int> {
                                                         scores.ScoreOwner.Id
                                                     }, pr = pr }
                    );
            }
            else
            {
                var std = LeaderboardStd.GetLeaderboard(_factory, scores.ScoreOwner);
                std.IncreasePlaycount(_factory, scores.PlayMode);
                std.IncreaseCount300(_factory, scores.Count300, scores.PlayMode);
                std.IncreaseCount100(_factory, scores.Count100, scores.PlayMode);
                std.IncreaseCount50(_factory, scores.Count50, scores.PlayMode);
                std.IncreaseCountMiss(_factory, scores.CountMiss, scores.PlayMode);
                std.IncreaseScore(_factory, (ulong)scores.TotalScore, true, scores.PlayMode);
                std.IncreaseScore(_factory, (ulong)scores.TotalScore, false, scores.PlayMode);

                std.UpdatePP(_factory, scores.PlayMode);
            }

            var newStd    = LeaderboardStd.GetLeaderboard(_factory, scores.ScoreOwner);
            var newStdPos = newStd.GetPosition(_factory, scores.PlayMode);


            var NewScore = Scores.GetScores(
                _factory,
                scores.FileMd5,
                scores.ScoreOwner,
                scores.PlayMode,
                isRelaxing,
                false,
                false,
                false,
                scores.Mods,
                true
                ).FirstOrDefault();

            var cg = new Cheesegull(_config);

            cg.SetBM(scores.FileMd5);

            var sets = cg.GetSets();
            var bm   = sets?[0].ChildrenBeatmaps.First(x => x.FileMD5 == scores.FileMd5) ?? new CheesegullBeatmap();

            double oldAcc;
            double newAcc;

            ulong oldRankedScore;
            ulong newRankedScore;

            double oldPP;
            double newPP;

            switch (scores.PlayMode)
            {
            case PlayMode.Osu:
                oldAcc = Accuracy.GetAccuracy(
                    oldStd.Count300Osu,
                    oldStd.Count100Osu,
                    oldStd.Count50Osu,
                    oldStd.Count300Osu, 0, 0,
                    PlayMode.Osu
                    );

                newAcc = Accuracy.GetAccuracy(
                    newStd.Count300Osu,
                    newStd.Count100Osu,
                    newStd.Count50Osu,
                    newStd.Count300Osu, 0, 0,
                    PlayMode.Osu
                    );

                oldRankedScore = oldStd.RankedScoreOsu;
                newRankedScore = newStd.RankedScoreOsu;

                oldPP = oldStd.PerformancePointsOsu;
                newPP = newStd.PerformancePointsOsu;
                break;

            case PlayMode.Taiko:
                oldAcc = Accuracy.GetAccuracy(
                    oldStd.Count300Taiko,
                    oldStd.Count100Taiko,
                    oldStd.Count50Taiko,
                    oldStd.Count300Taiko, 0, 0,
                    PlayMode.Taiko
                    );

                newAcc = Accuracy.GetAccuracy(
                    newStd.Count300Taiko,
                    newStd.Count100Taiko,
                    newStd.Count50Taiko,
                    newStd.Count300Taiko, 0, 0,
                    PlayMode.Taiko
                    );

                oldRankedScore = oldStd.RankedScoreTaiko;
                newRankedScore = newStd.RankedScoreTaiko;

                oldPP = oldStd.PerformancePointsTaiko;
                newPP = newStd.PerformancePointsTaiko;
                break;

            case PlayMode.Ctb:
                oldAcc = Accuracy.GetAccuracy(
                    oldStd.Count300Ctb,
                    oldStd.Count100Ctb,
                    oldStd.Count50Ctb,
                    oldStd.Count300Ctb, 0, 0,
                    PlayMode.Ctb
                    );

                newAcc = Accuracy.GetAccuracy(
                    newStd.Count300Ctb,
                    newStd.Count100Ctb,
                    newStd.Count50Ctb,
                    newStd.Count300Ctb, 0, 0,
                    PlayMode.Ctb
                    );

                oldRankedScore = oldStd.RankedScoreCtb;
                newRankedScore = newStd.RankedScoreCtb;

                oldPP = oldStd.PerformancePointsCtb;
                newPP = newStd.PerformancePointsCtb;
                break;

            case PlayMode.Mania:
                oldAcc = Accuracy.GetAccuracy(
                    oldStd.Count300Mania,
                    oldStd.Count100Mania,
                    oldStd.Count50Mania,
                    oldStd.Count300Mania, 0, 0,
                    PlayMode.Mania
                    );

                newAcc = Accuracy.GetAccuracy(
                    newStd.Count300Mania,
                    newStd.Count100Mania,
                    newStd.Count50Mania,
                    newStd.Count300Mania, 0, 0,
                    PlayMode.Mania
                    );

                oldRankedScore = oldStd.RankedScoreMania;
                newRankedScore = newStd.RankedScoreMania;

                oldPP = oldStd.PerformancePointsMania;
                newPP = newStd.PerformancePointsMania;
                break;

            default:
                return(Ok(""));
            }

            if (NewScore?.Position == 1 && (oldScore == null || oldScore.TotalScore < NewScore.TotalScore))
            {
                _sora.SendMessage(
                    $"[http://{_config.Server.Hostname}/{scores.ScoreOwner.Id} {scores.ScoreOwner.Username}] " +
                    $"has reached #1 on [https://osu.ppy.sh/b/{bm.BeatmapID} {sets?[0].Title} [{bm.DiffName}]] " +
                    $"using {ModUtil.ToString(NewScore.Mods)} " +
                    $"Good job! +{NewScore.PeppyPoints:F}PP",
                    "#announce",
                    false
                    );
            }

            Logger.Info(
                $"{L_COL.RED}{scores.ScoreOwner.Username}",
                $"{L_COL.PURPLE}( {scores.ScoreOwner.Id} ){L_COL.WHITE}",
                $"has just submitted a Score! he earned {L_COL.BLUE}{NewScore?.PeppyPoints:F}PP",
                $"{L_COL.WHITE}with an Accuracy of {L_COL.RED}{NewScore?.Accuracy * 100:F}",
                $"{L_COL.WHITE}on {L_COL.YELLOW}{sets?[0].Title} [{bm.DiffName}]",
                $"{L_COL.WHITE}using {L_COL.BLUE}{ModUtil.ToString(NewScore?.Mods ?? Mod.None)}"
                );

            var bmChart = new Chart(
                "beatmap",
                "Beatmap Ranking",
                $"https://osu.ppy.sh/b/{bm.BeatmapID}",
                oldScore?.Position ?? 0,
                NewScore?.Position ?? 0,
                oldScore?.MaxCombo ?? 0,
                NewScore?.MaxCombo ?? 0,
                oldScore?.Accuracy * 100 ?? 0,
                NewScore?.Accuracy * 100 ?? 0,
                (ulong)(oldScore?.TotalScore ?? 0),
                (ulong)(NewScore?.TotalScore ?? 0),
                oldScore?.PeppyPoints ?? 0,
                NewScore?.PeppyPoints ?? 0,
                NewScore?.Id ?? 0
                );

            cg.SetBMSet(bm.ParentSetID);

            var overallChart = new Chart(
                "overall",
                "Global Ranking",
                $"https://osu.ppy.sh/u/{scores.ScoreOwner.Id}",
                (int)oldStdPos,
                (int)newStdPos,
                0,
                0,
                oldAcc * 100,
                newAcc * 100,
                oldRankedScore,
                newRankedScore,
                oldPP,
                newPP,
                NewScore?.Id ?? 0,
                AchievementProcessor.ProcessAchievements(
                    _factory, scores.ScoreOwner, scores, bm, cg.GetSets()[0], oldStd, newStd
                    )
                );

            pr.LeaderboardStd = newStd;
            await _ev.RunEvent(
                EventType.BanchoUserStatsRequest,
                new BanchoUserStatsRequestArgs { userIds = new List <int> {
                                                     scores.ScoreOwner.Id
                                                 }, pr = pr }
                );

            return(Ok(
                       $"beatmapId:{bm.BeatmapID}|beatmapSetId:{bm.ParentSetID}|beatmapPlaycount:0|beatmapPasscount:0|approvedDate:\n\n" +
                       bmChart.ToOsuString() + "\n" + overallChart.ToOsuString()
                       ));
        }