<commit_before>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Game.Database;
using osu.Game.Online;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Utils;

namespace osu.Game.Beatmaps.Drawables
{
    public class BundledBeatmapDownloader : CompositeDrawable
    {
        private readonly bool shouldPostNotifications;

        public IEnumerable<BeatmapDownloadTracker> DownloadTrackers => downloadTrackers;

        private readonly List<BeatmapDownloadTracker> downloadTrackers = new List<BeatmapDownloadTracker>();

        private readonly List<string> downloadableFilenames = new List<string>();

        private BundledBeatmapModelDownloader beatmapDownloader;

        /// <summary>
        /// Construct a new beatmap downloader.
        /// </summary>
        /// <param name="onlyTutorial">Whether only the tutorial should be downloaded, instead of bundled beatmaps.</param>
        /// <param name="shouldPostNotifications">Whether downloads should create tracking notifications.</param>
        public BundledBeatmapDownloader(bool onlyTutorial, bool shouldPostNotifications = false)
        {
            this.shouldPostNotifications = shouldPostNotifications;

            if (onlyTutorial)
            {
                queueDownloads(new[] { tutorial_filename });
            }
            else
            {
                queueDownloads(bundled_osu, 8);
                queueDownloads(bundled_taiko, 3);
                queueDownloads(bundled_catch, 3);
                queueDownloads(bundled_mania, 3);
            }
        }

        protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
        {
            var localDependencies = new DependencyContainer(base.CreateChildDependencies(parent));

            localDependencies.CacheAs<BeatmapModelDownloader>(beatmapDownloader = new BundledBeatmapModelDownloader(parent.Get<BeatmapManager>(), parent.Get<IAPIProvider>()));

            if (shouldPostNotifications && parent.Get<INotificationOverlay>() is INotificationOverlay notifications)
                beatmapDownloader.PostNotification = notifications.Post;

            return localDependencies;
        }

        [BackgroundDependencyLoader]
        private void load()
        {
            foreach (string filename in downloadableFilenames)
            {
                var match = Regex.Match(filename, @"([0-9]*) (.*) - (.*)\.osz");

                var beatmapSet = new APIBeatmapSet
                {
                    OnlineID = int.Parse(match.Groups[1].Value),
                    Artist = match.Groups[2].Value,
                    Title = match.Groups[3].Value,
                };

                var beatmapDownloadTracker = new BeatmapDownloadTracker(beatmapSet);
                downloadTrackers.Add(beatmapDownloadTracker);
                AddInternal(beatmapDownloadTracker);

                beatmapDownloader.Download(beatmapSet);
            }
        }

        private void queueDownloads(string[] sourceFilenames, int? limit = null)
        {
            try
            {
                // Matches osu-stable, in order to provide new users with roughly the same randomised selection of bundled beatmaps.
                var random = new LegacyRandom(DateTime.UtcNow.Year * 1000 + (DateTime.UtcNow.DayOfYear / 7));

                downloadableFilenames.AddRange(sourceFilenames.OrderBy(x => random.NextDouble()).Take(limit ?? int.MaxValue));
            }
            catch { }
        }

        private class BundledBeatmapModelDownloader : BeatmapModelDownloader
        {
            public BundledBeatmapModelDownloader(IModelImporter<BeatmapSetInfo> beatmapImporter, IAPIProvider api)
                : base(beatmapImporter, api)
            {
            }

            protected override ArchiveDownloadRequest<IBeatmapSetInfo> CreateDownloadRequest(IBeatmapSetInfo set, bool minimiseDownloadSize)
                => new BundledBeatmapDownloadRequest(set, minimiseDownloadSize);

            public class BundledBeatmapDownloadRequest : DownloadBeatmapSetRequest
            {
                protected override string Uri => $"https://assets.ppy.sh/client-resources/bundled/{Model.OnlineID}.osz";

                public BundledBeatmapDownloadRequest(IBeatmapSetInfo beatmapSetInfo, bool minimiseDownloadSize)
                    : base(beatmapSetInfo, minimiseDownloadSize)
                {
                }
            }
        }

