Example #1
0
        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");
            });
        }
Example #2
0
 public DatabaseWorkingBeatmap(BeatmapDatabase database, BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false)
     : base(beatmapInfo, beatmapSetInfo, withStoryboard)
 {
     this.database = database;
 }
Example #3
0
 public ArchiveReader GetReader(BeatmapSetInfo beatmapSet)
 {
     return(ArchiveReader.GetReader(storage, beatmapSet.Path));
 }
Example #4
0
 public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path);
Example #5
0
        /// <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);
        }
Example #6
0
        /// <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);
        }
Example #7
0
 public static void CopyChangesToRealm(this BeatmapSetInfo source, BeatmapSetInfo destination)
 => copyChangesToRealm(source, destination);
Example #8
0
        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);
        }