mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 17:32:54 +08:00
Merge pull request #2492 from smoogipoo/ruleset-beatmap-statistics
Add mode-specific beatmap statistics
This commit is contained in:
commit
ac514c5d20
@ -1 +1 @@
|
||||
Subproject commit e793a084177f53920645c4f6f70cfef91e7fd19e
|
||||
Subproject commit 8c4f23269447d9ce21a5dbd3a0fd4f6caae9ab38
|
43
osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs
Normal file
43
osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
{
|
||||
public class CatchBeatmap : Beatmap<CatchHitObject>
|
||||
{
|
||||
public override IEnumerable<BeatmapStatistic> GetStatistics()
|
||||
{
|
||||
int fruits = HitObjects.Count(s => s is Fruit);
|
||||
int juiceStreams = HitObjects.Count(s => s is JuiceStream);
|
||||
int bananaShowers = HitObjects.Count(s => s is BananaShower);
|
||||
|
||||
return new[]
|
||||
{
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Fruit Count",
|
||||
Content = fruits.ToString(),
|
||||
Icon = FontAwesome.fa_circle_o
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Juice Stream Count",
|
||||
Content = juiceStreams.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Banana Shower Count",
|
||||
Content = bananaShowers.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -69,5 +69,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
X = positionData.X / CatchPlayfield.BASE_WIDTH
|
||||
};
|
||||
}
|
||||
|
||||
protected override Beatmap<CatchHitObject> CreateBeatmap() => new CatchBeatmap();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
@ -29,5 +30,27 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
{
|
||||
Stages.Add(defaultStage);
|
||||
}
|
||||
|
||||
public override IEnumerable<BeatmapStatistic> GetStatistics()
|
||||
{
|
||||
int notes = HitObjects.Count(s => s is Note);
|
||||
int holdnotes = HitObjects.Count(s => s is HoldNote);
|
||||
|
||||
return new[]
|
||||
{
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Note Count",
|
||||
Content = notes.ToString(),
|
||||
Icon = FontAwesome.fa_circle_o
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Hold Note Count",
|
||||
Content = holdnotes.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
43
osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs
Normal file
43
osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
public class OsuBeatmap : Beatmap<OsuHitObject>
|
||||
{
|
||||
public override IEnumerable<BeatmapStatistic> GetStatistics()
|
||||
{
|
||||
int circles = HitObjects.Count(c => c is HitCircle);
|
||||
int sliders = HitObjects.Count(s => s is Slider);
|
||||
int spinners = HitObjects.Count(s => s is Spinner);
|
||||
|
||||
return new[]
|
||||
{
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Circle Count",
|
||||
Content = circles.ToString(),
|
||||
Icon = FontAwesome.fa_circle_o
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Slider Count",
|
||||
Content = sliders.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Spinner Count",
|
||||
Content = spinners.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -65,5 +65,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override Beatmap<OsuHitObject> CreateBeatmap() => new OsuBeatmap();
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ using osu.Game.Rulesets.Osu.OsuDifficulty;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Framework.Input.Bindings;
|
||||
@ -17,8 +16,6 @@ using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Osu.Scoring;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
@ -40,36 +37,6 @@ namespace osu.Game.Rulesets.Osu
|
||||
new KeyBinding(InputKey.MouseRight, OsuAction.RightButton),
|
||||
};
|
||||
|
||||
public override IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap)
|
||||
{
|
||||
IEnumerable<HitObject> hitObjects = beatmap.Beatmap.HitObjects;
|
||||
IEnumerable<HitObject> circles = hitObjects.Where(c => !(c is IHasEndTime));
|
||||
IEnumerable<HitObject> sliders = hitObjects.Where(s => s is IHasCurve);
|
||||
IEnumerable<HitObject> spinners = hitObjects.Where(s => s is IHasEndTime && !(s is IHasCurve));
|
||||
|
||||
return new[]
|
||||
{
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Circle Count",
|
||||
Content = circles.Count().ToString(),
|
||||
Icon = FontAwesome.fa_circle_o
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Slider Count",
|
||||
Content = sliders.Count().ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Spinner Count",
|
||||
Content = spinners.Count().ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||
{
|
||||
if (mods.HasFlag(LegacyMods.Nightcore))
|
||||
|
43
osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs
Normal file
43
osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Beatmaps
|
||||
{
|
||||
public class TaikoBeatmap : Beatmap<TaikoHitObject>
|
||||
{
|
||||
public override IEnumerable<BeatmapStatistic> GetStatistics()
|
||||
{
|
||||
int hits = HitObjects.Count(s => s is Hit);
|
||||
int drumrolls = HitObjects.Count(s => s is DrumRoll);
|
||||
int swells = HitObjects.Count(s => s is Swell);
|
||||
|
||||
return new[]
|
||||
{
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Hit Count",
|
||||
Content = hits.ToString(),
|
||||
Icon = FontAwesome.fa_circle_o
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Drumroll Count",
|
||||
Content = drumrolls.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
},
|
||||
new BeatmapStatistic
|
||||
{
|
||||
Name = @"Swell Count",
|
||||
Content = swells.ToString(),
|
||||
Icon = FontAwesome.fa_circle
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -197,5 +197,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override Beatmap<TaikoHitObject> CreateBeatmap() => new TaikoBeatmap();
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,12 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
@ -72,13 +76,23 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
selectBeatmap(testBeatmap);
|
||||
|
||||
testBeatmapLabels(ruleset);
|
||||
|
||||
// TODO: adjust cases once more info is shown for other gamemodes
|
||||
switch (ruleset)
|
||||
{
|
||||
case OsuRuleset osu:
|
||||
testOsuBeatmap(osu);
|
||||
case OsuRuleset _:
|
||||
testInfoLabels(5);
|
||||
break;
|
||||
case TaikoRuleset _:
|
||||
testInfoLabels(5);
|
||||
break;
|
||||
case CatchRuleset _:
|
||||
testInfoLabels(5);
|
||||
break;
|
||||
case ManiaRuleset _:
|
||||
testInfoLabels(4);
|
||||
break;
|
||||
default:
|
||||
testInfoLabels(2);
|
||||
break;
|
||||
@ -88,7 +102,7 @@ namespace osu.Game.Tests.Visual
|
||||
testNullBeatmap();
|
||||
}
|
||||
|
||||
private void testOsuBeatmap(OsuRuleset ruleset)
|
||||
private void testBeatmapLabels(Ruleset ruleset)
|
||||
{
|
||||
AddAssert("check version", () => infoWedge.Info.VersionLabel.Text == $"{ruleset.ShortName}Version");
|
||||
AddAssert("check title", () => infoWedge.Info.TitleLabel.Text == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title");
|
||||
@ -138,7 +152,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
List<HitObject> objects = new List<HitObject>();
|
||||
for (double i = 0; i < 50000; i += 1000)
|
||||
objects.Add(new HitObject { StartTime = i });
|
||||
objects.Add(new TestHitObject { StartTime = i });
|
||||
|
||||
return new Beatmap
|
||||
{
|
||||
@ -153,7 +167,8 @@ namespace osu.Game.Tests.Visual
|
||||
},
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 6,
|
||||
Version = $"{ruleset.ShortName}Version"
|
||||
Version = $"{ruleset.ShortName}Version",
|
||||
BaseDifficulty = new BeatmapDifficulty()
|
||||
},
|
||||
HitObjects = objects
|
||||
};
|
||||
@ -163,5 +178,12 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public new BufferedWedgeInfo Info => base.Info;
|
||||
}
|
||||
|
||||
private class TestHitObject : HitObject, IHasPosition
|
||||
{
|
||||
public float X { get; } = 0;
|
||||
public float Y { get; } = 0;
|
||||
public Vector2 Position { get; } = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
IEnumerable<HitObject> IBeatmap.HitObjects => HitObjects;
|
||||
|
||||
public virtual IEnumerable<BeatmapStatistic> GetStatistics() => Enumerable.Empty<BeatmapStatistic>();
|
||||
|
||||
IBeatmap IBeatmap.Clone() => Clone();
|
||||
|
||||
public Beatmap<T> Clone()
|
||||
|
@ -41,6 +41,12 @@ namespace osu.Game.Beatmaps
|
||||
/// </summary>
|
||||
IEnumerable<HitObject> HitObjects { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns statistics for the <see cref="HitObjects"/> contained in this beatmap.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<BeatmapStatistic> GetStatistics();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a shallow-clone of this beatmap and returns it.
|
||||
/// </summary>
|
||||
|
@ -22,8 +22,6 @@ namespace osu.Game.Rulesets
|
||||
{
|
||||
public readonly RulesetInfo RulesetInfo;
|
||||
|
||||
public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { };
|
||||
|
||||
public IEnumerable<Mod> GetAllMods() => Enum.GetValues(typeof(ModType)).Cast<ModType>()
|
||||
// Confine all mods of each mod type into a single IEnumerable<Mod>
|
||||
.SelectMany(GetModsFor)
|
||||
|
@ -4,9 +4,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
@ -21,6 +23,8 @@ using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
@ -28,6 +32,8 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0);
|
||||
|
||||
private readonly IBindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
protected BufferedWedgeInfo Info;
|
||||
|
||||
public BeatmapInfoWedge()
|
||||
@ -46,6 +52,14 @@ namespace osu.Game.Screens.Select
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load([CanBeNull] OsuGame osuGame)
|
||||
{
|
||||
if (osuGame != null)
|
||||
ruleset.BindTo(osuGame.Ruleset);
|
||||
ruleset.ValueChanged += updateRuleset;
|
||||
}
|
||||
|
||||
protected override bool BlockPassThroughMouse => false;
|
||||
|
||||
protected override void PopIn()
|
||||
@ -62,9 +76,19 @@ namespace osu.Game.Screens.Select
|
||||
this.FadeOut(500, Easing.In);
|
||||
}
|
||||
|
||||
private WorkingBeatmap beatmap;
|
||||
|
||||
public void UpdateBeatmap(WorkingBeatmap beatmap)
|
||||
{
|
||||
LoadComponentAsync(new BufferedWedgeInfo(beatmap)
|
||||
this.beatmap = beatmap;
|
||||
loadBeatmap();
|
||||
}
|
||||
|
||||
private void updateRuleset(RulesetInfo ruleset) => loadBeatmap();
|
||||
|
||||
private void loadBeatmap()
|
||||
{
|
||||
LoadComponentAsync(new BufferedWedgeInfo(beatmap, ruleset.Value)
|
||||
{
|
||||
Shear = -Shear,
|
||||
Depth = Info?.Depth + 1 ?? 0,
|
||||
@ -90,9 +114,13 @@ namespace osu.Game.Screens.Select
|
||||
private UnicodeBindableString titleBinding;
|
||||
private UnicodeBindableString artistBinding;
|
||||
|
||||
public BufferedWedgeInfo(WorkingBeatmap working)
|
||||
private readonly RulesetInfo ruleset;
|
||||
|
||||
public BufferedWedgeInfo(WorkingBeatmap working, RulesetInfo userRuleset)
|
||||
{
|
||||
this.working = working;
|
||||
|
||||
ruleset = userRuleset ?? working.BeatmapInfo.Ruleset;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -211,7 +239,6 @@ namespace osu.Game.Screens.Select
|
||||
private InfoLabel[] getInfoLabels()
|
||||
{
|
||||
var beatmap = working.Beatmap;
|
||||
var info = working.BeatmapInfo;
|
||||
|
||||
List<InfoLabel> labels = new List<InfoLabel>();
|
||||
|
||||
@ -234,8 +261,20 @@ namespace osu.Game.Screens.Select
|
||||
Content = getBPMRange(beatmap),
|
||||
}));
|
||||
|
||||
//get statistics from the current ruleset.
|
||||
labels.AddRange(info.Ruleset.CreateInstance().GetBeatmapStatistics(working).Select(s => new InfoLabel(s)));
|
||||
IBeatmap playableBeatmap;
|
||||
|
||||
try
|
||||
{
|
||||
// Try to get the beatmap with the user's ruleset
|
||||
playableBeatmap = working.GetPlayableBeatmap(ruleset);
|
||||
}
|
||||
catch (BeatmapInvalidForRulesetException)
|
||||
{
|
||||
// Can't be converted to the user's ruleset, so use the beatmap's own ruleset
|
||||
playableBeatmap = working.GetPlayableBeatmap(working.BeatmapInfo.Ruleset);
|
||||
}
|
||||
|
||||
labels.AddRange(playableBeatmap.GetStatistics().Select(s => new InfoLabel(s)));
|
||||
}
|
||||
|
||||
return labels.ToArray();
|
||||
|
Loading…
Reference in New Issue
Block a user