private void migrateBeatmaps(OsuDbContext ef) { // can be removed 20220730. var existingBeatmapSets = ef.EFBeatmapSetInfo .Include(s => s.Beatmaps).ThenInclude(b => b.RulesetInfo) .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata) .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) .Include(s => s.Files).ThenInclude(f => f.FileInfo) .Include(s => s.Metadata) .AsSplitQuery(); log("Beginning beatmaps migration to realm"); // previous entries in EF are removed post migration. if (!existingBeatmapSets.Any()) { log("No beatmaps found to migrate"); return; } int count = existingBeatmapSets.Count(); realm.Run(r => { log($"Found {count} beatmaps in EF"); var transaction = r.BeginWrite(); int written = 0; int missing = 0; try { foreach (var beatmapSet in existingBeatmapSets) { if (++written % 1000 == 0) { transaction.Commit(); transaction = r.BeginWrite(); log($"Migrated {written}/{count} beatmaps..."); } var realmBeatmapSet = new BeatmapSetInfo { OnlineID = beatmapSet.OnlineID ?? -1, DateAdded = beatmapSet.DateAdded, Status = beatmapSet.Status, DeletePending = beatmapSet.DeletePending, Hash = beatmapSet.Hash, Protected = beatmapSet.Protected, }; migrateFiles(beatmapSet, r, realmBeatmapSet); foreach (var beatmap in beatmapSet.Beatmaps) { var ruleset = r.Find <RulesetInfo>(beatmap.RulesetInfo.ShortName); var metadata = getBestMetadata(beatmap.Metadata, beatmapSet.Metadata); if (ruleset == null) { log($"Skipping {++missing} beatmaps with missing ruleset"); continue; } var realmBeatmap = new BeatmapInfo(ruleset, new BeatmapDifficulty(beatmap.BaseDifficulty), metadata) { DifficultyName = beatmap.DifficultyName, Status = beatmap.Status, OnlineID = beatmap.OnlineID ?? -1, Length = beatmap.Length, BPM = beatmap.BPM, Hash = beatmap.Hash, StarRating = beatmap.StarRating, MD5Hash = beatmap.MD5Hash, Hidden = beatmap.Hidden, AudioLeadIn = beatmap.AudioLeadIn, StackLeniency = beatmap.StackLeniency, SpecialStyle = beatmap.SpecialStyle, LetterboxInBreaks = beatmap.LetterboxInBreaks, WidescreenStoryboard = beatmap.WidescreenStoryboard, EpilepsyWarning = beatmap.EpilepsyWarning, SamplesMatchPlaybackRate = beatmap.SamplesMatchPlaybackRate, DistanceSpacing = beatmap.DistanceSpacing, BeatDivisor = beatmap.BeatDivisor, GridSize = beatmap.GridSize, TimelineZoom = beatmap.TimelineZoom, Countdown = beatmap.Countdown, CountdownOffset = beatmap.CountdownOffset, MaxCombo = beatmap.MaxCombo, Bookmarks = beatmap.Bookmarks, BeatmapSet = realmBeatmapSet, }; realmBeatmapSet.Beatmaps.Add(realmBeatmap); } r.Add(realmBeatmapSet); } } finally { transaction.Commit(); } log($"Successfully migrated {count} beatmaps to realm"); }); }
public DatabaseWorkingBeatmap(BeatmapDatabase database, BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false) : base(beatmapInfo, beatmapSetInfo, withStoryboard) { this.database = database; }
public ArchiveReader GetReader(BeatmapSetInfo beatmapSet) { return(ArchiveReader.GetReader(storage, beatmapSet.Path)); }
public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path);
/// <summary> /// Duplicates content from <paramref name="path"/> to storage and returns a representing <see cref="BeatmapSetInfo"/>. /// </summary> /// <param name="path">Content location</param> /// <returns><see cref="BeatmapSetInfo"/></returns> private BeatmapSetInfo getBeatmapSet(string path) { string hash = null; BeatmapMetadata metadata; using (var reader = ArchiveReader.GetReader(storage, path)) metadata = reader.ReadMetadata(); if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader { using (var input = storage.GetStream(path)) { hash = input.GetMd5Hash(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); if (!storage.Exists(path)) { using (var output = storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } } var existing = connection.Table <BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash); if (existing != null) { if (existing.DeletePending) { existing.DeletePending = false; Update(existing, false); BeatmapSetAdded?.Invoke(existing); } return(existing); } var beatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, Beatmaps = new List <BeatmapInfo>(), Path = path, Hash = hash, Metadata = metadata }; using (var archive = ArchiveReader.GetReader(storage, path)) { string[] mapNames = archive.BeatmapFilenames; foreach (var name in mapNames) { using (var raw = archive.GetStream(name)) using (var ms = new MemoryStream()) //we need a memory stream so we can seek and shit using (var sr = new StreamReader(ms)) { raw.CopyTo(ms); ms.Position = 0; var decoder = BeatmapDecoder.GetDecoder(sr); Beatmap beatmap = decoder.Decode(sr); beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Hash = ms.GetMd5Hash(); // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } } beatmapSet.StoryboardFile = archive.StoryboardFilename; } return(beatmapSet); }
/// <summary> /// Duplicates content from <paramref name="path"/> to storage and returns a representing <see cref="BeatmapSetInfo"/>. /// </summary> /// <param name="path">Content location</param> /// <returns><see cref="BeatmapSetInfo"/></returns> private BeatmapSetInfo getBeatmapSet(string path) { string hash = null; BeatmapMetadata metadata; using (var reader = ArchiveReader.GetReader(storage, path)) metadata = reader.ReadMetadata(); if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader { using (var md5 = MD5.Create()) using (var input = storage.GetStream(path)) { hash = BitConverter.ToString(md5.ComputeHash(input)).Replace("-", "").ToLowerInvariant(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); if (!storage.Exists(path)) { using (var output = storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } } var existing = connection.Table <BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash); if (existing != null) { if (existing.DeletePending) { existing.DeletePending = false; Update(existing, false); BeatmapSetAdded?.Invoke(existing); } return(existing); } var beatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, Beatmaps = new List <BeatmapInfo>(), Path = path, Hash = hash, Metadata = metadata }; using (var reader = ArchiveReader.GetReader(storage, path)) { string[] mapNames = reader.BeatmapFilenames; foreach (var name in mapNames) { using (var stream = new StreamReader(reader.GetStream(name))) { var decoder = BeatmapDecoder.GetDecoder(stream); Beatmap beatmap = decoder.Decode(stream); beatmap.BeatmapInfo.Path = name; // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } } beatmapSet.StoryboardFile = reader.StoryboardFilename; } return(beatmapSet); }
public static void CopyChangesToRealm(this BeatmapSetInfo source, BeatmapSetInfo destination) => copyChangesToRealm(source, destination);
private BeatmapSetInfo getBeatmapSet(ArchiveReader archiveReader) { BeatmapMetadata metadata; using (var stream = new StreamReader(archiveReader.GetStream(archiveReader.BeatmapFilenames[0]))) metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; string hash; string path; using (var input = archiveReader.GetUnderlyingStream()) { hash = input.GetMd5Hash(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); if (!Storage.Exists(path)) { using (var output = Storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } var existing = Connection.Table <BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash); if (existing != null) { GetChildren(existing); if (existing.DeletePending) { existing.DeletePending = false; Update(existing, false); BeatmapSetAdded?.Invoke(existing); } return(existing); } var beatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, Beatmaps = new List <BeatmapInfo>(), Path = path, Hash = hash, Metadata = metadata }; using (var archive = ArchiveReader.GetReader(Storage, path)) { string[] mapNames = archive.BeatmapFilenames; foreach (var name in mapNames) { using (var raw = archive.GetStream(name)) using (var ms = new MemoryStream()) //we need a memory stream so we can seek and shit using (var sr = new StreamReader(ms)) { raw.CopyTo(ms); ms.Position = 0; var decoder = BeatmapDecoder.GetDecoder(sr); Beatmap beatmap = decoder.Decode(sr); beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Hash = ms.GetMd5Hash(); // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.Ruleset = rulesets.Query <RulesetInfo>().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.StarDifficulty = rulesets.Query <RulesetInfo>().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID)?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0; beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } } beatmapSet.StoryboardFile = archive.StoryboardFilename; } return(beatmapSet); }