mirror of
https://github.com/ppy/osu-tools.git
synced 2025-06-09 09:35:15 +09:00
Merge branch 'ppy:master' into better_accuracy_estimator
This commit is contained in:
commit
925b8f5461
14 changed files with 51 additions and 65 deletions
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
|
@ -7,7 +7,7 @@
|
|||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/PerformanceCalculator/bin/Debug/net5.0/PerformanceCalculator.dll",
|
||||
"${workspaceRoot}/PerformanceCalculator/bin/Debug/net8.0/PerformanceCalculator.dll",
|
||||
"place-your-arguments-here (launch.json)"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
|
@ -21,7 +21,7 @@
|
|||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/PerformanceCalculator/bin/Release/net5.0/PerformanceCalculator.dll",
|
||||
"${workspaceRoot}/PerformanceCalculator/bin/Release/net8.0/PerformanceCalculator.dll",
|
||||
"place-your-arguments-here (launch.json)"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using McMaster.Extensions.CommandLineUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring.Legacy;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
|
@ -26,9 +24,6 @@ namespace PerformanceCalculator.Performance
|
|||
{
|
||||
var score = base.CreateScore(apiScore, ruleset, apiBeatmap, workingBeatmap);
|
||||
|
||||
score.Mods = score.Mods.Append(ruleset.CreateMod<ModClassic>()).ToArray();
|
||||
score.IsLegacyScore = true;
|
||||
score.LegacyTotalScore = (int)score.TotalScore;
|
||||
LegacyScoreDecoder.PopulateMaximumStatistics(score, workingBeatmap);
|
||||
StandardisedScoreMigrationTools.UpdateFromLegacy(
|
||||
score,
|
||||
|
|
|
@ -84,23 +84,41 @@ namespace PerformanceCalculator.Performance
|
|||
{ "mods", ((int)mods).ToString(CultureInfo.InvariantCulture) }
|
||||
};
|
||||
|
||||
var beatmap = GetJsonFromApi<APIBeatmap>($"beatmaps/{beatmapId}");
|
||||
|
||||
switch (rulesetId)
|
||||
{
|
||||
case 0:
|
||||
return GetJsonFromApi<AttributesResponse<OsuDifficultyAttributes>>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes;
|
||||
return getMergedAttributes<OsuDifficultyAttributes>(beatmap);
|
||||
|
||||
case 1:
|
||||
return GetJsonFromApi<AttributesResponse<TaikoDifficultyAttributes>>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes;
|
||||
return getMergedAttributes<TaikoDifficultyAttributes>(beatmap);
|
||||
|
||||
case 2:
|
||||
return GetJsonFromApi<AttributesResponse<CatchDifficultyAttributes>>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes;
|
||||
return getMergedAttributes<CatchDifficultyAttributes>(beatmap);
|
||||
|
||||
case 3:
|
||||
return GetJsonFromApi<AttributesResponse<ManiaDifficultyAttributes>>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes;
|
||||
return getMergedAttributes<ManiaDifficultyAttributes>(beatmap);
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(rulesetId));
|
||||
}
|
||||
|
||||
DifficultyAttributes getMergedAttributes<TAttributes>(APIBeatmap apiBeatmap)
|
||||
where TAttributes : DifficultyAttributes, new()
|
||||
{
|
||||
// the osu-web endpoint queries osu-beatmap-difficulty-cache, which in turn does not return the full set of attributes -
|
||||
// it skips ones that are already present on `APIBeatmap`
|
||||
// (https://github.com/ppy/osu-beatmap-difficulty-lookup-cache/blob/db2203368221109803f2031788da31deb94e0f11/BeatmapDifficultyLookupCache/DifficultyCache.cs#L125-L128).
|
||||
// to circumvent this, do some manual grafting on our side to produce a fully populated set of attributes.
|
||||
var databasedAttributes = GetJsonFromApi<AttributesResponse<TAttributes>>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes;
|
||||
var fullAttributes = new TAttributes();
|
||||
fullAttributes.FromDatabaseAttributes(databasedAttributes.ToDatabaseAttributes().ToDictionary(
|
||||
pair => pair.attributeId,
|
||||
pair => Convert.ToDouble(pair.value, CultureInfo.InvariantCulture)
|
||||
), apiBeatmap);
|
||||
return fullAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace PerformanceCalculator.Simulate
|
|||
var maxCombo = GetMaxCombo(beatmap);
|
||||
int maxTinyDroplets = beatmap.HitObjects.OfType<JuiceStream>().Sum(s => s.NestedHitObjects.OfType<TinyDroplet>().Count());
|
||||
int maxDroplets = beatmap.HitObjects.OfType<JuiceStream>().Sum(s => s.NestedHitObjects.OfType<Droplet>().Count()) - maxTinyDroplets;
|
||||
int maxFruits = beatmap.HitObjects.OfType<Fruit>().Count() + 2 * beatmap.HitObjects.OfType<JuiceStream>().Count() + beatmap.HitObjects.OfType<JuiceStream>().Sum(s => s.RepeatCount);
|
||||
int maxFruits = beatmap.HitObjects.Sum(h => h is Fruit ? 1 : (h as JuiceStream)?.NestedHitObjects.Count(n => n is Fruit) ?? 0);
|
||||
|
||||
// Either given or max value minus misses
|
||||
int countDroplets = countGood ?? Math.Max(0, maxDroplets - countMiss);
|
||||
|
|
|
@ -80,11 +80,12 @@ namespace PerformanceCalculator.Simulate
|
|||
int delta = targetTotal - remainingHits;
|
||||
|
||||
// Each great and perfect increases total by 5 (great-meh=5)
|
||||
// There is no difference in accuracy between them, so just halve arbitrarily.
|
||||
greats = Math.Min(delta / 5, remainingHits) / 2;
|
||||
int perfects = greats.Value;
|
||||
// There is no difference in accuracy between them, so just halve arbitrarily (favouring perfects for an odd number).
|
||||
int greatsAndPerfects = Math.Min(delta / 5, remainingHits);
|
||||
greats = greatsAndPerfects / 2;
|
||||
int perfects = greatsAndPerfects - greats.Value;
|
||||
delta -= (greats.Value + perfects) * 5;
|
||||
remainingHits -= (greats.Value + perfects);
|
||||
remainingHits -= greats.Value + perfects;
|
||||
|
||||
// Each good increases total by 3 (good-meh=3).
|
||||
countGood = Math.Min(delta / 3, remainingHits);
|
||||
|
@ -93,6 +94,7 @@ namespace PerformanceCalculator.Simulate
|
|||
|
||||
// Each ok increases total by 1 (ok-meh=1).
|
||||
oks = delta;
|
||||
remainingHits -= oks.Value;
|
||||
|
||||
// Everything else is a meh, as initially assumed.
|
||||
countMeh = remainingHits;
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace PerformanceCalculatorGUI.Components
|
|||
{
|
||||
graphsContainer.Clear();
|
||||
|
||||
var skills = val.NewValue.Where(x => x is StrainSkill).ToArray();
|
||||
var skills = val.NewValue.Where(x => x is StrainSkill or StrainDecaySkill).ToArray();
|
||||
|
||||
// dont bother if there are no strain skills to draw
|
||||
if (skills.Length == 0)
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace PerformanceCalculatorGUI.Components.TextBoxes
|
|||
OnFocused?.Invoke();
|
||||
base.OnFocus(e);
|
||||
|
||||
GetContainingInputManager().TriggerFocusContention(this);
|
||||
GetContainingFocusManager()?.TriggerFocusContention(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System.Globalization;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace PerformanceCalculatorGUI.Components.TextBoxes
|
||||
|
@ -14,7 +13,7 @@ namespace PerformanceCalculatorGUI.Components.TextBoxes
|
|||
{
|
||||
protected override bool AllowIme => false;
|
||||
|
||||
protected override bool CanAddCharacter(char character) => character.IsAsciiDigit() || character == CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator[0];
|
||||
protected override bool CanAddCharacter(char character) => char.IsAsciiDigit(character) || character == CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator[0];
|
||||
|
||||
protected override void OnUserTextAdded(string added)
|
||||
{
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game" Version="2024.130.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Osu" Version="2024.130.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Taiko" Version="2024.130.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Catch" Version="2024.130.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Mania" Version="2024.130.2" />
|
||||
<PackageReference Include="ppy.osu.Game" Version="2024.625.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Osu" Version="2024.625.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Taiko" Version="2024.625.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Catch" Version="2024.625.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Rulesets.Mania" Version="2024.625.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -4,21 +4,15 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Catch.Edit;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
||||
{
|
||||
public partial class CatchObjectInspectorRuleset : DrawableCatchRuleset
|
||||
public partial class CatchObjectInspectorRuleset : DrawableCatchEditorRuleset
|
||||
{
|
||||
private readonly CatchDifficultyHitObject[] difficultyHitObjects;
|
||||
|
||||
|
@ -36,36 +30,12 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
|
||||
protected override Playfield CreatePlayfield() => new CatchObjectInspectorPlayfield(Beatmap.Difficulty);
|
||||
public override bool AllowBackwardsSeeks => true;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
objectDifficultyValuesContainer.CurrentDifficultyHitObject.Value = difficultyHitObjects.LastOrDefault(x => x.StartTime < Clock.CurrentTime);
|
||||
}
|
||||
|
||||
private partial class CatchObjectInspectorPlayfield : CatchEditorPlayfield
|
||||
{
|
||||
protected override GameplayCursorContainer CreateCursor() => null!;
|
||||
|
||||
public CatchObjectInspectorPlayfield(IBeatmapDifficultyInfo difficulty)
|
||||
: base(difficulty)
|
||||
{
|
||||
DisplayJudgements.Value = false;
|
||||
AddInternal(new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Y = 440,
|
||||
Height = 6.0f,
|
||||
CornerRadius = 4.0f,
|
||||
Masking = true,
|
||||
Child = new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.5f),
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics;
|
|||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
||||
|
@ -132,7 +131,7 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
});
|
||||
|
||||
if (hitObject.Angle is not null)
|
||||
flowContainer.Add(new ObjectInspectorDifficultyValue("Angle", MathUtils.RadiansToDegrees(hitObject.Angle.Value)));
|
||||
flowContainer.Add(new ObjectInspectorDifficultyValue("Angle", double.RadiansToDegrees(hitObject.Angle.Value)));
|
||||
|
||||
if (hitObject.BaseObject is Slider)
|
||||
{
|
||||
|
|
|
@ -178,7 +178,6 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
},
|
||||
"taiko" => new TaikoPlayfieldAdjustmentContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new TaikoObjectInspectorRuleset(rulesetInstance, playableBeatmap, modifiedMods, difficultyCalculator.Value as ExtendedTaikoDifficultyCalculator,
|
||||
processorBeatmap.Track.Rate)
|
||||
{
|
||||
|
|
|
@ -10,13 +10,14 @@ using osu.Game.Rulesets;
|
|||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
||||
{
|
||||
public partial class OsuObjectInspectorRuleset : DrawableOsuRuleset
|
||||
public partial class OsuObjectInspectorRuleset : DrawableOsuEditorRuleset
|
||||
{
|
||||
private readonly OsuDifficultyHitObject[] difficultyHitObjects;
|
||||
|
||||
|
@ -39,6 +40,8 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
|
||||
public override bool AllowBackwardsSeeks => true;
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuObjectInspectorPlayfield(difficultyHitObjects);
|
||||
|
||||
private partial class OsuObjectInspectorPlayfield : OsuPlayfield
|
||||
|
@ -55,14 +58,12 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
|
||||
protected override void OnNewDrawableHitObject(DrawableHitObject d)
|
||||
{
|
||||
base.OnNewDrawableHitObject(d);
|
||||
d.ApplyCustomUpdateState += updateState;
|
||||
}
|
||||
|
||||
private void updateState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
if (state == ArmedState.Idle)
|
||||
return;
|
||||
|
||||
if (hitObject is DrawableSliderRepeat repeat)
|
||||
{
|
||||
repeat.Arrow.ApplyTransformsAt(hitObject.StateUpdateTime, true);
|
||||
|
|
|
@ -8,12 +8,13 @@ using osu.Game.Beatmaps;
|
|||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Taiko.Edit;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
||||
{
|
||||
public partial class TaikoObjectInspectorRuleset : DrawableTaikoRuleset
|
||||
public partial class TaikoObjectInspectorRuleset : DrawableTaikoEditorRuleset
|
||||
{
|
||||
private readonly TaikoDifficultyHitObject[] difficultyHitObjects;
|
||||
|
||||
|
@ -31,6 +32,8 @@ namespace PerformanceCalculatorGUI.Screens.ObjectInspection
|
|||
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
|
||||
public override bool AllowBackwardsSeeks => true;
|
||||
|
||||
protected override Playfield CreatePlayfield() => new TaikoObjectInspectorPlayfield();
|
||||
|
||||
protected override void Update()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue