mirror of
https://github.com/ppy/osu.git
synced 2025-02-07 07:43:16 +08:00
fix CI again
This commit is contained in:
parent
3b86aff28d
commit
afce62be73
@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
||||
OsuDifficultyHitObject prevObj0 = currObj;
|
||||
|
||||
var readingObjects = currObj.ReadingObjects;
|
||||
|
||||
for (int i = 0; i < readingObjects.Count; i++)
|
||||
{
|
||||
var loopObj = readingObjects[i].HitObject;
|
||||
@ -40,10 +41,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
||||
|
||||
double loopDifficulty = currObj.OpacityAt(loopObj.BaseObject.StartTime, false);
|
||||
|
||||
// Small distances means objects may be cheesed, so it doesn't matter whether they are arranged confusingly.
|
||||
// Small distances means objects may be cheesed, so it doesn't matter whether they are arranged confusingly
|
||||
if (applyDistanceNerf) loopDifficulty *= (DifficultyCalculationUtils.Logistic(-(loopObj.LazyJumpDistance - 80) / 10) + 0.2) / 1.2;
|
||||
|
||||
// Additional buff for long sliderbodies. OVERBUFFED ON PURPOSE
|
||||
// Additional buff for long sliderbodies
|
||||
if (applySliderbodyDensity && loopObj.BaseObject is Slider slider)
|
||||
{
|
||||
// In radiuses, with minimal of 1
|
||||
@ -144,7 +145,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
||||
var easierObject = sortedDifficulties[j];
|
||||
|
||||
// Get the overlap value
|
||||
double overlapValue = 0;
|
||||
double overlapValue;
|
||||
|
||||
// OverlapValues dict only contains prev objects, so be sure to use right object
|
||||
if (harderObject.HitObject.Index > easierObject.HitObject.Index)
|
||||
@ -171,6 +172,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
||||
|
||||
return overlap_multiplier * Math.Max(0, screenOverlapDifficulty);
|
||||
}
|
||||
|
||||
public static double EvaluateDifficultyOf(DifficultyHitObject current)
|
||||
{
|
||||
if (current.BaseObject is Spinner || current.Index == 0)
|
||||
@ -191,43 +193,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
||||
return Math.Max(0, Math.Pow(difficulty, 1.37) - 1);
|
||||
}
|
||||
|
||||
// Returns value from 0 to 1, where 0 is very predictable and 1 is very unpredictable
|
||||
public static double EvaluateInpredictabilityOf(DifficultyHitObject current)
|
||||
{
|
||||
if (current.BaseObject is Spinner || current.Index == 0 || current.Previous(0).BaseObject is Spinner)
|
||||
return 0;
|
||||
|
||||
var osuCurrObj = (OsuDifficultyHitObject)current;
|
||||
var osuLastObj = (OsuDifficultyHitObject)current.Previous(0);
|
||||
|
||||
double currVelocity = osuCurrObj.LazyJumpDistance / osuCurrObj.StrainTime;
|
||||
double prevVelocity = osuLastObj.LazyJumpDistance / osuLastObj.StrainTime;
|
||||
|
||||
double velocityChangeFactor = 0;
|
||||
|
||||
// https://www.desmos.com/calculator/kqxmqc8pkg
|
||||
if (currVelocity > 0 || prevVelocity > 0)
|
||||
{
|
||||
double velocityChange = Math.Max(0,
|
||||
Math.Min(
|
||||
Math.Abs(prevVelocity - currVelocity) - 0.5 * Math.Min(currVelocity, prevVelocity),
|
||||
Math.Max(((OsuHitObject)osuCurrObj.BaseObject).Radius / Math.Max(osuCurrObj.StrainTime, osuLastObj.StrainTime), Math.Min(currVelocity, prevVelocity))
|
||||
)); // Stealed from xexxar
|
||||
velocityChangeFactor = velocityChange / Math.Max(currVelocity, prevVelocity); // maxiumum is 0.4
|
||||
velocityChangeFactor /= 0.4;
|
||||
}
|
||||
|
||||
// Rhythm difference punishment for velocity and angle bonuses
|
||||
double rhythmSimilarity = DifficultyCalculationUtils.GetRatio(osuCurrObj.StrainTime, osuLastObj.StrainTime);
|
||||
|
||||
// Make differentiation going from 1/4 to 1/2 and bigger difference
|
||||
// To 1/3 to 1/2 and smaller difference
|
||||
rhythmSimilarity = Math.Clamp(rhythmSimilarity, 0.5, 0.75);
|
||||
rhythmSimilarity = 4 * (rhythmSimilarity - 0.5);
|
||||
|
||||
return velocityChangeFactor * rhythmSimilarity;
|
||||
}
|
||||
|
||||
// This factor nerfs AR below 0 as extra safety measure
|
||||
private static double getTimeNerfFactor(double deltaTime) => Math.Clamp(2 - deltaTime / (reading_window_size / 2), 0, 1);
|
||||
|
||||
@ -235,14 +200,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
||||
private static double boundBinarySearch(List<OsuDifficultyHitObject.ReadingObject> arr, double target)
|
||||
{
|
||||
int low = 0;
|
||||
int mid;
|
||||
int high = arr.Count;
|
||||
|
||||
int result = -1;
|
||||
|
||||
while (low < high)
|
||||
{
|
||||
mid = low + (high - low) / 2;
|
||||
int mid = low + (high - low) / 2;
|
||||
|
||||
if (arr[mid].HitObject.StartTime >= target)
|
||||
{
|
||||
@ -253,6 +217,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
||||
}
|
||||
|
||||
if (result == -1) return 0;
|
||||
|
||||
return arr[result].Overlapness;
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
/// The difficulty corresponding to the reading skill. Low AR branch.
|
||||
/// </summary>
|
||||
[JsonProperty("reading_low_ar_difficulty")]
|
||||
public double ReadingDifficultyLowAR { get; set; }
|
||||
public double ReadingDifficultyLowAr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The difficulty corresponding to the flashlight skill.
|
||||
|
@ -43,13 +43,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
double speedNotes = skills.OfType<Speed>().First().RelevantNoteCount();
|
||||
|
||||
double flashlightRating = Math.Sqrt(skills.OfType<Flashlight>().First().DifficultyValue()) * difficulty_multiplier;
|
||||
double readingLowARRating = Math.Sqrt(skills.OfType<ReadingLowAR>().First().DifficultyValue()) * difficulty_multiplier;
|
||||
double readingLowARRating = Math.Sqrt(skills.OfType<ReadingLowAr>().First().DifficultyValue()) * difficulty_multiplier;
|
||||
|
||||
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
|
||||
|
||||
double aimDifficultyStrainCount = skills.OfType<Aim>().First().CountTopWeightedStrains();
|
||||
double speedDifficultyStrainCount = skills.OfType<Speed>().First().CountTopWeightedStrains();
|
||||
double lowArDifficultyStrainCount = skills.OfType<ReadingLowAR>().First().CountTopWeightedStrains();
|
||||
double lowArDifficultyStrainCount = skills.OfType<ReadingLowAr>().First().CountTopWeightedStrains();
|
||||
|
||||
if (mods.Any(m => m is OsuModTouchDevice))
|
||||
{
|
||||
@ -70,15 +70,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
double speedPerformance = OsuStrainSkill.DifficultyToPerformance(speedRating);
|
||||
|
||||
// Cognition
|
||||
double readingLowARPerformance = ReadingLowAR.DifficultyToPerformance(readingLowARRating);
|
||||
double readingARPerformance = readingLowARPerformance;
|
||||
double readingLowArPerformance = ReadingLowAr.DifficultyToPerformance(readingLowARRating);
|
||||
double readingArPerformance = readingLowArPerformance;
|
||||
|
||||
double potentialFlashlightPerformance = Flashlight.DifficultyToPerformance(flashlightRating);
|
||||
double flashlightPerformance = mods.Any(h => h is OsuModFlashlight) ? potentialFlashlightPerformance : 0;
|
||||
|
||||
double flashlightARPerformance = Math.Pow(Math.Pow(flashlightPerformance, FL_SUM_POWER) + Math.Pow(readingARPerformance, FL_SUM_POWER), 1.0 / FL_SUM_POWER);
|
||||
double flashlightArPerformance = Math.Pow(Math.Pow(flashlightPerformance, FL_SUM_POWER) + Math.Pow(readingArPerformance, FL_SUM_POWER), 1.0 / FL_SUM_POWER);
|
||||
|
||||
double cognitionPerformance = flashlightARPerformance;
|
||||
double cognitionPerformance = flashlightArPerformance;
|
||||
double mechanicalPerformance = Math.Pow(Math.Pow(aimPerformance, SUM_POWER) + Math.Pow(speedPerformance, SUM_POWER), 1.0 / SUM_POWER);
|
||||
|
||||
// Limit cognition by full memorisation difficulty, what is assumed to be mechanicalPerformance + flashlightPerformance
|
||||
@ -109,7 +109,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
AimDifficulty = aimRating,
|
||||
SpeedDifficulty = speedRating,
|
||||
SpeedNoteCount = speedNotes,
|
||||
ReadingDifficultyLowAR = readingLowARRating,
|
||||
ReadingDifficultyLowAr = readingLowARRating,
|
||||
FlashlightDifficulty = flashlightRating,
|
||||
SliderFactor = sliderFactor,
|
||||
AimDifficultStrainCount = aimDifficultyStrainCount,
|
||||
@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
new Aim(mods, false),
|
||||
new Speed(mods),
|
||||
new Flashlight(mods),
|
||||
new ReadingLowAR(mods),
|
||||
new ReadingLowAr(mods),
|
||||
};
|
||||
|
||||
return skills.ToArray();
|
||||
|
@ -111,34 +111,31 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
effectiveMissCount = Math.Min(effectiveMissCount + countOk * okMultiplier + countMeh * mehMultiplier, totalHits);
|
||||
}
|
||||
|
||||
double power = OsuDifficultyCalculator.SUM_POWER;
|
||||
const double power = OsuDifficultyCalculator.SUM_POWER;
|
||||
|
||||
double aimValue = computeAimValue(score, osuAttributes);
|
||||
double speedValue = computeSpeedValue(score, osuAttributes);
|
||||
double mechanicalValue = Math.Pow(Math.Pow(aimValue, power) + Math.Pow(speedValue, power), 1.0 / power);
|
||||
|
||||
// Cognition
|
||||
|
||||
double lowARValue = computeReadingLowARValue(score, osuAttributes);
|
||||
|
||||
double readingARValue = lowARValue;
|
||||
double lowArValue = computeReadingLowArValue(score, osuAttributes);
|
||||
|
||||
double flashlightValue = computeFlashlightValue(score, osuAttributes);
|
||||
|
||||
// Reduce AR reading bonus if FL is present
|
||||
double flPower = OsuDifficultyCalculator.FL_SUM_POWER;
|
||||
double flashlightARValue = score.Mods.Any(h => h is OsuModFlashlight) ?
|
||||
Math.Pow(Math.Pow(flashlightValue, flPower) + Math.Pow(readingARValue, flPower), 1.0 / flPower) : readingARValue;
|
||||
const double fl_power = OsuDifficultyCalculator.FL_SUM_POWER;
|
||||
|
||||
double cognitionValue = flashlightARValue;
|
||||
double flashlightArValue = score.Mods.Any(h => h is OsuModFlashlight)
|
||||
? Math.Pow(Math.Pow(flashlightValue, fl_power) + Math.Pow(lowArValue, fl_power), 1.0 / fl_power)
|
||||
: lowArValue;
|
||||
|
||||
double cognitionValue = flashlightArValue;
|
||||
cognitionValue = AdjustCognitionPerformance(cognitionValue, mechanicalValue, flashlightValue);
|
||||
|
||||
double accuracyValue = computeAccuracyValue(score, osuAttributes);
|
||||
|
||||
// Add cognition value without LP-sum cuz otherwise it makes balancing harder
|
||||
double totalValue =
|
||||
(Math.Pow(Math.Pow(mechanicalValue, power) + Math.Pow(accuracyValue, power), 1.0 / power)
|
||||
+ cognitionValue) * multiplier;
|
||||
double totalValue = (Math.Pow(Math.Pow(mechanicalValue, power) + Math.Pow(accuracyValue, power), 1.0 / power) + cognitionValue) * multiplier;
|
||||
|
||||
return new OsuPerformanceAttributes
|
||||
{
|
||||
@ -297,10 +294,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
double visualBonus = 0.1 * DifficultyCalculationUtils.Logistic(attributes.ApproachRate - 8.0);
|
||||
|
||||
// Buff if OD is way lower than AR
|
||||
double ARODDelta = Math.Max(0, attributes.OverallDifficulty - attributes.ApproachRate);
|
||||
double ArOdDelta = Math.Max(0, attributes.OverallDifficulty - attributes.ApproachRate);
|
||||
|
||||
// This one is goes from 0.0 on delta=0 to 1.0 somewhere around delta=3.4
|
||||
double deltaBonus = (1 - Math.Pow(0.95, Math.Pow(ARODDelta, 4)));
|
||||
double deltaBonus = (1 - Math.Pow(0.95, Math.Pow(ArOdDelta, 4)));
|
||||
|
||||
// Nerf delta bonus on OD lower than 10 and 9
|
||||
if (attributes.OverallDifficulty < 10)
|
||||
@ -335,9 +332,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
return flashlightValue;
|
||||
}
|
||||
|
||||
private double computeReadingLowARValue(ScoreInfo score, OsuDifficultyAttributes attributes)
|
||||
private double computeReadingLowArValue(ScoreInfo score, OsuDifficultyAttributes attributes)
|
||||
{
|
||||
double readingValue = ReadingLowAR.DifficultyToPerformance(attributes.ReadingDifficultyLowAR);
|
||||
double readingValue = ReadingLowAr.DifficultyToPerformance(attributes.ReadingDifficultyLowAr);
|
||||
|
||||
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
||||
if (effectiveMissCount > 0)
|
||||
|
@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
|
||||
// Overlapness between current and prev to make streams have 0 buff
|
||||
double instantOverlapness = 0;
|
||||
prevObject.OverlapValues?.TryGetValue(loopObj.Index, out instantOverlapness);
|
||||
prevObject.OverlapValues.TryGetValue(loopObj.Index, out instantOverlapness);
|
||||
|
||||
// Nerf overlaps on wide angles
|
||||
double angleFactor = 1;
|
||||
@ -230,6 +230,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
if (cumulativeTimeWithoutCurrent >= cumulativeTimeWithCurrent)
|
||||
break;
|
||||
}
|
||||
|
||||
cumulativeTimeWithCurrent += historicTimes[i];
|
||||
}
|
||||
|
||||
@ -284,9 +285,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
private static double getAngleSimilarity(double angle1, double angle2)
|
||||
{
|
||||
double difference = Math.Abs(angle1 - angle2);
|
||||
double threeshold = Math.PI / 12;
|
||||
const double threeshold = Math.PI / 12;
|
||||
|
||||
if (difference > threeshold) return 0;
|
||||
|
||||
return 1 - difference / threeshold;
|
||||
}
|
||||
|
||||
@ -297,18 +299,18 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
double distance = Vector2.Distance(odho1.StackedPosition, odho2.StackedPosition); // Distance func is kinda slow for some reason
|
||||
double radius = odho1.BaseObject.Radius;
|
||||
|
||||
double distance_sqr = distance * distance;
|
||||
double radius_sqr = radius * radius;
|
||||
double distanceSqr = distance * distance;
|
||||
double radiusSqr = radius * radius;
|
||||
|
||||
if (distance > radius * 2)
|
||||
return 0;
|
||||
|
||||
double s1 = Math.Acos(distance / (2 * radius)) * radius_sqr; // Area of sector
|
||||
double s2 = distance * Math.Sqrt(radius_sqr - distance_sqr / 4) / 2; // Area of triangle
|
||||
double s1 = Math.Acos(distance / (2 * radius)) * radiusSqr; // Area of sector
|
||||
double s2 = distance * Math.Sqrt(radiusSqr - distanceSqr / 4) / 2; // Area of triangle
|
||||
|
||||
double overlappingAreaNormalized = (s1 - s2) * 2 / (Math.PI * radius_sqr);
|
||||
double overlappingAreaNormalized = (s1 - s2) * 2 / (Math.PI * radiusSqr);
|
||||
|
||||
// don't ask me how i get this value, looks oddly similar to PI - 3
|
||||
// Don't ask me how I got this value, looks oddly similar to PI - 3
|
||||
const double stack_distance_ratio = 0.1414213562373;
|
||||
|
||||
double perfectStackBuff = (stack_distance_ratio - distance / radius) / stack_distance_ratio; // scale from 0 on normal stack to 1 on perfect stack
|
||||
@ -397,21 +399,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
OsuDifficultyHitObject? prevObj5 = (OsuDifficultyHitObject?)Previous(5);
|
||||
|
||||
// 3-3 repeat
|
||||
double similarity3_1 = getGeneralSimilarity(this, prevObj2);
|
||||
double similarity3_2 = getGeneralSimilarity(prevObj0, prevObj3);
|
||||
double similarity3_3 = getGeneralSimilarity(prevObj1, prevObj4);
|
||||
double similarityBy3 = getGeneralSimilarity(this, prevObj2) * getGeneralSimilarity(prevObj0, prevObj3) * getGeneralSimilarity(prevObj1, prevObj4);
|
||||
|
||||
double similarity3_total = similarity3_1 * similarity3_2 * similarity3_3;
|
||||
|
||||
// 4-4 repeat
|
||||
double similarity4_1 = getGeneralSimilarity(this, prevObj3);
|
||||
double similarity4_2 = getGeneralSimilarity(prevObj0, prevObj4);
|
||||
double similarity4_3 = getGeneralSimilarity(prevObj1, prevObj5);
|
||||
|
||||
double similarity4_total = similarity4_1 * similarity4_2 * similarity4_3;
|
||||
// 4-4 repeat, only first 3 are checked, this is enough
|
||||
double similarityBy4 = getGeneralSimilarity(this, prevObj3) * getGeneralSimilarity(prevObj0, prevObj4) * getGeneralSimilarity(prevObj1, prevObj5);
|
||||
|
||||
// Bandaid to fix Rubik's Cube +EZ
|
||||
double wideness = 0;
|
||||
|
||||
if (Angle!.Value > Math.PI * 0.5)
|
||||
{
|
||||
// Goes from 0 to 1 as angle increasing from 90 degrees to 180
|
||||
@ -429,7 +424,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
double predictability = Math.Cos(Math.Min(Math.PI / 2, 6 * adjustedAngleDifference)) * rhythmFactor;
|
||||
|
||||
// Punish for big pattern similarity
|
||||
return 1 - (1 - predictability) * (1 - Math.Max(similarity3_total, similarity4_total));
|
||||
return 1 - (1 - predictability) * (1 - Math.Max(similarityBy3, similarityBy4));
|
||||
}
|
||||
|
||||
private double getGeneralSimilarity(OsuDifficultyHitObject? o1, OsuDifficultyHitObject? o2)
|
||||
@ -440,7 +435,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
if (o1.AngleSigned == null || o2.AngleSigned == null)
|
||||
return o1.AngleSigned == o2.AngleSigned ? 1 : 0;
|
||||
|
||||
|
||||
double timeSimilarity = 1 - getTimeDifference(o1.StrainTime, o2.StrainTime);
|
||||
|
||||
double angleDelta = Math.Abs((double)o1.AngleSigned - (double)o2.AngleSigned);
|
||||
|
@ -12,12 +12,12 @@ using osu.Game.Rulesets.Osu.Difficulty.Evaluators;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
{
|
||||
public class ReadingLowAR : StrainSkill
|
||||
public class ReadingLowAr : StrainSkill
|
||||
{
|
||||
private double skillMultiplier => 1.22;
|
||||
private double aimComponentMultiplier => 0.4;
|
||||
|
||||
public ReadingLowAR(Mod[] mods)
|
||||
public ReadingLowAr(Mod[] mods)
|
||||
: base(mods)
|
||||
{
|
||||
}
|
||||
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
private double strainDecayBase => 0.15;
|
||||
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000);
|
||||
|
||||
private double currentDensityAimStrain = 0;
|
||||
private double currentDensityAimStrain;
|
||||
|
||||
protected override double StrainValueAt(DifficultyHitObject current)
|
||||
{
|
||||
@ -43,6 +43,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
|
||||
private double reducedNoteCount => 5;
|
||||
private double reducedNoteBaseline => 0.7;
|
||||
|
||||
public override double DifficultyValue()
|
||||
{
|
||||
// Sections with 0 difficulty are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
|
||||
@ -70,6 +71,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
public static double DifficultyToPerformance(double difficulty) => Math.Max(
|
||||
Math.Max(Math.Pow(difficulty, 1.5) * 20, Math.Pow(difficulty, 2) * 17.0),
|
||||
Math.Max(Math.Pow(difficulty, 3) * 10.5, Math.Pow(difficulty, 4) * 6.00));
|
||||
|
Loading…
Reference in New Issue
Block a user