Esempio n. 1
0
        private void GenerateCollections(object sender, object data = null)
        {
            if (_userTopGeneratorForm == null || _userTopGeneratorForm.IsDisposed)
            {
                _userTopGeneratorForm = GuiComponentsProvider.Instance.GetClassImplementing <IUserTopGeneratorForm>();
                var model = new UserTopGeneratorModel((a) =>
                                                      _collectionGenerator.CreateCollectionName(new ApiScore()
                {
                    EnabledMods = (int)(Mods.Hr | Mods.Hd)
                },
                                                                                                "Piotrekol", a));
                model.GenerateUsernames += GenerateUsernames;
                new UserTopGeneratorFormPresenter(model, _userTopGeneratorForm);
                model.Start           += (s, a) => _collectionGenerator.GenerateCollection(model.GeneratorConfiguration);
                model.SaveCollections +=
                    (s, a) => _collectionEditor.EditCollection(CollectionEditArgs.AddCollections(model.Collections));
                model.Abort += (s, a) => _collectionGenerator.Abort();
                _collectionGenerator.StatusUpdated +=
                    (s, a) =>
                {
                    model.GenerationStatus = _collectionGenerator.Status;
                    model.GenerationCompletionPrecentage = _collectionGenerator.ProcessingCompletionPrecentage;
                };

                _collectionGenerator.CollectionsUpdated +=
                    (s, a) => model.Collections          = _collectionGenerator.Collections;
            }
            _userTopGeneratorForm.Show();
        }
        public void EditCollection(CollectionEditArgs e)
        {
            if (e.Action == CollectionEdit.Rename || e.Action == CollectionEdit.Add)
            {
                bool isRenameform = e.Action == CollectionEdit.Rename;

                var newCollectionName = _collectionAddRenameForm
                                        .GetCollectionName(IsCollectionNameValid, e.OrginalName, isRenameform);

                if (newCollectionName == "")
                {
                    return;
                }
                if (e.Action == CollectionEdit.Rename)
                {
                    e = CollectionEditArgs.RenameCollection(e.OrginalName, newCollectionName);
                }
                else
                {
                    e = CollectionEditArgs.AddCollections(new Collections()
                    {
                        new Collection(_mapCacher)
                        {
                            Name = newCollectionName
                        }
                    });
                }
            }

            _collectionEditor.EditCollection(e);
        }
Esempio n. 3
0
        private void _view_RightClick(object sender, Gui.Misc.StringEventArgs e)
        {
            var selectedCollections = _model.SelectedCollections;
            CollectionEditArgs args;

            switch (e.Value)
            {
            case "Delete":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.RemoveCollections(selectedCollections);
                break;

            case "Merge":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.MergeCollections(selectedCollections, selectedCollections[0].Name);
                break;

            case "Intersect":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.IntersectCollections(selectedCollections, selectedCollections[0].Name);
                break;

            case "Create":
                args = CollectionEditArgs.AddCollections(null);
                break;

            case "Rename":
                if (_view.SelectedCollection == null)
                {
                    return;
                }
                args = CollectionEditArgs.RenameCollection(_view.SelectedCollection, null);
                break;

            case "Duplicate":
                if (_view.SelectedCollection == null)
                {
                    return;
                }

                args = CollectionEditArgs.DuplicateCollection(_view.SelectedCollection);
                break;

            default:
                return;
            }

            _model.EmitCollectionEditing(args);
        }
