Esempio n. 1
0
        public new static int ToNumericResult(HitResult result)
        {
            switch (result)
            {
            // Override Ok and Meh
            case HitResult.Meh:
                return(100);

            case HitResult.Ok:
                return(200);

            default:
                return(Judgement.ToNumericResult(result));
            }
        }
Esempio n. 2
0
        private static void applyResult(HitResult result, ref ScoringValues scoringValues)
        {
            if (!result.IsScorable())
            {
                return;
            }

            if (result.IsBonus())
            {
                scoringValues.BonusScore += result.IsHit() ? Judgement.ToNumericResult(result) : 0;
            }
            else
            {
                scoringValues.BaseScore += result.IsHit() ? Judgement.ToNumericResult(result) : 0;
            }

            if (result.IsBasic())
            {
                scoringValues.CountBasicHitObjects++;
            }
        }
Esempio n. 3
0
            private void onScoringModeChanged(ValueChangedEvent <ScoringMode> mode)
            {
                difficultyCancellationSource?.Cancel();
                difficultyCancellationSource = null;

                if (score.Beatmap == null)
                {
                    Value = score.TotalScore;
                    return;
                }

                int    beatmapMaxCombo;
                double accuracy = score.Accuracy;

                if (score.IsLegacyScore)
                {
                    if (score.RulesetID == 3)
                    {
                        // In osu!stable, a full-GREAT score has 100% accuracy in mania. Along with a full combo, the score becomes indistinguishable from a full-PERFECT score.
                        // To get around this, recalculate accuracy based on the hit statistics.
                        // Note: This cannot be applied universally to all legacy scores, as some rulesets (e.g. catch) group multiple judgements together.
                        double maxBaseScore = score.Statistics.Select(kvp => kvp.Value).Sum() * Judgement.ToNumericResult(HitResult.Perfect);
                        double baseScore    = score.Statistics.Select(kvp => Judgement.ToNumericResult(kvp.Key) * kvp.Value).Sum();
                        if (maxBaseScore > 0)
                        {
                            accuracy = baseScore / maxBaseScore;
                        }
                    }

                    // This score is guaranteed to be an osu!stable score.
                    // The combo must be determined through either the beatmap's max combo value or the difficulty calculator, as lazer's scoring has changed and the score statistics cannot be used.
                    if (score.Beatmap.MaxCombo == null)
                    {
                        if (score.Beatmap.ID == 0 || difficulties == null)
                        {
                            // We don't have enough information (max combo) to compute the score, so use the provided score.
                            Value = score.TotalScore;
                            return;
                        }

                        // We can compute the max combo locally after the async beatmap difficulty computation.
                        difficultyBindable = difficulties().GetBindableDifficulty(score.Beatmap, score.Ruleset, score.Mods, (difficultyCancellationSource = new CancellationTokenSource()).Token);
                        difficultyBindable.BindValueChanged(d =>
                        {
                            if (d.NewValue is StarDifficulty diff)
                            {
                                updateScore(diff.MaxCombo, accuracy);
                            }
                        }, true);

                        return;
                    }

                    beatmapMaxCombo = score.Beatmap.MaxCombo.Value;
                }
                else
                {
                    // This score is guaranteed to be an osu!lazer score.
                    // The combo must be determined through the score's statistics, as both the beatmap's max combo and the difficulty calculator will provide osu!stable combo values.
                    beatmapMaxCombo = Enum.GetValues(typeof(HitResult)).OfType <HitResult>().Where(r => r.AffectsCombo()).Select(r => score.Statistics.GetOrDefault(r)).Sum();
                }

                updateScore(beatmapMaxCombo, accuracy);
            }
Esempio n. 4
0
        /// <summary>
        /// Retrieves the total score of a <see cref="ScoreInfo"/> in the given <see cref="ScoringMode"/>.
        /// </summary>
        /// <param name="score">The <see cref="ScoreInfo"/> to calculate the total score of.</param>
        /// <param name="mode">The <see cref="ScoringMode"/> to return the total score as.</param>
        /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the process.</param>
        /// <returns>The total score.</returns>
        public async Task <long> GetTotalScoreAsync([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised, CancellationToken cancellationToken = default)
        {
            // TODO: This is required for playlist aggregate scores. They should likely not be getting here in the first place.
            if (string.IsNullOrEmpty(score.BeatmapInfo.Hash))
            {
                return(score.TotalScore);
            }

            int    beatmapMaxCombo;
            double accuracy = score.Accuracy;

            if (score.IsLegacyScore)
            {
                if (score.RulesetID == 3)
                {
                    // In osu!stable, a full-GREAT score has 100% accuracy in mania. Along with a full combo, the score becomes indistinguishable from a full-PERFECT score.
                    // To get around this, recalculate accuracy based on the hit statistics.
                    // Note: This cannot be applied universally to all legacy scores, as some rulesets (e.g. catch) group multiple judgements together.
                    double maxBaseScore = score.Statistics.Select(kvp => kvp.Value).Sum() * Judgement.ToNumericResult(HitResult.Perfect);
                    double baseScore    = score.Statistics.Select(kvp => Judgement.ToNumericResult(kvp.Key) * kvp.Value).Sum();
                    if (maxBaseScore > 0)
                    {
                        accuracy = baseScore / maxBaseScore;
                    }
                }

                // This score is guaranteed to be an osu!stable score.
                // The combo must be determined through either the beatmap's max combo value or the difficulty calculator, as lazer's scoring has changed and the score statistics cannot be used.
                if (score.BeatmapInfo.MaxCombo != null)
                {
                    beatmapMaxCombo = score.BeatmapInfo.MaxCombo.Value;
                }
                else
                {
                    if (difficulties == null)
                    {
                        return(score.TotalScore);
                    }

                    // We can compute the max combo locally after the async beatmap difficulty computation.
                    var difficulty = await difficulties().GetDifficultyAsync(score.BeatmapInfo, score.Ruleset, score.Mods, cancellationToken).ConfigureAwait(false);

                    // Something failed during difficulty calculation. Fall back to provided score.
                    if (difficulty == null)
                    {
                        return(score.TotalScore);
                    }

                    beatmapMaxCombo = difficulty.Value.MaxCombo;
                }
            }
            else
            {
                // This is guaranteed to be a non-legacy score.
                // The combo must be determined through the score's statistics, as both the beatmap's max combo and the difficulty calculator will provide osu!stable combo values.
                beatmapMaxCombo = Enum.GetValues(typeof(HitResult)).OfType <HitResult>().Where(r => r.AffectsCombo()).Select(r => score.Statistics.GetValueOrDefault(r)).Sum();
            }

            if (beatmapMaxCombo == 0)
            {
                return(0);
            }

            var ruleset        = score.Ruleset.CreateInstance();
            var scoreProcessor = ruleset.CreateScoreProcessor();

            scoreProcessor.Mods.Value = score.Mods;

            return((long)Math.Round(scoreProcessor.GetScore(mode, accuracy, (double)score.MaxCombo / beatmapMaxCombo, score.Statistics)));
        }