public uint GetPosition(SoraDbContext ctx, PlayMode mode) { var pos = mode switch // Prevent position jumping around. { PlayMode.Osu => PerformancePointsOsu <= 0 ? 0 : -1, PlayMode.Taiko => PerformancePointsTaiko <= 0 ? 0 : -1, PlayMode.Ctb => PerformancePointsCtb <= 0 ? 0 : -1, PlayMode.Mania => PerformancePointsMania <= 0 ? 0 : -1, _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null), }; if (pos == -1) { pos = mode switch { PlayMode.Osu => ctx.Leaderboard.Count(x => x.PerformancePointsOsu > PerformancePointsOsu), PlayMode.Taiko => ctx.Leaderboard .Count(x => x.PerformancePointsTaiko > PerformancePointsTaiko), PlayMode.Ctb => ctx.Leaderboard.Count(x => x.PerformancePointsCtb > PerformancePointsCtb), PlayMode.Mania => ctx.Leaderboard .Count(x => x.PerformancePointsMania > PerformancePointsMania), _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null), } } ;
public async Task <IActionResult> GetReplay( [FromQuery(Name = "c")] int replayId, [FromQuery(Name = "m")] PlayMode mode, [FromQuery(Name = "u")] string userName, [FromQuery(Name = "h")] string pass, [FromServices] SoraDbContext ctx ) { var user = await DbUser.GetDbUser(ctx, userName); if (user == null) { return(Ok("err: pass")); } if (!user.IsPassword(pass)) { return(Ok("err: pass")); } var s = await DbScore.GetScore(ctx, replayId); if (s == null) { return(NotFound()); } return(File(System.IO.File.OpenRead("data/replays/" + s.ReplayMd5), "binary/octet-stream", s.ReplayMd5)); }
public static Ruleset Convert(PlayMode mode) { return(mode switch { PlayMode.Osu => (Ruleset) new OsuRuleset(), PlayMode.Taiko => new CatchRuleset(), PlayMode.Ctb => new TaikoRuleset(), PlayMode.Mania => new ManiaRuleset(), _ => new OsuRuleset(), });
public void IncreaseScore(ulong score, bool ranked, PlayMode mode) { switch (mode) { case PlayMode.Osu: if (ranked) { RankedScoreOsu += score; } else { TotalScoreOsu += score; } break; case PlayMode.Taiko: if (ranked) { RankedScoreTaiko += score; } else { TotalScoreTaiko += score; } break; case PlayMode.Ctb: if (ranked) { RankedScoreCtb += score; } else { TotalScoreCtb += score; } break; case PlayMode.Mania: if (ranked) { RankedScoreMania += score; } else { TotalScoreMania += score; } break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } }
public static async IAsyncEnumerable <DbScore> GetScores( SoraDbContext ctx, string fileMd5, DbUser user, PlayMode playMode = PlayMode.Osu, bool friendsOnly = false, bool countryOnly = false, bool modOnly = false, Mod mods = Mod.None, bool onlySelf = false ) { const CountryId cid = CountryId.XX; /* Legacy Code * if (countryOnly) * cid = UserStats.GetUserStats(factory, user.Id).CountryId; */ var query = ctx.Scores .Where(score => score.FileMd5 == fileMd5 && score.PlayMode == playMode) .Where( score => !friendsOnly || ctx.Friends .Where(f => f.UserId == user.Id) .Select(f => f.FriendId) .Contains(score.UserId) ) /* Legacy Code TODO: Implement * .Where( * score * => !countryOnly || factory.Get().UserStats * .Select(c => c.CountryId) * .Contains(cid) * ) */ .Where(score => !modOnly || score.Mods == mods) .Where(score => !onlySelf || score.UserId == user.Id) .OrderByDescending(score => score.TotalScore) .Include(x => x.ScoreOwner) .ToList() .GroupBy(s => s.UserId) // TODO: this is stupid. but we cant change it :c .Select(s => s.First()) .Take(50); foreach (var dbScore in query) { yield return(dbScore); } }
public void IncreasePlaycount(PlayMode mode) { switch (mode) { case PlayMode.Osu: PlayCountOsu++; break; case PlayMode.Taiko: PlayCountTaiko++; break; case PlayMode.Ctb: PlayCountCtb++; break; case PlayMode.Mania: PlayCountMania++; break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } }
public async Task <IActionResult> GetScoreResult( [FromQuery(Name = "v")] ScoreboardType type, [FromQuery(Name = "c")] string fileMd5, [FromQuery(Name = "f")] string f, [FromQuery(Name = "m")] PlayMode playMode, [FromQuery(Name = "i")] int i, [FromQuery(Name = "mods")] Mod mods, [FromQuery(Name = "us")] string us, [FromQuery(Name = "ha")] string pa, [FromServices] IServiceProvider serviceProvider, [FromServices] SoraDbContext ctx, [FromServices] DbContextPool <SoraDbContext> ctxPool, [FromServices] Pisstaube pisstaube, [FromServices] Cache cache) { try { var dbUser = await DbUser.GetDbUser(ctx, us); if (dbUser?.IsPassword(pa) != true) { return(Ok("error: pass")); } var cacheHash = Hex.ToHex( Crypto.GetMd5( $"{fileMd5}{playMode}{mods}{type}{dbUser.Id}{dbUser.UserName}" ) ); if (cache.TryGet($"sora:Scoreboards:{cacheHash}", out string cachedData)) { return(Ok(cachedData)); } var scores = DbScore.GetScores(ctx, fileMd5, dbUser, playMode, type == ScoreboardType.Friends, type == ScoreboardType.Country, type == ScoreboardType.Mods, mods); BeatmapSet set = null; DbScore ownScore = null; var beatmap = DbBeatmap.GetBeatmap(ctx, fileMd5); if (beatmap == null) { var apiSet = await pisstaube.FetchBeatmapSetAsync(fileMd5); if (apiSet == null) { goto JustContinue; } var beatmaps = DbBeatmap.FromBeatmapSet(apiSet).ToList(); var beatmapChecksums = beatmaps.Select(s => s.FileMd5); var dbBeatmaps = ctx.Beatmaps.Where(rset => beatmapChecksums.Any(lFileMd5 => rset.FileMd5 == lFileMd5)) .ToList(); var pool = serviceProvider.GetRequiredService <DbContextPool <SoraDbContext> >(); Task.WaitAll(beatmaps.Select(rawBeatmap => Task.Run(async() => { var context = pool.Rent(); try { var dbBeatmap = dbBeatmaps.FirstOrDefault(s => s.FileMd5 == rawBeatmap.FileMd5); if (dbBeatmap != null && (dbBeatmap.Flags & DbBeatmapFlags.RankedFreeze) != 0) { rawBeatmap.RankedStatus = dbBeatmap.RankedStatus; rawBeatmap.Flags = dbBeatmap.Flags; } context.Beatmaps.AddOrUpdate(rawBeatmap); await context.SaveChangesAsync(); } finally { pool.Return(context); } })).ToArray()); beatmap = beatmaps.FirstOrDefault(s => s.FileMd5 == fileMd5); } await foreach (var score in DbScore.GetScores(ctx, fileMd5, dbUser, playMode, false, false, false, mods, true)) { ownScore = score; break; } if (beatmap != null) { set = new BeatmapSet { SetID = beatmap.Id, Artist = beatmap.Artist, Title = beatmap.Title, RankedStatus = beatmap.RankedStatus, ChildrenBeatmaps = new List <Beatmap> { new Beatmap { FileMD5 = beatmap.FileMd5, DiffName = beatmap.DiffName, ParentSetID = beatmap.SetId, BeatmapID = beatmap.Id, Mode = beatmap.PlayMode, }, }, } } ; JustContinue: var sboard = new Scoreboard(set?.ChildrenBeatmaps.FirstOrDefault(bm => bm.FileMD5 == fileMd5), set, scores, ownScore); cache.Set($"sora:Scoreboards:{cacheHash}", cachedData = await sboard.ToOsuString(ctxPool), TimeSpan.FromSeconds(30)); return(Ok(cachedData)); } catch (Exception ex) { Logger.Err(ex); return(Ok("Failed")); } }