Esempio n. 4
0
        private async void UploadNewCollections(object sender, object data = null)
        {
            if (!await Initalizer.WebCollectionProvider.IsCurrentKeyValid())
            {
                _userDialogs.OkMessageBox("You need to login before uploading collections", "Error", MessageBoxType.Error);
                return;
            }

            var collectionList = (IList <ICollection>)data;

            foreach (var c in collectionList)
            {
                if (!c.AllBeatmaps().Any())
                {
                    _userDialogs.OkMessageBox("Empty collection - upload aborted", "Error", MessageBoxType.Error);
                    return;
                }
            }

            var oldCollections = new Collections();

            oldCollections.AddRange(collectionList);

            var newCollections = new Collections();

            foreach (var c in collectionList)
            {
                var webCollection = new WebCollection(0, _osuFileIo.LoadedMaps, true);
                webCollection.Name = c.Name;
                webCollection.LastEditorUsername = c.LastEditorUsername;

                foreach (var collectionBeatmap in c.AllBeatmaps())
                {
                    webCollection.AddBeatmap(collectionBeatmap);
                }

                newCollections.AddRange(await webCollection.Save(Initalizer.WebCollectionProvider));
            }

            _collectionEditor.EditCollection(CollectionEditArgs.RemoveCollections(oldCollections));
            _collectionEditor.EditCollection(CollectionEditArgs.AddCollections(newCollections));

            var sidePanel = (IOnlineCollectionList)_mainForm.SidePanelView;

            sidePanel.WebCollections.AddRange(newCollections.OfType <WebCollection>());
            sidePanel.WebCollections.CallReset();

            if (newCollections.Count > 0)
            {
                _userDialogs.OkMessageBox($"Collections uploaded", "Info", MessageBoxType.Success);
            }
            if (newCollections.Count == 1)
            {
                Process.Start($"https://osustats.ppy.sh/collection/{newCollections[0].OnlineId}");
            }
        }
        private void LoadDefaultCollection()
        {
            var fileLocation = Path.Combine(Initalizer.OsuDirectory, "collection.db");

            if (File.Exists(fileLocation))
            {
                var loadedCollections = _osuFileIo.CollectionLoader.LoadCollection(fileLocation);
                _collectionEditor.EditCollection(CollectionEditArgs.AddCollections(loadedCollections));
            }
        }
        public void EditCollection(CollectionEditArgs e)
        {
            if (e.Action == CollectionEdit.Rename || e.Action == CollectionEdit.Add)
            {
                bool isRenameform = e.Action == CollectionEdit.Rename;

                var newCollectionName = _collectionAddRenameForm
                                        .GetCollectionName(IsCollectionNameValid, e.OrginalName, isRenameform);

                if (newCollectionName == "")
                {
                    return;
                }
                switch (e.Action)
                {
                case CollectionEdit.Rename:
                    e = CollectionEditArgs.RenameCollection(e.OrginalName, newCollectionName);
                    break;

                case CollectionEdit.Add:
                    e = CollectionEditArgs.AddCollections(new Collections()
                    {
                        new Collection(_mapCacher)
                        {
                            Name = newCollectionName
                        }
                    });
                    break;
                }
            }

            if (e.Action == CollectionEdit.Duplicate)
            {
                var newCollection = new Collection(_mapCacher)
                {
                    Name = GetValidCollectionName(e.OrginalName)
                };

                _collectionEditor.EditCollection(
                    CollectionEditArgs.AddCollections(new Collections()
                {
                    newCollection
                })
                    );

                var beatmaps = new Beatmaps();
                beatmaps.AddRange(e.Collections[0].AllBeatmaps());

                e = CollectionEditArgs.AddBeatmaps(newCollection.Name, beatmaps);
            }

            _collectionEditor.EditCollection(e);
        }
        private void LoadCollectionFile()
        {
            var fileLocation = _userDialogs.SelectFile("", "Collection database (*.db/*.osdb)|*.db;*.osdb",
                                                       "collection.db");

            if (fileLocation == string.Empty)
            {
                return;
            }
            var loadedCollections = _osuFileIo.CollectionLoader.LoadCollection(fileLocation);

            _collectionEditor.EditCollection(CollectionEditArgs.AddCollections(loadedCollections));
        }