        private const string tutorial_filename = "1011011 nekodex - new beginnings.osz";

        private static readonly string[] bundled_osu =
        {
            "682286 Yuyoyuppe - Emerald Galaxy.osz",
            "682287 baker - For a Dead Girl+.osz",
            "682289 Hige Driver - I Wanna Feel Your Love (feat. shully).osz",
            "682290 Hige Driver - Miracle Sugite Yabai (feat. shully).osz",
            "682416 Hige Driver - Palette.osz",
            "682595 baker - Kimi ga Kimi ga -vocanico remix-.osz",
            "716211 yuki. - Spring Signal.osz",
            "716213 dark cat - BUBBLE TEA (feat. juu & cinders).osz",
            "716215 LukHash - CLONED.osz",
            "716219 IAHN - Snowdrop.osz",
            "716249 *namirin - Senaka Awase no Kuukyo (with Kakichoco).osz",
            "716390 sakuraburst - SHA.osz",
            "716441 Fractal Dreamers - Paradigm Shift.osz",
            "729808 Thaehan - Leprechaun.osz",
            "751771 Cranky - Hanaarashi.osz",
            "751772 Cranky - Ran.osz",
            "751773 Cranky - Feline, the White....osz",
            "751774 Function Phantom - Variable.osz",
            "751779 Rin - Daishibyo set 14 ~ Sado no Futatsuiwa.osz",
            "751782 Fractal Dreamers - Fata Morgana.osz",
            "751785 Cranky - Chandelier - King.osz",
            "751846 Fractal Dreamers - Celestial Horizon.osz",<commit_msg>Add "always bundled" beatmaps<commit_after>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Game.Database;
using osu.Game.Online;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Utils;

namespace osu.Game.Beatmaps.Drawables
{
    public class BundledBeatmapDownloader : CompositeDrawable
    {
        private readonly bool shouldPostNotifications;

        public IEnumerable<BeatmapDownloadTracker> DownloadTrackers => downloadTrackers;

        private readonly List<BeatmapDownloadTracker> downloadTrackers = new List<BeatmapDownloadTracker>();

        private readonly List<string> downloadableFilenames = new List<string>();

        private BundledBeatmapModelDownloader beatmapDownloader;

        /// <summary>
        /// Construct a new beatmap downloader.
        /// </summary>
        /// <param name="onlyTutorial">Whether only the tutorial should be downloaded, instead of bundled beatmaps.</param>
        /// <param name="shouldPostNotifications">Whether downloads should create tracking notifications.</param>
        public BundledBeatmapDownloader(bool onlyTutorial, bool shouldPostNotifications = false)
        {
            this.shouldPostNotifications = shouldPostNotifications;

            if (onlyTutorial)
            {
                queueDownloads(new[] { tutorial_filename });
            }
            else
            {
                queueDownloads(always_bundled_beatmaps);

                queueDownloads(bundled_osu, 8);
                queueDownloads(bundled_taiko, 3);
                queueDownloads(bundled_catch, 3);
                queueDownloads(bundled_mania, 3);
            }
        }

        protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
        {
            var localDependencies = new DependencyContainer(base.CreateChildDependencies(parent));

            localDependencies.CacheAs<BeatmapModelDownloader>(beatmapDownloader = new BundledBeatmapModelDownloader(parent.Get<BeatmapManager>(), parent.Get<IAPIProvider>()));

            if (shouldPostNotifications && parent.Get<INotificationOverlay>() is INotificationOverlay notifications)
                beatmapDownloader.PostNotification = notifications.Post;

            return localDependencies;
        }

        [BackgroundDependencyLoader]
        private void load()
        {
            foreach (string filename in downloadableFilenames)
            {
                var match = Regex.Match(filename, @"([0-9]*) (.*) - (.*)\.osz");

                var beatmapSet = new APIBeatmapSet
                {
                    OnlineID = int.Parse(match.Groups[1].Value),
                    Artist = match.Groups[2].Value,
                    Title = match.Groups[3].Value,
                };

                var beatmapDownloadTracker = new BeatmapDownloadTracker(beatmapSet);
                downloadTrackers.Add(beatmapDownloadTracker);
                AddInternal(beatmapDownloadTracker);

                beatmapDownloader.Download(beatmapSet);
            }
        }

        private void queueDownloads(string[] sourceFilenames, int? limit = null)
        {
            try
            {
                // Matches osu-stable, in order to provide new users with roughly the same randomised selection of bundled beatmaps.
                var random = new LegacyRandom(DateTime.UtcNow.Year * 1000 + (DateTime.UtcNow.DayOfYear / 7));

                downloadableFilenames.AddRange(sourceFilenames.OrderBy(x => random.NextDouble()).Take(limit ?? int.MaxValue));
            }
            catch { }
        }

        private class BundledBeatmapModelDownloader : BeatmapModelDownloader
        {
            public BundledBeatmapModelDownloader(IModelImporter<BeatmapSetInfo> beatmapImporter, IAPIProvider api)
                : base(beatmapImporter, api)
            {
            }

            protected override ArchiveDownloadRequest<IBeatmapSetInfo> CreateDownloadRequest(IBeatmapSetInfo set, bool minimiseDownloadSize)
                => new BundledBeatmapDownloadRequest(set, minimiseDownloadSize);

            public class BundledBeatmapDownloadRequest : DownloadBeatmapSetRequest
            {
                protected override string Uri => $"https://assets.ppy.sh/client-resources/bundled/{Model.OnlineID}.osz";

                public BundledBeatmapDownloadRequest(IBeatmapSetInfo beatmapSetInfo, bool minimiseDownloadSize)
                    : base(beatmapSetInfo, minimiseDownloadSize)
                {
                }
            }
        }

        private const string tutorial_filename = "1011011 nekodex - new beginnings.osz";

        /// <summary>
        /// Contest winners or other special cases.
        /// </summary>
        private static readonly string[] always_bundled_beatmaps =
        {
            // This thing is 40mb, I'm not sure we want it here...
            @"1388906 Raphlesia & BilliumMoto - My Love.osz"
        };

        private static readonly string[] bundled_osu =
        {
            "682286 Yuyoyuppe - Emerald Galaxy.osz",
            "682287 baker - For a Dead Girl+.osz",
            "682289 Hige Driver - I Wanna Feel Your Love (feat. shully).osz",
            "682290 Hige Driver - Miracle Sugite Yabai (feat. shully).osz",
            "682416 Hige Driver - Palette.osz",
            "682595 baker - Kimi ga Kimi ga -vocanico remix-.osz",
            "716211 yuki. - Spring Signal.osz",
            "716213 dark cat - BUBBLE TEA (feat. juu & cinders).osz",
            "716215 LukHash - CLONED.osz",
            "716219 IAHN - Snowdrop.osz",
            "716249 *namirin - Senaka Awase no Kuukyo (with Kakichoco).osz",
            "716390 sakuraburst - SHA.osz",
            "716441 Fractal Dreamers - Paradigm Shift.osz",
            "729808 Thaehan - Leprechaun.osz",
            "751771 Cranky - Hanaarashi.osz",
            "751772 Cranky - Ran.osz",
            "751773 Cranky - Feline, the White....osz",
            "751774 Function Phantom - Variable.osz",
            "751779 Rin - Daishibyo set 14 ~ Sado no Futatsuiwa.osz",
            "751782 Fractal Dreamers - Fata Morgana.osz",
            "751785 Cranky - Chandelier - King.osz",
            "751846 Fractal Dreamers - Celestial Horizon.osz",
{'fraction_non_alphanumeric': 0.08598232284075051, 'fraction_numerical': 0.024732516669251046, 'mean_word_length': 2.233642516921534, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 51, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 93, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '252484', 'n_tokens_mistral': 3756, 'n_tokens_neox': 3411, 'n_words': 794}