diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs index 00f0d67e24..3394a6498e 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs @@ -41,21 +41,45 @@ namespace osu.Desktop.VisualTests.Tests DrainRate = 1, }, StarDifficulty = 5.3f, + Metric = new BeatmapMetric + { + Ratings = Enumerable.Range(0,10).ToArray(), + Fails = Enumerable.Range(lastRange, 100).Select(i => (i % 12) - 6).ToArray(), + Retries = Enumerable.Range(lastRange - 3, 100).Select(i => (i % 12) - 6).ToArray(), + }, }, }); - AddRepeatStep("new fail values", newRetryAndFailValues, 10); - AddStep("new ratings", () => details.Ratings = Enumerable.Range(1, 10)); - AddStep("remove fails", () => details.Fails = null ); - AddStep("remove ratings", () => details.Ratings = null ); + AddRepeatStep("fail values", newRetryAndFailValues, 10); } private int lastRange = 1; private void newRetryAndFailValues() { - details.Fails = Enumerable.Range(lastRange, 100).Select(i => (int)(Math.Cos(i) * 100)); - details.Retries = Enumerable.Range(lastRange, 100).Select(i => (int)(Math.Sin(i) * 100)); + details.Beatmap = new BeatmapInfo + { + Version = "VisualTest", + Metadata = new BeatmapMetadata + { + Source = "Some guy", + Tags = "beatmap metadata example with a very very long list of tags and not much creativity", + }, + Difficulty = new BeatmapDifficulty + { + CircleSize = 7, + ApproachRate = 3.5f, + OverallDifficulty = 5.7f, + DrainRate = 1, + }, + StarDifficulty = 5.3f, + Metric = new BeatmapMetric + { + Ratings = Enumerable.Range(0, 10).ToArray(), + Fails = Enumerable.Range(lastRange, 100).Select(i => (i % 12) - 6).ToArray(), + Retries = Enumerable.Range(lastRange - 3, 100).Select(i => (i % 12) - 6).ToArray(), + }, + }; lastRange += 100; } } diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs index bc6e077633..252d52a744 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Database/BeatmapInfo.cs @@ -41,6 +41,9 @@ namespace osu.Game.Database [OneToOne(CascadeOperations = CascadeOperation.All)] public BeatmapDifficulty Difficulty { get; set; } + [Ignore] + public BeatmapMetric Metric { get; set; } + public string Path { get; set; } public string Hash { get; set; } diff --git a/osu.Game/Database/BeatmapMetric.cs b/osu.Game/Database/BeatmapMetric.cs new file mode 100644 index 0000000000..2302289047 --- /dev/null +++ b/osu.Game/Database/BeatmapMetric.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Database +{ + public class BeatmapMetric + { + /// + /// Ratings for a beatmap, length should be 10 + /// + public int[] Ratings { get; set; } + + /// + /// Fails for a beatmap, length should be 100 + /// + public int[] Fails { get; set; } + + /// + /// Retries for a beatmap, length should be 100 + /// + public int[] Retries { get; set; } + } +} diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index 555d366f98..c9733b807d 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -20,6 +20,9 @@ namespace osu.Game.Graphics.UserInterface private const EasingTypes easing = EasingTypes.InOutCubic; private float length; + /// + /// Length of the bar, ranges from 0 to 1 + /// public float Length { get @@ -41,12 +44,6 @@ namespace osu.Game.Graphics.UserInterface } set { - if (background == null) - Add(background = new Box - { - RelativeSizeAxes = Axes.Both, - Depth = 1, - }); background.Colour = value; } } @@ -81,10 +78,15 @@ namespace osu.Game.Graphics.UserInterface { Children = new[] { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(0,0,0,0) + }, bar = new Box { RelativeSizeAxes = Axes.Both, - } + }, }; } diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index 832ba74b89..b29726ab1c 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -11,6 +11,11 @@ namespace osu.Game.Graphics.UserInterface { public class BarGraph : FillFlowContainer { + /// + /// Manually sets the max value, if null is instead used + /// + public float? MaxValue { get; set; } + private BarDirection direction = BarDirection.BottomToTop; public new BarDirection Direction { @@ -30,6 +35,9 @@ namespace osu.Game.Graphics.UserInterface } } + /// + /// A list of floats that defines the length of each + /// public IEnumerable Values { set @@ -39,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface for (int i = 0; i < values.Count; i++) if (graphBars.Count > i) { - graphBars[i].Length = values[i] / values.Max(); + graphBars[i].Length = values[i] / (MaxValue ?? values.Max()); graphBars[i].Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / values.Count) : new Vector2(1.0f / values.Count, 1); } else @@ -47,9 +55,10 @@ namespace osu.Game.Graphics.UserInterface { RelativeSizeAxes = Axes.Both, Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / values.Count) : new Vector2(1.0f / values.Count, 1), - Length = values[i] / values.Max(), + Length = values[i] / (MaxValue ?? values.Max()), Direction = Direction, }); + Remove(Children.Where((bar, index) => index >= values.Count)); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 6bbe7a0858..e33f42e5b1 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -47,85 +47,49 @@ namespace osu.Game.Screens.Select { return beatmap; } - set { if (beatmap == value) return; beatmap = value; - description.ContentText = beatmap.Version; - source.ContentText = beatmap.Metadata.Source; - tags.ContentText = beatmap.Metadata.Tags; + description.Text = beatmap.Version; + source.Text = beatmap.Metadata.Source; + tags.Text = beatmap.Metadata.Tags; circleSize.Value = beatmap.Difficulty.CircleSize; drainRate.Value = beatmap.Difficulty.DrainRate; overallDifficulty.Value = beatmap.Difficulty.OverallDifficulty; approachRate.Value = beatmap.Difficulty.ApproachRate; stars.Value = (float)beatmap.StarDifficulty; - } - } - private List ratings; - public IEnumerable Ratings - { - get - { - return ratings; - } - set - { - ratings = value?.ToList() ?? new List(); - if(ratings.Count == 0) - ratingsContainer.FadeOut(250); + + List ratings = beatmap.Metric?.Ratings?.ToList() ?? new List(); + if (ratings.Count == 0) + ratingsContainer.Hide(); else { - ratingsContainer.FadeIn(250); + ratingsContainer.Show(); negativeRatings.Text = ratings.GetRange(0, 5).Sum().ToString(); positiveRatings.Text = ratings.GetRange(5, 5).Sum().ToString(); ratingsBar.Length = (float)ratings.GetRange(0, 5).Sum() / ratings.Sum(); ratingsGraph.Values = ratings.Select(rating => (float)rating); } - } - } - private List retries; - public IEnumerable Retries - { - get - { - return retries; - } - set - { - retries = value?.ToList() ?? new List(); - calcRetryAndFailGraph(); - } - } + List retries = beatmap.Metric?.Retries?.ToList() ?? new List(); + List fails = beatmap.Metric?.Fails?.ToList() ?? new List(); - private List fails; - public IEnumerable Fails - { - get - { - return fails; - } - set - { - fails = value?.ToList() ?? new List(); - calcRetryAndFailGraph(); - } - } - - private void calcRetryAndFailGraph() - { - if ((fails?.Count ?? 0) == 0 || (retries?.Count ?? 0) == 0) - retryAndFailContainer.FadeOut(250); - else - { - retryAndFailContainer.FadeIn(250); - failGraph.Values = fails.Select(fail => (float)fail); - retryGraph.Values = retries?.Select((retry, index) => (float)retry + fails[index]); + if ((fails?.Count ?? 0) == 0 || (retries?.Count ?? 0) == 0) + retryAndFailContainer.Hide(); + else + { + retryAndFailContainer.Show(); + float maxValue = fails.Select((fail, index) => fail + retries[index]).Max(); + failGraph.MaxValue = maxValue; + retryGraph.MaxValue = maxValue; + failGraph.Values = fails.Select(fail => (float)fail); + retryGraph.Values = retries.Select((retry, index) => retry + MathHelper.Clamp(fails[index], 0, maxValue)); + } } } @@ -152,24 +116,9 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding(10) { Top = 25 }, Children = new [] { - description = new MetadataSegment - { - HeaderText = "Description", - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - source = new MetadataSegment - { - HeaderText = "Source", - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - tags = new MetadataSegment - { - HeaderText = "Tags", - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } + description = new MetadataSegment("Description"), + source = new MetadataSegment("Source"), + tags = new MetadataSegment("Tags") }, }, new FillFlowContainer @@ -178,7 +127,7 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Y, Width = 0.6f, Direction = FillDirection.Vertical, - Spacing = new Vector2(0,15), + Spacing = new Vector2(0, 15), Padding = new MarginPadding(10) { Top = 0 }, Children = new Drawable[] { @@ -203,37 +152,11 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding(15) { Top = 25 }, Children = new [] { - circleSize = new DifficultyRow - { - DifficultyName = "Circle Size", - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - MaxValue = 7, - }, - drainRate = new DifficultyRow - { - DifficultyName = "HP Drain", - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }, - overallDifficulty = new DifficultyRow - { - DifficultyName = "Accuracy", - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }, - approachRate = new DifficultyRow - { - DifficultyName = "Approach Rate", - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }, - stars = new DifficultyRow - { - DifficultyName = "Star Difficulty", - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }, + circleSize = new DifficultyRow("Circle Size", 7), + drainRate = new DifficultyRow("HP Drain"), + overallDifficulty = new DifficultyRow("Accuracy"), + approachRate = new DifficultyRow("Approach Rate"), + stars = new DifficultyRow("Star Diffculty"), }, }, }, @@ -320,7 +243,7 @@ namespace osu.Game.Screens.Select new OsuSpriteText { Text = "Points of Failure", - Font = @"Exo2.0-Regular", + Font = @"Exo2.0-Regular", }, new Container { @@ -341,7 +264,7 @@ namespace osu.Game.Screens.Select } }, }, - }, + } }; } @@ -368,8 +291,9 @@ namespace osu.Game.Screens.Select private readonly Bar bar; private readonly OsuSpriteText valueText; - private float difficultyValue; + private readonly float maxValue; + private float difficultyValue; public float Value { get @@ -384,33 +308,6 @@ namespace osu.Game.Screens.Select } } - private float maxValue = 10; - - public float MaxValue - { - get - { - return maxValue; - } - set - { - maxValue = value; - bar.Length = Value / value; - } - } - - public string DifficultyName - { - get - { - return name.Text; - } - set - { - name.Text = value; - } - } - public Color4 AccentColour { get @@ -423,13 +320,17 @@ namespace osu.Game.Screens.Select } } - public DifficultyRow() + public DifficultyRow(string difficultyName, float maxValue = 10) { + this.maxValue = maxValue; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; Children = new Drawable[] { name = new OsuSpriteText { Font = @"Exo2.0-Regular", + Text = difficultyName, }, bar = new Bar { @@ -462,30 +363,30 @@ namespace osu.Game.Screens.Select private readonly OsuSpriteText header; private readonly FillFlowContainer content; - private const int fade_time = 250; - - public string HeaderText + public string Text { set { - header.Text = value; - } - } - - public string ContentText - { - set - { - if (value == "") - FadeOut(fade_time); + if (string.IsNullOrEmpty(value)) + Hide(); else { - FadeIn(fade_time); - content.Children = value.Split(' ').Select(text => new OsuSpriteText - { - Text = text, - Font = "Exo2.0-Regular", - }); + Show(); + if (header.Text == "Tags") + content.Children = value.Split(' ').Select(text => new OsuSpriteText + { + Text = text, + Font = "Exo2.0-Regular", + }); + else + content.Children = new[] + { + new OsuSpriteText + { + Text = value, + Font = "Exo2.0-Regular", + } + }; } } } @@ -502,13 +403,17 @@ namespace osu.Game.Screens.Select } } - public MetadataSegment() + public MetadataSegment(string headerText) { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Margin = new MarginPadding { Top = 10 }; Children = new Drawable[] { header = new OsuSpriteText { Font = @"Exo2.0-Bold", + Text = headerText, }, content = new FillFlowContainer { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1888fda4a6..7f01efbe70 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -79,6 +79,7 @@ +