Esempio n. 8
0
        public async Task Run(string[] args)
        {
            //IUserDialogs can be implemented in WinForm or WPF or Gtk or Console or...?
            UserDialogs = GuiComponentsProvider.Instance.GetClassImplementing <IUserDialogs>();



            //Init "main" classes
            CollectionsManager = new CollectionsManagerWithCounts(LoadedBeatmaps);

            var collectionAddRemoveForm = GuiComponentsProvider.Instance.GetClassImplementing <ICollectionAddRenameForm>();

            CollectionEditor = new CollectionEditor(CollectionsManager, CollectionsManager, collectionAddRemoveForm, OsuFileIo.LoadedMaps);

            var updateChecker = new UpdateChecker();

            updateChecker.CheckForUpdates();
            var infoTextModel = new InfoTextModel(updateChecker);

            var mainForm      = GuiComponentsProvider.Instance.GetClassImplementing <IMainFormView>();
            var mainPresenter = new MainFormPresenter(mainForm, new MainFormModel(CollectionEditor, UserDialogs), infoTextModel, WebCollectionProvider);

            //set initial text info and update events
            SetTextData(infoTextModel);

            var loginForm         = GuiComponentsProvider.Instance.GetClassImplementing <ILoginFormView>();
            var guiActionsHandler = new GuiActionsHandler(OsuFileIo, CollectionsManager, UserDialogs, mainForm, mainPresenter, loginForm);

            if (!string.IsNullOrWhiteSpace(Settings.Default.Osustats_apiKey))
            {
                guiActionsHandler.SidePanelActionsHandler.OsustatsLogin(null, Settings.Default.Osustats_apiKey);
            }

            if (args.Length > 0)
            {
                if (File.Exists(args[0]))
                {
                    CollectionsManager.EditCollection(CollectionEditArgs.AddCollections(OsuFileIo.CollectionLoader.LoadCollection(args[0])));
                }
            }

            StartupPresenter = new StartupPresenter(GuiComponentsProvider.Instance.GetClassImplementing <IStartupForm>(), guiActionsHandler.SidePanelActionsHandler, UserDialogs, CollectionsManager);
            await StartupPresenter.Run();


            mainForm.ShowAndBlock();

            Quit();
        }
Esempio n. 9
0
        private void AddCollections(object sender, object data = null)
        {
            var webCollections = (IList <WebCollection>)data;

            var collections = new Collections();

            foreach (var webCollection in webCollections)
            {
                if (!Initalizer.CollectionsManager.LoadedCollections.Contains(webCollection))
                {
                    collections.Add(webCollection);
                }
            }

            Initalizer.CollectionsManager.EditCollection(CollectionEditArgs.AddCollections(collections));
        }
Esempio n. 10
0
        private void LoadCollection(string fileLocation)
        {
            if (string.IsNullOrEmpty(fileLocation) || !File.Exists(fileLocation))
            {
                return;
            }

            try
            {
                var loadedCollections = _osuFileIo.CollectionLoader.LoadCollection(fileLocation);
                _collectionEditor.EditCollection(CollectionEditArgs.AddCollections(loadedCollections));
            }
            catch (CorruptedFileException ex)
            {
                _userDialogs.OkMessageBox(ex.Message, "Error", MessageBoxType.Error);
            }
        }
Esempio n. 11
0
        private void LoadCollection(string fileLocation)
        {
            if (string.IsNullOrEmpty(fileLocation) || !File.Exists(fileLocation))
            {
                return;
            }

            try
            {
                var loadedCollections = _osuFileIo.CollectionLoader.LoadCollection(fileLocation);
                //var cc = string.Join("\n",loadedCollections.SelectMany(c => c.AllBeatmaps()).Select(bb => bb.Md5));
                _collectionEditor.EditCollection(CollectionEditArgs.AddCollections(loadedCollections));
            }
            catch (CorruptedFileException ex)
            {
                _userDialogs.OkMessageBox(ex.Message, "Error", MessageBoxType.Error);
            }
        }
