Пример #1
0
        private async void ToggleSearch(object sender, EventArgs e)
        {
            if (_searchCancelToken != null)
            {
                _searchCancelToken.Cancel();
                _searchCancelToken = null;
                return;
            }

            var levelPattern = LevPatternBox.Text;
            var errorFiles   = new List <string>();

            bool searchForFastestReplays;
            bool searchForAllReplays;
            var  clickedButton = (Button)sender;

            if (clickedButton.Equals(SearchButton))
            {
                searchForAllReplays     = fastestSlowestSelect.SelectedOption == 2;
                searchForFastestReplays = fastestSlowestSelect.SelectedOption == 0;
            }
            else
            {
                searchForAllReplays     = true;
                searchForFastestReplays = false;
            }

            var searchOnlyMissingLev = clickedButton.Equals(ReplaysWithoutLevFileButton);
            var searchOnlyWrongLev   = clickedButton.Equals(ReplaysIncorrectLevButton);

            if (!Utils.RecDirectoryExists())
            {
                Utils.ShowError(Constants.RecDirNotFound);
                return;
            }

            var p1Apples = Range <int> .FromNumericBoxes(TextBox1, TextBox14);

            var p2Apples = Range <int> .FromNumericBoxes(TextBox3, TextBox16);

            var p1Turns = Range <int> .FromNumericBoxes(TextBox2, TextBox23);

            var p2Turns = Range <int> .FromNumericBoxes(TextBox10, TextBox15);

            var p1Gt = Range <int> .FromNumericBoxes(TextBox11, TextBox24);

            var p2Gt = Range <int> .FromNumericBoxes(TextBox12, TextBox13);

            var p1Sv = Range <int> .FromNumericBoxes(TextBox4, TextBox21);

            var p2Sv = Range <int> .FromNumericBoxes(TextBox9, TextBox22);

            var p1Rv = Range <int> .FromNumericBoxes(TextBox6, TextBox19);

            var p2Rv = Range <int> .FromNumericBoxes(TextBox7, TextBox20);

            var p1Lv = Range <int> .FromNumericBoxes(TextBox8, TextBox17);

            var p2Lv = Range <int> .FromNumericBoxes(TextBox5, TextBox18);

            Range <double> time;

            try
            {
                time = Utils.GetTimeRange(TimeMinBox.Text, TimeMaxBox.Text);
            }
            catch (Exception)
            {
                Utils.ShowError("Time bound is in wrong format. Make sure it is 9 characters long.");
                return;
            }

            var size = new Range <int>((int)minFileSizeBox.Value * 1024, (int)maxFileSizeBox.Value * 1024);

            Regex levFilenameMatcher;

            try
            {
                levFilenameMatcher = new Regex(levelPattern, RegexOptions.IgnoreCase);
            }
            catch (Exception)
            {
                levFilenameMatcher = new Regex(string.Empty);
            }

            var searchParams = new ReplaySearchParameters
            {
                InternalRec        = SearchParameters.GetBoolOptionFromTriSelect(intExtSelect),
                AcrossLev          = SearchParameters.GetBoolOptionFromTriSelect(elmaAcrossSelect),
                Date               = new Range <DateTime>(minDateTime.Value, maxDateTime.Value),
                Finished           = SearchParameters.GetBoolOptionFromTriSelect(finishedSelect),
                LevExists          = BoolOption.Dontcare,
                WrongLev           = BoolOption.Dontcare,
                LevFilenameMatcher = levFilenameMatcher,
                MultiPlayer        = SearchParameters.GetBoolOptionFromTriSelect(singleMultiSelect),
                Size               = size,
                Time               = time,
                P1Bounds           =
                    new ReplaySearchParameters.PlayerBounds
                {
                    Apples        = p1Apples,
                    GroundTouches = p1Gt,
                    LeftVolts     = p1Lv,
                    RightVolts    = p1Rv,
                    SuperVolts    = p1Sv,
                    Turns         = p1Turns
                },
                P2Bounds =
                    new ReplaySearchParameters.PlayerBounds
                {
                    Apples        = p2Apples,
                    GroundTouches = p2Gt,
                    LeftVolts     = p2Lv,
                    RightVolts    = p2Rv,
                    SuperVolts    = p2Sv,
                    Turns         = p2Turns
                }
            };

            if (searchOnlyMissingLev)
            {
                searchParams.ResetOptions();
                searchParams.LevExists = BoolOption.False;
            }

            if (searchOnlyWrongLev)
            {
                searchParams.ResetOptions();
                searchParams.WrongLev = BoolOption.True;
            }

            var allFiles = Directory.GetFiles(Global.AppSettings.General.ReplayDirectory, "*.rec",
                                              Global.AppSettings.ReplayManager.RecDirSearchOption);
            var replayFiles = searchOnlyMissingLev || searchOnlyWrongLev
                ? allFiles.ToList()
                : Utils.FilterByRegex(allFiles, SearchPattern).ToList();

            ObjectList.ClearObjects();
            var oldButtonText = clickedButton.Text;

            _searchCancelToken              = new CancellationTokenSource();
            DuplicateButton.Enabled         = false;
            DuplicateFilenameButton.Enabled = false;
            ConfigButton.Enabled            = false;
            clickedButton.Text              = "Stop";
            var foundReplays = new List <Replay>();

            ToolStripProgressBar1.Maximum = replayFiles.Count;

            var recsByLevel     = new Dictionary <string, List <Replay> >();
            var token           = _searchCancelToken.Token;
            var progressHandler = new Progress <(int progress, int levels, int recs, int phase)>(value =>
            {
                var(progressValue, levels, recs, phase) = value;
                ToolStripProgressBar1.Value             = progressValue;
                if (searchForAllReplays)
                {
                    statusLabel.Text = $"Found {recs} replays so far";
                }
                else
                {
                    statusLabel.Text = phase == 1 ? $"Phase 1: {levels} levels" : $"Phase 2: {recs} replays";
                }
            });
            var progress = (IProgress <(int progress, int levels, int recs, int phase)>)progressHandler;
            var iter     = 0;

            try
            {
                await Task.Run(() =>
                {
                    foreach (var replayFile in replayFiles)
                    {
                        iter++;
                        Replay srp;
                        try
                        {
                            srp = new Replay(replayFile);
                        }
                        catch (ArgumentException)
                        {
                            errorFiles.Add(replayFile);
                            continue;
                        }

                        if (searchParams.Matches(srp))
                        {
                            if (!searchForAllReplays)
                            {
                                var key = srp.LevelFilename.ToLower() + srp.IsMulti;
                                recsByLevel.TryGetValue(key, out var recs);
                                if (recs == null)
                                {
                                    recs             = new List <Replay>();
                                    recsByLevel[key] = recs;
                                }

                                recs.Add(srp);
                            }
                            else
                            {
                                foundReplays.Add(srp);
                            }
                        }

                        if (iter % 10 == 0)
                        {
                            progress.Report((iter, recsByLevel.Count, foundReplays.Count, 1));
                        }
                        token.ThrowIfCancellationRequested();
                    }
                }, token);
            }
            catch (OperationCanceledException)
            {
                Finalize();
                return;
            }

            if (!searchForAllReplays)
            {
                ToolStripProgressBar1.Maximum = recsByLevel.Count;
                iter = 0;
                try
                {
                    await Task.Run(() =>
                    {
                        foreach (var rbl in recsByLevel)
                        {
                            iter++;
                            var matchedReplay = rbl.Value[0];
                            foreach (var z in rbl.Value.Where(z => !z.WrongLevelVersion))
                            {
                                if (searchForFastestReplays)
                                {
                                    if (!matchedReplay.Finished && z.Finished)
                                    {
                                        matchedReplay = z;
                                    }
                                    else if (matchedReplay.Finished && z.Finished && z.Time < matchedReplay.Time)
                                    {
                                        matchedReplay = z;
                                    }
                                    else if (!matchedReplay.Finished && !z.Finished &&
                                             z.Player1.Apples > matchedReplay.Player1.Apples)
                                    {
                                        matchedReplay = z;
                                    }
                                }
                                else
                                {
                                    if (matchedReplay.Finished && !z.Finished)
                                    {
                                        matchedReplay = z;
                                    }
                                    else if (matchedReplay.Finished && z.Finished && z.Time > matchedReplay.Time)
                                    {
                                        matchedReplay = z;
                                    }
                                    else if (!matchedReplay.Finished && !z.Finished &&
                                             (z.Player1.Apples < matchedReplay.Player1.Apples ||
                                              matchedReplay.Time > z.Time))
                                    {
                                        matchedReplay = z;
                                    }
                                }
                            }

                            if (searchForFastestReplays || rbl.Value.Count > 1)
                            {
                                foundReplays.Add(matchedReplay);
                            }
                            if (iter % 10 == 0)
                            {
                                progress.Report((iter, recsByLevel.Count, foundReplays.Count, 2));
                            }
                            token.ThrowIfCancellationRequested();
                        }
                    }, token);
                }
                catch (OperationCanceledException)
                {
                }
            }

            Finalize();

            void Finalize()
            {
                ObjectList.SetObjects(foundReplays);
                statusLabel.Text                = "Ready";
                ToolStripProgressBar1.Value     = 0;
                _searchCancelToken              = null;
                DuplicateButton.Enabled         = true;
                DuplicateFilenameButton.Enabled = true;
                ConfigButton.Enabled            = true;
                clickedButton.Text              = oldButtonText;
                DisplaySelectionInfo();
                if (errorFiles.Count > 0)
                {
                    using (var ef = new ErrorForm(errorFiles))
                    {
                        ef.ShowDialog();
                    }
                }
            }
        }
        private async void searchButton_Click(object sender, EventArgs e)
        {
            if (_searchCancelToken != null)
            {
                _searchCancelToken.Cancel();
                _searchCancelToken = null;
                return;
            }

            if (!Utils.LevDirectoryExists())
            {
                Utils.ShowError(Constants.LevDirNotFound);
                return;
            }
            var res = GetRegexes();

            if (!res.HasValue)
            {
                Utils.ShowError("Some of the search parameters have invalid syntax (regex).");
                return;
            }

            var allFiles = Directory.GetFiles(Global.AppSettings.General.LevelDirectory, "*.lev",
                                              Global.AppSettings.LevelManager.LevDirSearchOption);
            var recFiles = Directory.GetFiles(Global.AppSettings.General.ReplayDirectory, "*.rec",
                                              Global.AppSettings.LevelManager.RecDirSearchOption);
            var levFiles = Utils.FilterByRegex(allFiles, SearchPattern).ToList();

            searchProgressBar.Maximum = recFiles.Length;
            var progressHandler = new Progress <(int progress, string statusText)>(value =>
            {
                var(progressValue, status) = value;
                searchProgressBar.Value    = progressValue;
                statusLabel.Text           = status;
            });
            var progress = (IProgress <(int progress, string statusText)>)progressHandler;

            var errorFiles = new List <string>();

            _recsByLevel       = new Dictionary <string, List <Replay> >();
            _searchCancelToken = new CancellationTokenSource();
            var token         = _searchCancelToken.Token;
            var foundLevs     = new List <Level>();
            var clickedButton = (Button)sender;
            var oldButtonText = clickedButton.Text;

            clickedButton.Text = "Stop";
            try
            {
                await Task.Run(() =>
                {
                    var iter = 0;
                    foreach (var f in recFiles)
                    {
                        iter++;
                        var r   = new Replay(f);
                        var key = r.LevelFilename.ToLower() + r.LevId;
                        _recsByLevel.TryGetValue(key, out var list);
                        if (list == null)
                        {
                            list = new List <Replay>();
                            _recsByLevel[key] = list;
                        }

                        list.Add(r);
                        if (iter % 10 == 0)
                        {
                            progress.Report((iter, $"Processing replay files first: {iter} of {recFiles.Length}"));
                        }
                        token.ThrowIfCancellationRequested();
                    }
                }, token);
            }
            catch (OperationCanceledException)
            {
                Finalize();
                return;
            }

            searchProgressBar.Maximum = levFiles.Count;
            var(titleRe, lgrRe, gtRe, stRe, spnRe, mpnRe) = res.Value;
            var searchParams = new LevelSearchParameters
            {
                AcrossLev            = SearchParameters.GetBoolOptionFromTriSelect(elmaAcrossSelect),
                Date                 = new Range <DateTime>(minDateTime.Value, maxDateTime.Value),
                Size                 = new Range <int>((int)minFileSizeBox.Value * 1024, (int)maxFileSizeBox.Value * 1024),
                Title                = titleRe,
                Lgr                  = lgrRe,
                GroundTexture        = gtRe,
                SkyTexture           = stRe,
                SinglePlayerNick     = spnRe,
                MultiPlayerNick      = mpnRe,
                SinglePlayerBestTime = Utils.GetTimeRange(minSingleBestTimeBox.Text, maxSingleBestTimeBox.Text),
                MultiPlayerBestTime  = Utils.GetTimeRange(minMultiBestTimeBox.Text, maxMultiBestTimeBox.Text),
                GroundPolygons       = Range <int> .FromNumericBoxes(minGroundPolygonsBox, maxGroundPolygonsBox),
                GroundVertices       = Range <int> .FromNumericBoxes(minGroundVerticesBox, maxGroundVerticesBox),
                GrassPolygons        = Range <int> .FromNumericBoxes(minGrassPolygonsBox, maxGrassPolygonsBox),
                GrassVertices        = Range <int> .FromNumericBoxes(minGrassVerticesBox, maxGrassVerticesBox),
                SingleTop10Times     = Range <int> .FromNumericBoxes(minSingleplayerTimesBox, maxSingleplayerTimesBox),
                MultiTop10Times      = Range <int> .FromNumericBoxes(minMultiplayerTimesBox, maxMultiplayerTimesBox),
                Killers              = Range <int> .FromNumericBoxes(minKillersBox, maxKillersBox),
                Flowers              = Range <int> .FromNumericBoxes(minFlowersBox, maxFlowersBox),
                Pictures             = Range <int> .FromNumericBoxes(minPicturesBox, maxPicturesBox),
                Textures             = Range <int> .FromNumericBoxes(minTexturesBox, maxTexturesBox),
                Apples               = Range <int> .FromNumericBoxes(minApplesBox, maxApplesBox),
                GravApples           = new Dictionary <AppleType, Range <int> >
                {
                    { AppleType.Normal, Range <int> .FromNumericBoxes(minNormApplesBox, maxNormApplesBox) },
                    { AppleType.GravityUp, Range <int> .FromNumericBoxes(minGravUpApplesBox, maxGravUpApplesBox) },
                    { AppleType.GravityDown, Range <int> .FromNumericBoxes(minGravDownApplesBox, maxGravDownApplesBox) },
                    { AppleType.GravityLeft, Range <int> .FromNumericBoxes(minGravLeftApplesBox, maxGravLeftApplesBox) },
                    { AppleType.GravityRight, Range <int> .FromNumericBoxes(minGravRightApplesBox, maxGravRightApplesBox) }
                }
            };

            try
            {
                await Task.Run(() =>
                {
                    var iter = 0;
                    foreach (var levFile in levFiles)
                    {
                        iter++;
                        Level srp;
                        try
                        {
                            srp = Level.FromPath(levFile);
                        }
                        catch (ArgumentException)
                        {
                            errorFiles.Add(levFile);
                            continue;
                        }

                        if (searchParams.Matches(srp))
                        {
                            foundLevs.Add(srp);
                        }

                        if (iter % 10 == 0)
                        {
                            progress.Report((iter, $"Found {foundLevs.Count} levels so far"));
                        }
                        token.ThrowIfCancellationRequested();
                    }
                }, token);
            }
            catch (OperationCanceledException)
            {
            }

            Finalize();

            void Finalize()
            {
                foreach (var lev in foundLevs)
                {
                    var key = lev.FileName.ToLower() + lev.Identifier;
                    _recsByLevel.TryGetValue(key, out var recs);
                    if (recs != null)
                    {
                        lev.Replays = recs.Count;
                    }
                }

                ObjectList.SetObjects(foundLevs);
                statusLabel.Text        = "Ready";
                searchProgressBar.Value = 0;
                _searchCancelToken      = null;
                configButton.Enabled    = true;
                clickedButton.Text      = oldButtonText;
                DisplaySelectionInfo();
                if (errorFiles.Count > 0)
                {
                    using (var ef = new ErrorForm(errorFiles))
                    {
                        ef.ShowDialog();
                    }
                }
            }
        }