public MapAnalysisContext(DbBeatmap dmp, Score sc, string osuRoot) { this.sc = sc; this.dmp = dmp; this.osuRoot = osuRoot; loadFiles(); calcDiff(); convObjs(); procReplay(); }
private void showMapInfo(DbBeatmap map, List <Score> scores) { mapInfo.Text = $"MapInfo{nl}" + $"Song title: {map.Title}{nl}" + $"Difficulty: {map.Difficulty}{nl}" + $"Hash: {map.MD5Hash}{nl}"; replayInfo.Text = ""; replaySelect.Items.Clear(); foreach (var score in scores) { replaySelect.Items.Add($"x{score.Combo} [{score.ScoreTimestamp.ToLongDateString()} {score.ScoreTimestamp.ToLongTimeString()}]"); } }
public static void AddOrUpdate(this DbSet <DbBeatmap> dbSet, DbBeatmap data) { var context = dbSet.GetContext(); var entities = dbSet.AsNoTracking().Where(set => set.Id == data.Id); var dbVal = entities.FirstOrDefault(); if (dbVal != null) { context.Entry(dbVal).CurrentValues.SetValues(data); context.Entry(dbVal).State = EntityState.Modified; return; } dbSet.Add(data); }
/// <summary> /// Parses osu!.db file. /// </summary> /// <param name="stream">Stream containing osu!.db data.</param> /// <returns>A usable <see cref="OsuDatabase"/>.</returns> public static OsuDatabase DecodeOsu(Stream stream) { OsuDatabase db = new OsuDatabase(); using (var r = new SerializationReader(stream)) { db.OsuVersion = r.ReadInt32(); db.FolderCount = r.ReadInt32(); db.AccountUnlocked = r.ReadBoolean(); db.UnlockDate = r.ReadDateTime(); db.PlayerName = r.ReadString(); int beatmapCount = r.ReadInt32(); db.BeatmapCount = beatmapCount; for (int i = 0; i < beatmapCount; i++) { DbBeatmap beatmap = new DbBeatmap(); if (db.OsuVersion < 20191106) { beatmap.BytesOfBeatmapEntry = r.ReadInt32(); } beatmap.Artist = r.ReadString(); beatmap.ArtistUnicode = r.ReadString(); beatmap.Title = r.ReadString(); beatmap.TitleUnicode = r.ReadString(); beatmap.Creator = r.ReadString(); beatmap.Difficulty = r.ReadString(); beatmap.AudioFileName = r.ReadString(); beatmap.MD5Hash = r.ReadString(); beatmap.FileName = r.ReadString(); beatmap.RankedStatus = (RankedStatus)r.ReadByte(); beatmap.CirclesCount = r.ReadUInt16(); beatmap.SlidersCount = r.ReadUInt16(); beatmap.SpinnersCount = r.ReadUInt16(); beatmap.LastModifiedTime = r.ReadDateTime(); beatmap.ApproachRate = db.OsuVersion >= 20140609 ? r.ReadSingle() : r.ReadByte(); beatmap.CircleSize = db.OsuVersion >= 20140609 ? r.ReadSingle() : r.ReadByte(); beatmap.HPDrain = db.OsuVersion >= 20140609 ? r.ReadSingle() : r.ReadByte(); beatmap.OverallDifficulty = db.OsuVersion >= 20140609 ? r.ReadSingle() : r.ReadByte(); beatmap.SliderVelocity = r.ReadDouble(); if (db.OsuVersion >= 20140609) { beatmap.StandardStarRating = r.ReadDictionary <Mods, double>(); beatmap.TaikoStarRating = r.ReadDictionary <Mods, double>(); beatmap.CatchStarRating = r.ReadDictionary <Mods, double>(); beatmap.ManiaStarRating = r.ReadDictionary <Mods, double>(); } beatmap.DrainTime = r.ReadInt32(); beatmap.TotalTime = r.ReadInt32(); beatmap.AudioPreviewTime = r.ReadInt32(); int timingPointsCount = r.ReadInt32(); for (int j = 0; j < timingPointsCount; j++) { DbTimingPoint timingPoint = new DbTimingPoint(); timingPoint.BPM = r.ReadDouble(); timingPoint.Offset = r.ReadDouble(); timingPoint.Inherited = r.ReadBoolean(); beatmap.TimingPoints.Add(timingPoint); } beatmap.BeatmapId = r.ReadInt32(); beatmap.BeatmapSetId = r.ReadInt32(); beatmap.ThreadId = r.ReadInt32(); beatmap.StandardGrade = (Grade)r.ReadByte(); beatmap.TaikoGrade = (Grade)r.ReadByte(); beatmap.CatchGrade = (Grade)r.ReadByte(); beatmap.ManiaGrade = (Grade)r.ReadByte(); beatmap.LocalOffset = r.ReadInt16(); beatmap.StackLeniency = r.ReadSingle(); beatmap.Ruleset = (Ruleset)r.ReadByte(); beatmap.Source = r.ReadString(); beatmap.Tags = r.ReadString(); beatmap.OnlineOffset = r.ReadInt16(); beatmap.TitleFont = r.ReadString(); beatmap.IsUnplayed = r.ReadBoolean(); beatmap.LastPlayed = r.ReadDateTime(); beatmap.IsOsz2 = r.ReadBoolean(); beatmap.FolderName = r.ReadString(); beatmap.LastCheckedAgainstOsuRepo = r.ReadDateTime(); beatmap.IgnoreBeatmapSound = r.ReadBoolean(); beatmap.IgnoreBeatmapSkin = r.ReadBoolean(); beatmap.DisableStoryboard = r.ReadBoolean(); beatmap.DisableVideo = r.ReadBoolean(); beatmap.VisualOverride = r.ReadBoolean(); if (db.OsuVersion < 20140609) { r.BaseStream.Seek(sizeof(short), SeekOrigin.Current); //let's skip this unknown variable } r.BaseStream.Seek(sizeof(int), SeekOrigin.Current); //and this one beatmap.ManiaScrollSpeed = r.ReadByte(); db.Beatmaps.Add(beatmap); } db.Permissions = (Permissions)r.ReadInt32(); } return(db); }
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) { try { var dbUser = await DbUser.GetDbUser(_ctx, us); var user = dbUser?.ToUser(); if (dbUser?.IsPassword(pa) != true) return Ok("error: pass"); var cacheHash = Hex.ToHex( Crypto.GetMd5( $"{fileMd5}{playMode}{mods}{type}{user.Id}{user.UserName}" ) ); if (_cache.TryGet($"sora:Scoreboards:{cacheHash}", out string cachedData)) return Ok(cachedData); var scores = await DbScore.GetScores(_ctx, fileMd5, dbUser, playMode, type == ScoreboardType.Friends, type == ScoreboardType.Country, type == ScoreboardType.Mods, mods); var beatmap = DbBeatmap.GetBeatmap(_ctx, fileMd5); BeatmapSet apiSet; if (beatmap == null) { 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 concurrentLock = new object(); var pool = serviceProvider.GetRequiredService<DbContextPool<SoraDbContext>>(); Task.WaitAll(beatmaps.Select(rawBeatmap => Task.Run(async () => { var context = pool.Rent(); 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(); pool.Return(context); })).ToArray()); beatmap = beatmaps.FirstOrDefault(s => s.FileMd5 == fileMd5); } JustContinue: var ownScore = await DbScore.GetLatestScore(_ctx, new DbScore { FileMd5 = fileMd5, UserId = user.Id, PlayMode = playMode, TotalScore = 0 }); var sScores = scores.Select(s => new Score { Count100 = s.Count100, Count50 = s.Count50, Count300 = s.Count300, Date = s.Date, Mods = s.Mods, CountGeki = s.CountGeki, CountKatu = s.CountKatu, CountMiss = s.CountMiss, FileMd5 = s.FileMd5, MaxCombo = s.MaxCombo, PlayMode = s.PlayMode, TotalScore = s.TotalScore, UserId = s.UserId, UserName = s.ScoreOwner.UserName, }).ToList(); // Fetch the correct position for sScore for (var j = 0; j < scores.Count; j++) { sScores[j].Position = await scores[j].Position(_ctx); } Score ownsScore = null; if (ownScore != null) ownsScore = new Score { Count100 = ownScore.Count100, Count50 = ownScore.Count50, Count300 = ownScore.Count300, Date = ownScore.Date, Mods = ownScore.Mods, CountGeki = ownScore.CountGeki, CountKatu = ownScore.CountKatu, CountMiss = ownScore.CountMiss, FileMd5 = ownScore.FileMd5, MaxCombo = ownScore.MaxCombo, PlayMode = ownScore.PlayMode, TotalScore = ownScore.TotalScore, UserId = dbUser.Id, UserName = dbUser.UserName, Position = await ownScore.Position(_ctx) }; BeatmapSet set = null; 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 } } }; var sboard = new Scoreboard(set?.ChildrenBeatmaps.FirstOrDefault(bm => bm.FileMD5 == fileMd5), set, sScores, ownsScore); _cache.Set($"sora:Scoreboards:{cacheHash}", cachedData = sboard.ToOsuString(), TimeSpan.FromSeconds(30)); return Ok(cachedData); } catch (Exception ex) { Logger.Err(ex); return Ok("Failed"); } }
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")); } }