Exemplo n.º 1
0
        /// <summary>
        /// Add a <see cref="BeatmapSetInfo"/> to the database.
        /// </summary>
        /// <param name="beatmapSet">The beatmap to add.</param>
        public void Add(BeatmapSetInfo beatmapSet)
        {
            var context = GetContext();

            foreach (var beatmap in beatmapSet.Beatmaps.Where(b => b.Metadata != null))
            {
                // If we detect a new metadata object it'll be attached to the current context so it can be reused
                // to prevent duplicate entries when persisting. To accomplish this we look in the cache (.Local)
                // of the corresponding table (.Set<BeatmapMetadata>()) for matching entries to our criteria.
                var contextMetadata = context.Set <BeatmapMetadata>().Local.SingleOrDefault(e => e.Equals(beatmap.Metadata));
                if (contextMetadata != null)
                {
                    beatmap.Metadata = contextMetadata;
                }
                else
                {
                    context.BeatmapMetadata.Attach(beatmap.Metadata);
                }
            }

            context.BeatmapSetInfo.Attach(beatmapSet);
            context.SaveChanges();

            BeatmapSetAdded?.Invoke(beatmapSet);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Add a <see cref="BeatmapSetInfo"/> to the database.
        /// </summary>
        /// <param name="beatmapSet">The beatmap to add.</param>
        public void Add(BeatmapSetInfo beatmapSet)
        {
            Connection.RunInTransaction(() =>
            {
                Connection.InsertOrReplaceWithChildren(beatmapSet, true);
            });

            BeatmapSetAdded?.Invoke(beatmapSet);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Update a <see cref="BeatmapSetInfo"/> in the database. TODO: This only supports very basic updates currently.
        /// </summary>
        /// <param name="beatmapSet">The beatmap to update.</param>
        public void Update(BeatmapSetInfo beatmapSet)
        {
            BeatmapSetRemoved?.Invoke(beatmapSet);

            using (var usage = ContextFactory.GetForWrite())
                usage.Context.BeatmapSetInfo.Update(beatmapSet);

            BeatmapSetAdded?.Invoke(beatmapSet);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Add a <see cref="BeatmapSetInfo"/> to the database.
        /// </summary>
        /// <param name="beatmapSet">The beatmap to add.</param>
        public void Add(BeatmapSetInfo beatmapSet)
        {
            var context = GetContext();

            context.BeatmapSetInfo.Attach(beatmapSet);
            context.SaveChanges();

            BeatmapSetAdded?.Invoke(beatmapSet);
        }
Exemplo n.º 5
0
        private BeatmapStore createBeatmapStore(Func <OsuDbContext> context)
        {
            var store = new BeatmapStore(context);

            store.BeatmapSetAdded   += s => BeatmapSetAdded?.Invoke(s);
            store.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);
            store.BeatmapHidden     += b => BeatmapHidden?.Invoke(b);
            store.BeatmapRestored   += b => BeatmapRestored?.Invoke(b);
            return(store);
        }
Exemplo n.º 6
0
        public void Import(IEnumerable <BeatmapSetInfo> beatmapSets)
        {
            connection.BeginTransaction();

            foreach (var s in beatmapSets)
            {
                connection.InsertWithChildren(s, true);
                BeatmapSetAdded?.Invoke(s);
            }

            connection.Commit();
        }
Exemplo n.º 7
0
        /// <summary>
        /// Restore a previously deleted <see cref="BeatmapSetInfo"/>.
        /// </summary>
        /// <param name="beatmapSet">The beatmap to restore.</param>
        /// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns>
        public bool Undelete(BeatmapSetInfo beatmapSet)
        {
            if (!beatmapSet.DeletePending)
            {
                return(false);
            }

            beatmapSet.DeletePending = false;
            Connection.Update(beatmapSet);

            BeatmapSetAdded?.Invoke(beatmapSet);
            return(true);
        }
Exemplo n.º 8
0
        public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, IIpcHost importHost = null)
        {
            beatmaps = new BeatmapStore(connection);
            beatmaps.BeatmapSetAdded   += s => BeatmapSetAdded?.Invoke(s);
            beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);

            this.storage  = storage;
            this.files    = files;
            this.rulesets = rulesets;

            if (importHost != null)
            {
                ipc = new BeatmapIPCChannel(importHost, this);
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Restore a previously deleted <see cref="BeatmapSetInfo"/>.
        /// </summary>
        /// <param name="beatmapSet">The beatmap to restore.</param>
        /// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns>
        public bool Undelete(BeatmapSetInfo beatmapSet)
        {
            var context = GetContext();

            Refresh(ref beatmapSet, BeatmapSets);

            if (!beatmapSet.DeletePending)
            {
                return(false);
            }
            beatmapSet.DeletePending = false;
            context.SaveChanges();

            BeatmapSetAdded?.Invoke(beatmapSet);
            return(true);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Restore a previously deleted <see cref="BeatmapSetInfo"/>.
        /// </summary>
        /// <param name="beatmapSet">The beatmap to restore.</param>
        /// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns>
        public bool Undelete(BeatmapSetInfo beatmapSet)
        {
            using (ContextFactory.GetForWrite())
            {
                Refresh(ref beatmapSet, BeatmapSets);

                if (!beatmapSet.DeletePending)
                {
                    return(false);
                }

                beatmapSet.DeletePending = false;
            }

            BeatmapSetAdded?.Invoke(beatmapSet);
            return(true);
        }
Exemplo n.º 11
0
        public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, IIpcHost importHost = null)
        {
            this.contextFactory = contextFactory;

            beatmaps = new BeatmapStore(contextFactory);

            beatmaps.BeatmapSetAdded   += s => BeatmapSetAdded?.Invoke(s);
            beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);
            beatmaps.BeatmapHidden     += b => BeatmapHidden?.Invoke(b);
            beatmaps.BeatmapRestored   += b => BeatmapRestored?.Invoke(b);

            files = new FileStore(contextFactory, storage);

            this.rulesets = rulesets;
            this.api      = api;

            if (importHost != null)
            {
                ipc = new BeatmapIPCChannel(importHost, this);
            }

            beatmaps.Cleanup();
        }
Exemplo n.º 12
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;

                                beatmap.BeatmapInfo.StarDifficulty = beatmap.CalculateStarDifficulty();

                                beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo);
                            }
                }
                beatmapSet.StoryboardFile = archive.StoryboardFilename;
            }

            return(beatmapSet);
        }
Exemplo n.º 13
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);
        }
Exemplo n.º 14
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);
        }