Exemplo n.º 1
0
 public virtual PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => null;
Exemplo n.º 2
0
 public override PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => new CatchPerformanceCalculator(this, attributes, score);
Exemplo n.º 3
0
        protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes)
        {
            var maniaAttributes = (ManiaDifficultyAttributes)attributes;

            scaledScore  = score.TotalScore;
            countPerfect = score.Statistics.GetValueOrDefault(HitResult.Perfect);
            countGreat   = score.Statistics.GetValueOrDefault(HitResult.Great);
            countGood    = score.Statistics.GetValueOrDefault(HitResult.Good);
            countOk      = score.Statistics.GetValueOrDefault(HitResult.Ok);
            countMeh     = score.Statistics.GetValueOrDefault(HitResult.Meh);
            countMiss    = score.Statistics.GetValueOrDefault(HitResult.Miss);

            if (maniaAttributes.ScoreMultiplier > 0)
            {
                // Scale score up, so it's comparable to other keymods
                scaledScore *= 1.0 / maniaAttributes.ScoreMultiplier;
            }

            // Arbitrary initial value for scaling pp in order to standardize distributions across game modes.
            // The specific number has no intrinsic meaning and can be adjusted as needed.
            double multiplier = 0.8;

            if (score.Mods.Any(m => m is ModNoFail))
            {
                multiplier *= 0.9;
            }
            if (score.Mods.Any(m => m is ModEasy))
            {
                multiplier *= 0.5;
            }

            double difficultyValue = computeDifficultyValue(maniaAttributes);
            double accValue        = computeAccuracyValue(difficultyValue, maniaAttributes);
            double totalValue      =
                Math.Pow(
                    Math.Pow(difficultyValue, 1.1) +
                    Math.Pow(accValue, 1.1), 1.0 / 1.1
                    ) * multiplier;

            return(new ManiaPerformanceAttributes
            {
                Difficulty = difficultyValue,
                Accuracy = accValue,
                ScaledScore = scaledScore,
                Total = totalValue
            });
        }
Exemplo n.º 4
0
 public OsuPerformanceCalculator(Ruleset ruleset, DifficultyAttributes attributes, ScoreInfo score)
     : base(ruleset, attributes, score)
 {
 }
Exemplo n.º 5
0
        protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes)
        {
            var taikoAttributes = (TaikoDifficultyAttributes)attributes;

            countGreat = score.Statistics.GetValueOrDefault(HitResult.Great);
            countOk    = score.Statistics.GetValueOrDefault(HitResult.Ok);
            countMeh   = score.Statistics.GetValueOrDefault(HitResult.Meh);
            countMiss  = score.Statistics.GetValueOrDefault(HitResult.Miss);

            double multiplier = 1.1; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things

            if (score.Mods.Any(m => m is ModNoFail))
            {
                multiplier *= 0.90;
            }

            if (score.Mods.Any(m => m is ModHidden))
            {
                multiplier *= 1.10;
            }

            double difficultyValue = computeDifficultyValue(score, taikoAttributes);
            double accuracyValue   = computeAccuracyValue(score, taikoAttributes);
            double totalValue      =
                Math.Pow(
                    Math.Pow(difficultyValue, 1.1) +
                    Math.Pow(accuracyValue, 1.1), 1.0 / 1.1
                    ) * multiplier;

            return(new TaikoPerformanceAttributes
            {
                Difficulty = difficultyValue,
                Accuracy = accuracyValue,
                Total = totalValue
            });
        }