Esempio n. 12
0
        private void LoadCollections(string[] fileLocations)
        {
            if (fileLocations == null || fileLocations.Length == 0 || fileLocations.Any(string.IsNullOrWhiteSpace))
            {
                return;
            }

            Collections collections = new();

            foreach (string fileLocation in fileLocations)
            {
                try
                {
                    collections.AddRange(_osuFileIo.CollectionLoader.LoadCollection(fileLocation));
                }
                catch (CorruptedFileException ex)
                {
                    _userDialogs.OkMessageBox(ex.Message, "Error", MessageBoxType.Error);
                }
            }

            _collectionEditor.EditCollection(CollectionEditArgs.AddCollections(collections));
        }
        private void _view_RightClick(object sender, Gui.Misc.StringEventArgs e)
        {
            var selectedCollections = _model.SelectedCollections;
            CollectionEditArgs args;

            switch (e.Value)
            {
            case "Delete":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.RemoveCollections(selectedCollections);
                break;

            case "Merge":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.MergeCollections(selectedCollections, selectedCollections[0].Name);
                break;

            case "Intersect":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.IntersectCollections(selectedCollections, selectedCollections[0].Name);
                break;

            case "Inverse":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.InverseCollections(selectedCollections, selectedCollections[0].Name);
                break;

            case "Difference":
                if (selectedCollections == null)
                {
                    return;
                }
                args = CollectionEditArgs.DifferenceCollections(selectedCollections, selectedCollections[0].Name);
                break;

            case "Create":
                args = CollectionEditArgs.AddCollections(null);
                break;

            case "Rename":
                if (_view.SelectedCollection == null)
                {
                    return;
                }
                args = CollectionEditArgs.RenameCollection(_view.SelectedCollection, null);
                break;

            case "Duplicate":
                if (_view.SelectedCollection == null)
                {
                    return;
                }

                args = CollectionEditArgs.DuplicateCollection(_view.SelectedCollection);
                break;

            case "Export":
                if (selectedCollections == null)
                {
                    return;
                }

                args = CollectionEditArgsExtension.ExportBeatmaps(selectedCollections);
                break;

            case "Copy":
                if (selectedCollections == null)
                {
                    return;
                }
                var tempFolder = Path.Combine(Path.GetTempPath(), "CMcollections");
                if (Directory.Exists(tempFolder))
                {
                    Directory.Delete(tempFolder, true);
                }

                Directory.CreateDirectory(tempFolder);
                var fileName     = Helpers.StripInvalidFileNameCharacters(selectedCollections[0].Name, "_");
                var tempLocation = Path.Combine(tempFolder, $"{fileName}.osdb");
                Initalizer.OsuFileIo.CollectionLoader.SaveOsdbCollection(selectedCollections, tempLocation);
                Clipboard.SetFileDropList(new StringCollection {
                    tempLocation
                });
                return;

            default:
                return;
            }

            _model.EmitCollectionEditing(args);
        }