Exemplo n.º 6
0
        protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes)
        {
            var catchAttributes = (CatchDifficultyAttributes)attributes;

            fruitsHit       = score.Statistics.GetValueOrDefault(HitResult.Great);
            ticksHit        = score.Statistics.GetValueOrDefault(HitResult.LargeTickHit);
            tinyTicksHit    = score.Statistics.GetValueOrDefault(HitResult.SmallTickHit);
            tinyTicksMissed = score.Statistics.GetValueOrDefault(HitResult.SmallTickMiss);
            misses          = score.Statistics.GetValueOrDefault(HitResult.Miss);

            // We are heavily relying on aim in catch the beat
            double value = Math.Pow(5.0 * Math.Max(1.0, catchAttributes.StarRating / 0.0049) - 4.0, 2.0) / 100000.0;

            // Longer maps are worth more. "Longer" means how many hits there are which can contribute to combo
            int numTotalHits = totalComboHits();

            double lengthBonus =
                0.95 + 0.3 * Math.Min(1.0, numTotalHits / 2500.0) +
                (numTotalHits > 2500 ? Math.Log10(numTotalHits / 2500.0) * 0.475 : 0.0);

            value *= lengthBonus;

            value *= Math.Pow(0.97, misses);

            // Combo scaling
            if (catchAttributes.MaxCombo > 0)
            {
                value *= Math.Min(Math.Pow(score.MaxCombo, 0.8) / Math.Pow(catchAttributes.MaxCombo, 0.8), 1.0);
            }

            double approachRate       = catchAttributes.ApproachRate;
            double approachRateFactor = 1.0;

            if (approachRate > 9.0)
            {
                approachRateFactor += 0.1 * (approachRate - 9.0); // 10% for each AR above 9
            }
            if (approachRate > 10.0)
            {
                approachRateFactor += 0.1 * (approachRate - 10.0); // Additional 10% at AR 11, 30% total
            }
            else if (approachRate < 8.0)
            {
                approachRateFactor += 0.025 * (8.0 - approachRate); // 2.5% for each AR below 8
            }
            value *= approachRateFactor;

            if (score.Mods.Any(m => m is ModHidden))
            {
                // Hiddens gives almost nothing on max approach rate, and more the lower it is
                if (approachRate <= 10.0)
                {
                    value *= 1.05 + 0.075 * (10.0 - approachRate); // 7.5% for each AR below 10
                }
                else if (approachRate > 10.0)
                {
                    value *= 1.01 + 0.04 * (11.0 - Math.Min(11.0, approachRate)); // 5% at AR 10, 1% at AR 11
                }
            }

            if (score.Mods.Any(m => m is ModFlashlight))
            {
                value *= 1.35 * lengthBonus;
            }

            value *= Math.Pow(accuracy(), 5.5);

            if (score.Mods.Any(m => m is ModNoFail))
            {
                value *= 0.90;
            }

            return(new CatchPerformanceAttributes
            {
                Total = value
            });
        }
Exemplo n.º 7
0
        protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes)
        {
            var osuAttributes = (OsuDifficultyAttributes)attributes;

            accuracy           = score.Accuracy;
            scoreMaxCombo      = score.MaxCombo;
            countGreat         = score.Statistics.GetValueOrDefault(HitResult.Great);
            countOk            = score.Statistics.GetValueOrDefault(HitResult.Ok);
            countMeh           = score.Statistics.GetValueOrDefault(HitResult.Meh);
            countMiss          = score.Statistics.GetValueOrDefault(HitResult.Miss);
            effectiveMissCount = calculateEffectiveMissCount(osuAttributes);

            double multiplier = 1.12; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things.

            if (score.Mods.Any(m => m is OsuModNoFail))
            {
                multiplier *= Math.Max(0.90, 1.0 - 0.02 * effectiveMissCount);
            }

            if (score.Mods.Any(m => m is OsuModSpunOut) && totalHits > 0)
            {
                multiplier *= 1.0 - Math.Pow((double)osuAttributes.SpinnerCount / totalHits, 0.85);
            }

            if (score.Mods.Any(h => h is OsuModRelax))
            {
                // As we're adding Oks and Mehs to an approximated number of combo breaks the result can be higher than total hits in specific scenarios (which breaks some calculations) so we need to clamp it.
                effectiveMissCount = Math.Min(effectiveMissCount + countOk + countMeh, totalHits);

                multiplier *= 0.6;
            }

            double aimValue        = computeAimValue(score, osuAttributes);
            double speedValue      = computeSpeedValue(score, osuAttributes);
            double accuracyValue   = computeAccuracyValue(score, osuAttributes);
            double flashlightValue = computeFlashlightValue(score, osuAttributes);
            double totalValue      =
                Math.Pow(
                    Math.Pow(aimValue, 1.1) +
                    Math.Pow(speedValue, 1.1) +
                    Math.Pow(accuracyValue, 1.1) +
                    Math.Pow(flashlightValue, 1.1), 1.0 / 1.1
                    ) * multiplier;

            return(new OsuPerformanceAttributes
            {
                Aim = aimValue,
                Speed = speedValue,
                Accuracy = accuracyValue,
                Flashlight = flashlightValue,
                EffectiveMissCount = effectiveMissCount,
                Total = totalValue
            });
        }
 public TimedDifficultyAttributes(double time, DifficultyAttributes attributes)
 {
     Time       = time;
     Attributes = attributes;
 }
Exemplo n.º 9
0
 public StarDifficulty(double starDifficulty, int maxCombo)
 {
     Stars      = starDifficulty;
     MaxCombo   = maxCombo;
     Attributes = null;
 }