Esempio n. 14
0
        internal void Run()
        {
            var osuFileIo = new OsuFileIo(new BeatmapExtension());

            //Automatic Detection of osu! directory location
            string dir = osuFileIo.OsuPathResolver.GetOsuDir(ThisPathIsCorrect, SelectDirectoryDialog);



            string osuPath       = @"E:\osu!\";
            string osuDbFileName = "osu!.db";
            string ExampleCollectionFileLocation = @"E:\osuCollections\SomeCollectionThatExists.db";



            osuFileIo.OsuDatabase.Load(osuPath + osuDbFileName);

            //osu! configuration file is currently only used for getting a songs folder location
            osuFileIo.OsuSettings.Load(osuPath);

            //Data loaded using next 2 functions are going to be automatically correlated
            //with currently avalable beatmap data.
            osuFileIo.CollectionLoader.LoadOsuCollection(ExampleCollectionFileLocation);
            //osuFileIo.CollectionLoader.LoadOsdbCollection("");


            string osuSongsFolderLocation = osuFileIo.OsuSettings.CustomBeatmapDirectoryLocation;

            //Create Collection manager instance
            var collectionManager = new CollectionsManagerWithCounts(osuFileIo.OsuDatabase.LoadedMaps.Beatmaps);

            //or just this:
            //var collectionManager = new CollectionsManager(osuFileIo.OsuDatabase.LoadedMaps.Beatmaps);

            collectionManager.LoadedCollections.CollectionChanged += LoadedCollections_CollectionChanged;

            //Create some dummy collections
            Collection ourCollection = new Collection(osuFileIo.LoadedMaps)
            {
                Name = "Example collection1"
            };
            Collection ourSecondCollection = new Collection(osuFileIo.LoadedMaps)
            {
                Name = "Example collection2"
            };

            //Add these to our manager
            collectionManager.EditCollection(
                CollectionEditArgs.AddCollections(new Collections()
            {
                ourCollection, ourSecondCollection
            })
                );

            //Add some beatmaps to ourSecondCollection
            collectionManager.EditCollection(
                CollectionEditArgs.AddBeatmaps("Example collection2", new Beatmaps()
            {
                new BeatmapExtension()
                {
                    Md5 = "'known' md5"
                },
                new BeatmapExtension()
                {
                    Md5 = "another 'known' md5"
                },
                new BeatmapExtension()
                {
                    Md5 = "md5 that we have no idea about"
                }
            }));

            //Trying to issue any action on collection with unknown name will be just ignored
            collectionManager.EditCollection(
                CollectionEditArgs.AddBeatmaps("Collection that doesn't exist", new Beatmaps()
            {
                new BeatmapExtension()
                {
                    Md5 = "1234567890,yes I know these aren't valid md5s"
                }
            }));

            //Merge our collections into one.
            //Note that while I do not impose a limit on collection name length, osu! does and it will be truncated upon opening collection in osu! client.
            collectionManager.EditCollection(
                CollectionEditArgs.MergeCollections(new Collections()
            {
                ourCollection, ourSecondCollection
            }
                                                    , "Collection created from 2 Example collections")
                );

            //true
            bool isNameTaken = collectionManager.CollectionNameExists("Collection created from 2 Example collections");

            ICollection ourMergedCollection = collectionManager.GetCollectionByName("Collection created from 2 Example collections");

            //These are avaliable only when using CollectionsManagerWithCounts
            var TotalBeatmapCount    = collectionManager.BeatmapsInCollectionsCount;
            var MissingBeatmapsCount = collectionManager.MissingMapSetsCount;

            //Lets save our collections after edits
            //as .osdb
            osuFileIo.CollectionLoader.SaveOsdbCollection(collectionManager.LoadedCollections, ExampleCollectionFileLocation);
            //or .db
            osuFileIo.CollectionLoader.SaveOsuCollection(collectionManager.LoadedCollections, ExampleCollectionFileLocation);
        }
Esempio n. 15
0
        static void Main(string[] args)
        {
            try
            {
                if (System.Threading.Thread.CurrentThread.CurrentCulture.Name.StartsWith("zh"))
                {
                    language = JsonConvert.DeserializeObject <Language>(Encoding.UTF8.GetString(Properties.Resources.zh_tw));                                                                            //假如是中文語系,就使用中文
                }
                else
                {
                    language = new Language();  //否則,英文
                }
            }
            catch (Exception) { language = new Language(); /*這邊是當跳出錯誤時,使用英文。正常來說是不會有錯誤才對,但有次比賽拿來做測試的時候出了錯誤,也抓不到點,就先認定是語系的問題了*/ }

            Console.Title = language.AppTitle;

            if (OsuPathResolver.Instance.OsuIsRunning)
            {
                FormatWrite(language.DetectionOsuIsRunning, ConsoleColor.Red);
            }

            OpenFileDialog openFileDialog = new OpenFileDialog(); //選擇收藏夾檔案的對話方塊

            openFileDialog.AddExtension    = true;
            openFileDialog.CheckFileExists = true;
            openFileDialog.CheckPathExists = true;
            openFileDialog.DefaultExt      = "json";
            openFileDialog.Filter          = language.OpenFileFilter;
            openFileDialog.Multiselect     = false;

            if (openFileDialog.ShowDialog() == DialogResult.Cancel)
            {
                Exit(language.PleaseSelectCollection, true);
            }

            JsonData collectionData = null;

            try { collectionData = JsonConvert.DeserializeObject <JsonData>(File.ReadAllText(openFileDialog.FileName)); } //讀取收藏夾資料
            catch (Exception) { }
            if (collectionData == null || collectionData.collection_data == null)
            {
                Exit(language.ReadCollectionFail, true);
            }

            string osuPath = OsuPathResolver.Instance.GetOsuDir((path) => { //第一次會先偵測osu的路徑,然後提示使用者是否正確
                var dialogResult = MessageBox.Show(
                    string.Format(
                        language.ConfirmOsuPath, Environment.NewLine + path, Environment.NewLine),
                    "", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk);
                return(dialogResult == DialogResult.Yes);
            }, (text) => {
                FolderBrowserDialog dialog = new FolderBrowserDialog(); //假如是錯誤的,那就開個資料夾選擇對話框,讓使用者自行選擇osu的路徑

                dialog.ShowNewFolderButton = false;
                dialog.Description         = language.PleaseSelectOsuPath;
                dialog.RootFolder          = Environment.SpecialFolder.MyComputer;
                if (dialog.ShowDialog() == DialogResult.OK && Directory.Exists(dialog.SelectedPath))
                {
                    return(dialog.SelectedPath);
                }
                return("");
            });

            if (osuPath == string.Empty || !Directory.Exists(osuPath))
            {
                Exit(language.NeedValidOsuPath, true);
            }
            if (!osuPath.EndsWith("\\"))
            {
                osuPath += "\\";
            }

            FormatWrite(string.Format(language.OsuPath, osuPath), ConsoleColor.Yellow);
            OsuFileIo.OsuSettings.Load(osuPath);
            OsuFileIo.OsuDatabase.Load(osuPath + "osu!.db"); //載入osu的資料庫來抓取songs的資料夾路徑

            List <BeatmapData> needDownloadBeatmapList = new List <BeatmapData>();
            var collectionManager = new CollectionsManager(OsuFileIo.OsuDatabase.LoadedMaps.Beatmaps); Collection collection;                          //初始化目前osu所有的Beatmap

            collectionManager.EditCollection(CollectionEditArgs.AddCollections(OsuFileIo.CollectionLoader.LoadCollection(osuPath + "collection.db"))); //載入原先的收藏夾

            foreach (CollectionData item in collectionData.collection_data)
            {
                FormatWrite(string.Format(language.CollectionName, item.collection_name), ConsoleColor.Yellow);

                if (collectionManager.CollectionNameExists(item.collection_name))
                {
                    collection = collectionManager.GetCollectionByName(item.collection_name);                                                               //如果收藏夾已經存在,就讀取出來
                }
                else
                {
                    collection = new Collection(OsuFileIo.LoadedMaps)
                    {
                        Name = item.collection_name
                    }
                };                                                                                      //否則新建一個

                foreach (BeatmapData item2 in item.beatmap_data)
                {
                    if (!collection.AllBeatmaps().Any((x) => x.MapId == item2.beatmap_id)) //讀取收藏夾內的Beatmap,如果要匯入的收藏夾Beatmap ID不存在於收藏夾內,那就新增進去
                    {
                        FormatWrite(string.Format(language.AddBeatmapToCollection, item2.beatmap_name), ConsoleColor.Green);
                        collection.AddBeatmapByHash(item2.beatmap_md5);                                         //新增Beatmap,使用Hash新增法
                        if (!OsuFileIo.OsuDatabase.LoadedMaps.Beatmaps.Any((x) => x.MapId == item2.beatmap_id)) //如果osu資料庫裡面沒有該Beatmap
                        {
                            needDownloadBeatmapList.Add(item2);                                                 //就新增到下載清單內
                            FormatWrite(language.NeedDownloadBeatmap, ConsoleColor.Cyan);
                        }
                    }
                }

                collectionManager.EditCollection(CollectionEditArgs.RemoveCollections(new Collections()
                {
                    collection
                }));                                                                                                      //先把收藏夾移除
                collectionManager.EditCollection(CollectionEditArgs.AddCollections(new Collections()
                {
                    collection
                }));                                                                                                   //再把收藏夾新增,以達成重整的效果
            }

            if (needDownloadBeatmapList.Count != 0) //如果下載清單數量不為0,就進入下載程序
            {
                FormatWrite(language.DownloadBeatmapInfo, ConsoleColor.Green);
                CookieAwareWebClient cookieAwareWebClient = new CookieAwareWebClient(); //CollectionManager提供的class,可以讓WebClient使用cookie的功能
                string username, password;
                do
                {
                    Console.Write(language.OsuUsername); username = Console.ReadLine();
                    Console.Write(language.OsuPassword); password = "";
                    do
                    {
                        ConsoleKeyInfo key = Console.ReadKey(true);
                        if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter)
                        {
                            password += key.KeyChar;
                            Console.Write("*");
                        }
                        else
                        {
                            if (key.Key == ConsoleKey.Backspace && password.Length > 0)
                            {
                                password = password.Substring(0, (password.Length - 1));
                                Console.Write("\b \b");
                            }
                            else if (key.Key == ConsoleKey.Enter)
                            {
                                Console.WriteLine();
                                break;
                            }
                        }
                    } while (true);

                    try { if (!cookieAwareWebClient.Login(loginAddress, string.Format(loginDataStr, username, password)).Contains("I don't have an account"))
                          {
                              break;
                          }
                    }                                                                                                                                                  //登入失敗的話,回傳的網頁資料會有I don't have an account
                    catch (Exception ex) { Exit(string.Format(language.LoginErrorElseReason, ex.Message)); }

                    FormatWrite(language.LoginError, ConsoleColor.Red);
                } while (true);

                bool downloadVideo = MessageBox.Show(language.DownloadBeatmapWithVideo, "", MessageBoxButtons.YesNo) == DialogResult.Yes; //提示下載時是否包含背景影片

                needDownloadBeatmapList.ForEach((item) => {
                    string savePath = OsuFileIo.OsuSettings.CustomBeatmapDirectoryLocation + item.beatmap_setid + " " + StripInvalidCharacters(item.beatmap_name) + ".osz"; //存放路徑: osu的songs資料夾 + BeatmapSet ID + BeatmapSet Name
                    if (!File.Exists(savePath))
                    {
                        FormatWrite(string.Format(language.DownloadBeatmapName, Path.GetFileName(savePath)), ConsoleColor.Green);
                        try { File.WriteAllBytes(savePath, cookieAwareWebClient.DownloadData("https://osu.ppy.sh/d/" + item.beatmap_setid + (downloadVideo ? "n" : ""))); }
                        catch (Exception ex) { Console.WriteLine(string.Format(language.DownloadFali, ex.Message)); }
                    }
                    else
                    {
                        FormatWrite(string.Format(language.DownloadDone, Path.GetFileName(savePath)), ConsoleColor.Yellow);
                    }
                });
            }

            string backupName = "collection.db-" + DateTime.Now.ToFileTime() + ".bak"; //備份舊的收藏夾檔案

            File.Move(osuPath + "collection.db", osuPath + backupName);                //然後覆蓋新的收藏夾檔案
            Console.WriteLine(string.Format(language.BackupCollectionTo, osuPath + backupName));

            Console.WriteLine(language.WritingNewCollection);
            OsuFileIo.CollectionLoader.SaveOsuCollection(collectionManager.LoadedCollections, osuPath + "collection.db");

            if (OsuPathResolver.Instance.OsuIsRunning)
            {
                if (needDownloadBeatmapList.Count != 0)
                {
                    Exit(language.WriteDone1);
                }
                else
                {
                    Exit(language.WriteDone2);
                }
            }
            else
            {
                if (needDownloadBeatmapList.Count != 0)
                {
                    Exit(language.WriteDone3);
                }
                else
                {
                    Exit(language.WriteDone4);
                }
            }
        }
        public void Run(string[] args)
        {
            //IUserDialogs can be implemented in WinForm or WPF or Gtk or Console or...?
            UserDialogs = GuiComponentsProvider.Instance.GetClassImplementing <IUserDialogs>();

            if (Settings.Default.DontAskAboutOsuDirectory)
            {
                OsuDirectory = OsuFileIo.OsuPathResolver.GetOsuDir(_ => false, _ => Settings.Default.OsuDirectory);
            }
            else
            {
                OsuDirectory = OsuFileIo.OsuPathResolver.GetOsuDir(dir =>
                {
                    var result = UserDialogs.YesNoMessageBox($"Detected osu! in \"{dir}\"{Environment.NewLine}Is that correct?", "osu! directory", MessageBoxType.Question,
                                                             "Don't ask me again");
                    Settings.Default.DontAskAboutOsuDirectory = result.doNotAskAgain;
                    Settings.Default.Save();
                    return(result.Result);
                }, UserDialogs.SelectDirectory);
            }

            if (string.IsNullOrEmpty(OsuDirectory) && UserDialogs.YesNoMessageBox(
                    "osu! could not be found. Do you want to continue regardless?" + Environment.NewLine +
                    "This will cause all .db collections to show only as beatmap hashes.", "osu! location",
                    MessageBoxType.Question) == false)
            {
                Quit();
            }

            if (!string.IsNullOrEmpty(OsuDirectory))
            {
                Settings.Default.OsuDirectory = OsuDirectory;
                Settings.Default.Save();
                //Load osu database and setting files
                var osuDbFile     = Path.Combine(OsuDirectory, @"osu!.db");
                var osuScoresFile = Path.Combine(OsuDirectory, @"scores.db");
                OsuFileIo.OsuDatabase.Load(osuDbFile);
                OsuFileIo.OsuSettings.Load(OsuDirectory);
                OsuFileIo.ScoresLoader.ReadDb(osuScoresFile);
                BeatmapUtils.OsuSongsDirectory = OsuFileIo.OsuSettings.CustomBeatmapDirectoryLocation;
            }

            //Init "main" classes
            CollectionsManager = new CollectionsManagerWithCounts(LoadedBeatmaps);

            var collectionAddRemoveForm = GuiComponentsProvider.Instance.GetClassImplementing <ICollectionAddRenameForm>();

            CollectionEditor = new CollectionEditor(CollectionsManager, CollectionsManager, collectionAddRemoveForm, OsuFileIo.LoadedMaps);

            if (args.Length > 0)
            {
                if (File.Exists(args[0]))
                {
                    CollectionsManager.EditCollection(CollectionEditArgs.AddCollections(OsuFileIo.CollectionLoader.LoadCollection(args[0])));
                }
            }

            var updateChecker = new UpdateChecker();

            updateChecker.CheckForUpdates();
            var infoTextModel = new InfoTextModel(updateChecker);

            var mainForm      = GuiComponentsProvider.Instance.GetClassImplementing <IMainFormView>();
            var mainPresenter = new MainFormPresenter(mainForm, new MainFormModel(CollectionEditor, UserDialogs), infoTextModel, WebCollectionProvider);

            //set initial text info and update events
            SetTextData(infoTextModel);


            var loginForm         = GuiComponentsProvider.Instance.GetClassImplementing <ILoginFormView>();
            var guiActionsHandler = new GuiActionsHandler(OsuFileIo, CollectionsManager, UserDialogs, mainForm, mainPresenter, loginForm);

            if (!string.IsNullOrWhiteSpace(Settings.Default.Osustats_apiKey))
            {
                guiActionsHandler.SidePanelActionsHandler.OsustatsLogin(null, Settings.Default.Osustats_apiKey);
            }

            mainForm.ShowAndBlock();
            Quit();
        }