Fix BeatmapSetOverlay not displaying Fails/Retries/Ratings (#5016)

Fix BeatmapSetOverlay not displaying Fails/Retries/Ratings

Co-authored-by: Dean Herbert <pe@ppy.sh>
This commit is contained in:
Dean Herbert 2019-06-15 18:46:01 +09:00 committed by GitHub
commit 6fc5aa73b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 388 additions and 174 deletions

View File

@ -41,6 +41,9 @@ public class TestSceneBeatmapSetOverlay : OsuTestScene
typeof(SuccessRate),
};
private RulesetInfo maniaRuleset;
private RulesetInfo taikoRuleset;
public TestSceneBeatmapSetOverlay()
{
Add(overlay = new BeatmapSetOverlay());
@ -49,13 +52,25 @@ public TestSceneBeatmapSetOverlay()
[BackgroundDependencyLoader]
private void load(RulesetStore rulesets)
{
var mania = rulesets.GetRuleset(3);
var taiko = rulesets.GetRuleset(1);
maniaRuleset = rulesets.GetRuleset(3);
taikoRuleset = rulesets.GetRuleset(1);
}
[Test]
public void TestLoading()
{
AddStep(@"show loading", () => overlay.ShowBeatmapSet(null));
}
[Test]
public void TestOnline()
{
AddStep(@"show online", () => overlay.FetchAndShowBeatmapSet(55));
}
[Test]
public void TestLocalBeatmaps()
{
AddStep(@"show first", () =>
{
overlay.ShowBeatmapSet(new BeatmapSetInfo
@ -87,13 +102,14 @@ private void load(RulesetStore rulesets)
Cover = @"https://assets.ppy.sh/beatmaps/415886/covers/cover.jpg?1465651778",
},
},
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
StarDifficulty = 1.36,
Version = @"BASIC",
Ruleset = mania,
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
@ -111,16 +127,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 2.22,
Version = @"NOVICE",
Ruleset = mania,
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
@ -138,16 +153,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 3.49,
Version = @"ADVANCED",
Ruleset = mania,
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
@ -165,16 +179,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 4.24,
Version = @"EXHAUST",
Ruleset = mania,
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
@ -192,16 +205,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 5.26,
Version = @"GRAVITY",
Ruleset = mania,
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
@ -219,9 +231,8 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
},
@ -258,13 +269,14 @@ private void load(RulesetStore rulesets)
Cover = @"https://assets.ppy.sh/beatmaps/625493/covers/cover.jpg?1499167472",
},
},
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
StarDifficulty = 1.40,
Version = @"yzrin's Kantan",
Ruleset = taiko,
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 2,
@ -282,16 +294,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 2.23,
Version = @"Futsuu",
Ruleset = taiko,
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 2,
@ -309,16 +320,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 3.19,
Version = @"Muzukashii",
Ruleset = taiko,
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 2,
@ -336,16 +346,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 3.97,
Version = @"Charlotte's Oni",
Ruleset = taiko,
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 5,
@ -363,16 +372,15 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 5.08,
Version = @"Labyrinth Oni",
Ruleset = taiko,
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 5,
@ -390,16 +398,24 @@ private void load(RulesetStore rulesets)
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
},
});
});
}
[Test]
public void TestHide()
{
AddStep(@"hide", overlay.Hide);
}
[Test]
public void TestShowWithNoReload()
{
AddStep(@"show without reload", overlay.Show);
}
}

View File

@ -0,0 +1,69 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Overlays.BeatmapSet;
using osu.Game.Screens.Select.Details;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneBeatmapSetOverlayDetails : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(Details)
};
private RatingsExposingDetails details;
[SetUp]
public void Setup() => Schedule(() =>
{
Child = details = new RatingsExposingDetails
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
};
});
[Test]
public void TestMetrics()
{
var firstSet = createSet();
var secondSet = createSet();
AddStep("set first set", () => details.BeatmapSet = firstSet);
AddAssert("ratings set", () => details.Ratings.Metrics == firstSet.Metrics);
AddStep("set second set", () => details.BeatmapSet = secondSet);
AddAssert("ratings set", () => details.Ratings.Metrics == secondSet.Metrics);
BeatmapSetInfo createSet() => new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).Select(_ => RNG.Next(10)).ToArray() },
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(),
}
}
}
};
}
private class RatingsExposingDetails : Details
{
public new UserRatings Ratings => base.Ratings;
}
}
}

View File

@ -0,0 +1,82 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Overlays.BeatmapSet;
using osu.Game.Screens.Select.Details;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneBeatmapSetOverlaySuccessRate : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(Details)
};
private GraphExposingSuccessRate successRate;
[SetUp]
public void Setup() => Schedule(() =>
{
Child = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(275, 220),
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Gray,
},
successRate = new GraphExposingSuccessRate
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(275, 220),
Padding = new MarginPadding(20)
}
}
};
});
[Test]
public void TestMetrics()
{
var firstBeatmap = createBeatmap();
var secondBeatmap = createBeatmap();
AddStep("set first set", () => successRate.Beatmap = firstBeatmap);
AddAssert("ratings set", () => successRate.Graph.Metrics == firstBeatmap.Metrics);
AddStep("set second set", () => successRate.Beatmap = secondBeatmap);
AddAssert("ratings set", () => successRate.Graph.Metrics == secondBeatmap.Metrics);
BeatmapInfo createBeatmap() => new BeatmapInfo
{
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(),
}
};
}
private class GraphExposingSuccessRate : SuccessRate
{
public new FailRetryGraph Graph => base.Graph;
}
}
}

View File

@ -32,6 +32,10 @@ private void load(OsuGameBase game)
AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
{
BeatmapSetInfo =
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
BeatmapInfo =
{
Version = "All Metrics",
@ -50,9 +54,8 @@ private void load(OsuGameBase game)
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
}
@ -60,6 +63,10 @@ private void load(OsuGameBase game)
AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
{
BeatmapSetInfo =
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
BeatmapInfo =
{
Version = "All Metrics",
@ -77,15 +84,18 @@ private void load(OsuGameBase game)
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
});
AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
{
BeatmapSetInfo =
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
BeatmapInfo =
{
Version = "Only Ratings",
@ -101,11 +111,7 @@ private void load(OsuGameBase game)
OverallDifficulty = 6,
ApproachRate = 6,
},
StarDifficulty = 4.8f,
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
},
StarDifficulty = 4.8f
}
});
@ -129,8 +135,8 @@ private void load(OsuGameBase game)
StarDifficulty = 2.91f,
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
});

View File

@ -1,28 +1,38 @@
// 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.ComponentModel;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Screens.Select;
namespace osu.Game.Tests.Visual.SongSelect
{
[Description("PlaySongSelect beatmap details")]
[System.ComponentModel.Description("PlaySongSelect beatmap details")]
public class TestSceneBeatmapDetails : OsuTestScene
{
public TestSceneBeatmapDetails()
private BeatmapDetails details;
[SetUp]
public void Setup() => Schedule(() =>
{
BeatmapDetails details;
Add(details = new BeatmapDetails
Child = details = new BeatmapDetails
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(150),
});
};
});
[Test]
public void TestAllMetrics()
{
AddStep("all metrics", () => details.Beatmap = new BeatmapInfo
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "All Metrics",
Metadata = new BeatmapMetadata
{
@ -39,14 +49,21 @@ public TestSceneBeatmapDetails()
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
});
}
[Test]
public void TestAllMetricsExceptSource()
{
AddStep("all except source", () => details.Beatmap = new BeatmapInfo
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "All Metrics",
Metadata = new BeatmapMetadata
{
@ -62,14 +79,21 @@ public TestSceneBeatmapDetails()
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
});
}
[Test]
public void TestOnlyRatings()
{
AddStep("ratings", () => details.Beatmap = new BeatmapInfo
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "Only Ratings",
Metadata = new BeatmapMetadata
{
@ -84,12 +108,12 @@ public TestSceneBeatmapDetails()
ApproachRate = 6,
},
StarDifficulty = 4.8f,
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
},
});
}
[Test]
public void TestOnlyFailsAndRetries()
{
AddStep("fails retries", () => details.Beatmap = new BeatmapInfo
{
Version = "Only Retries and Fails",
@ -108,11 +132,15 @@ public TestSceneBeatmapDetails()
StarDifficulty = 2.91f,
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
});
}
[Test]
public void TestNoMetrics()
{
AddStep("no metrics", () => details.Beatmap = new BeatmapInfo
{
Version = "No Metrics",
@ -129,10 +157,22 @@ public TestSceneBeatmapDetails()
ApproachRate = 6.5f,
},
StarDifficulty = 1.97f,
Metrics = new BeatmapMetrics(),
});
}
[Test]
public void TestNullBeatmap()
{
AddStep("null beatmap", () => details.Beatmap = null);
}
[Test]
public void TestOnlineMetrics()
{
AddStep("online ratings/retries/fails", () => details.Beatmap = new BeatmapInfo
{
OnlineBeatmapID = 162,
});
}
}
}

View File

@ -270,9 +270,8 @@ private void realBeatmap()
},
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0, 11),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
};
}

View File

@ -1,31 +1,26 @@
// 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.Collections.Generic;
using System;
using Newtonsoft.Json;
namespace osu.Game.Beatmaps
{
/// <summary>
/// Beatmap metrics based on acculumated online data from community plays.
/// Beatmap metrics based on accumulated online data from community plays.
/// </summary>
public class BeatmapMetrics
{
/// <summary>
/// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?).
/// </summary>
public IEnumerable<int> Ratings { get; set; }
/// <summary>
/// Points of failure on a relative time scale (usually 0..100).
/// </summary>
[JsonProperty(@"fail")]
public IEnumerable<int> Fails { get; set; }
public int[] Fails { get; set; } = Array.Empty<int>();
/// <summary>
/// Points of retry on a relative time scale (usually 0..100).
/// </summary>
[JsonProperty(@"exit")]
public IEnumerable<int> Retries { get; set; }
public int[] Retries { get; set; } = Array.Empty<int>();
}
}

View File

@ -32,6 +32,9 @@ public int? OnlineBeatmapSetID
[NotMapped]
public BeatmapSetOnlineInfo OnlineInfo { get; set; }
[NotMapped]
public BeatmapSetMetrics Metrics { get; set; }
public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0;
[NotMapped]

View File

@ -0,0 +1,17 @@
// 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;
using Newtonsoft.Json;
namespace osu.Game.Beatmaps
{
public class BeatmapSetMetrics
{
/// <summary>
/// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?).
/// </summary>
[JsonProperty("ratings")]
public int[] Ratings { get; set; } = Array.Empty<int>();
}
}

View File

@ -1,20 +0,0 @@
// 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 osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetBeatmapDetailsRequest : APIRequest<APIBeatmapMetrics>
{
private readonly BeatmapInfo beatmap;
public GetBeatmapDetailsRequest(BeatmapInfo beatmap)
{
this.beatmap = beatmap;
}
protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}";
}
}

View File

@ -57,6 +57,9 @@ public class APIBeatmap : BeatmapMetadata
[JsonProperty(@"version")]
private string version { get; set; }
[JsonProperty(@"failtimes")]
private BeatmapMetrics metrics { get; set; }
public BeatmapInfo ToBeatmap(RulesetStore rulesets)
{
var set = BeatmapSet?.ToBeatmapSet(rulesets);
@ -70,6 +73,7 @@ public BeatmapInfo ToBeatmap(RulesetStore rulesets)
Version = version,
Status = Status,
BeatmapSet = set,
Metrics = metrics,
BaseDifficulty = new BeatmapDifficulty
{
DrainRate = drainRate,

View File

@ -1,29 +0,0 @@
// 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 Newtonsoft.Json;
using osu.Game.Beatmaps;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIBeatmapMetrics : BeatmapMetrics
{
//the online API returns some metrics as a nested object.
[JsonProperty(@"failtimes")]
private BeatmapMetrics failTimes
{
set
{
Fails = value.Fails;
Retries = value.Retries;
}
}
//and other metrics in the beatmap set.
[JsonProperty(@"beatmapset")]
private BeatmapMetrics beatmapSet
{
set => Ratings = value.Ratings;
}
}
}

View File

@ -54,6 +54,9 @@ public int? OnlineBeatmapSetID
[JsonProperty(@"last_updated")]
private DateTimeOffset lastUpdated { get; set; }
[JsonProperty(@"ratings")]
private int[] ratings { get; set; }
[JsonProperty(@"user_id")]
private long creatorId
{
@ -70,6 +73,7 @@ public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets)
OnlineBeatmapSetID = OnlineBeatmapSetID,
Metadata = this,
Status = Status,
Metrics = ratings == null ? null : new BeatmapSetMetrics { Ratings = ratings },
OnlineInfo = new BeatmapSetOnlineInfo
{
Covers = covers,

View File

@ -50,7 +50,7 @@ public BeatmapInfo Beatmap
private void updateDisplay()
{
bpm.Value = BeatmapSet?.OnlineInfo.BPM.ToString(@"0.##") ?? "-";
bpm.Value = BeatmapSet?.OnlineInfo?.BPM.ToString(@"0.##") ?? "-";
if (beatmap == null)
{

View File

@ -16,10 +16,11 @@ namespace osu.Game.Overlays.BeatmapSet
{
public class Details : FillFlowContainer
{
protected readonly UserRatings Ratings;
private readonly PreviewButton preview;
private readonly BasicStats basic;
private readonly AdvancedStats advanced;
private readonly UserRatings ratings;
private BeatmapSetInfo beatmapSet;
@ -33,6 +34,7 @@ public BeatmapSetInfo BeatmapSet
beatmapSet = value;
basic.BeatmapSet = preview.BeatmapSet = BeatmapSet;
updateDisplay();
}
}
@ -46,13 +48,12 @@ public BeatmapInfo Beatmap
if (value == beatmap) return;
basic.Beatmap = advanced.Beatmap = beatmap = value;
updateDisplay();
}
}
private void updateDisplay()
{
ratings.Metrics = Beatmap?.Metrics;
Ratings.Metrics = BeatmapSet?.Metrics;
}
public Details()
@ -87,7 +88,7 @@ public Details()
},
new DetailBox
{
Child = ratings = new UserRatings
Child = Ratings = new UserRatings
{
RelativeSizeAxes = Axes.X,
Height = 95,

View File

@ -14,11 +14,12 @@ namespace osu.Game.Overlays.BeatmapSet
{
public class SuccessRate : Container
{
protected readonly FailRetryGraph Graph;
private readonly FillFlowContainer header;
private readonly OsuSpriteText successRateLabel, successPercent, graphLabel;
private readonly Bar successRate;
private readonly Container percentContainer;
private readonly FailRetryGraph graph;
private BeatmapInfo beatmap;
@ -37,15 +38,15 @@ public BeatmapInfo Beatmap
private void updateDisplay()
{
int passCount = beatmap?.OnlineInfo.PassCount ?? 0;
int playCount = beatmap?.OnlineInfo.PlayCount ?? 0;
int passCount = beatmap?.OnlineInfo?.PassCount ?? 0;
int playCount = beatmap?.OnlineInfo?.PlayCount ?? 0;
var rate = playCount != 0 ? (float)passCount / playCount : 0;
successPercent.Text = rate.ToString("P0");
successRate.Length = rate;
percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic);
graph.Metrics = beatmap?.Metrics;
Graph.Metrics = beatmap?.Metrics;
}
public SuccessRate()
@ -94,7 +95,7 @@ public SuccessRate()
},
},
},
graph = new FailRetryGraph
Graph = new FailRetryGraph
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
@ -117,7 +118,7 @@ protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
graph.Padding = new MarginPadding { Top = header.DrawHeight };
Graph.Padding = new MarginPadding { Top = header.DrawHeight };
}
}
}

View File

@ -10,7 +10,6 @@
using osu.Game.Graphics.UserInterface;
using System.Linq;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Framework.Threading;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Extensions.Color4Extensions;
@ -18,6 +17,8 @@
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests;
using osu.Game.Rulesets;
namespace osu.Game.Screens.Select
{
@ -40,6 +41,9 @@ public class BeatmapDetails : Container
private ScheduledDelegate pendingBeatmapSwitch;
[Resolved]
private RulesetStore rulesets { get; set; }
private BeatmapInfo beatmap;
public BeatmapInfo Beatmap
@ -181,57 +185,79 @@ private void updateStatistics()
tags.Text = Beatmap?.Metadata?.Tags;
// metrics may have been previously fetched
if (Beatmap?.Metrics != null)
if (Beatmap?.BeatmapSet?.Metrics != null && Beatmap?.Metrics != null)
{
updateMetrics(Beatmap.Metrics);
updateMetrics();
return;
}
// metrics may not be fetched but can be
if (Beatmap?.OnlineBeatmapID != null)
// for now, let's early abort if an OnlineBeatmapID is not present (should have been populated at import time).
if (Beatmap?.OnlineBeatmapID == null)
{
var requestedBeatmap = Beatmap;
var lookup = new GetBeatmapDetailsRequest(requestedBeatmap);
lookup.Success += res =>
updateMetrics();
return;
}
var requestedBeatmap = Beatmap;
var lookup = new GetBeatmapRequest(requestedBeatmap);
lookup.Success += res =>
{
Schedule(() =>
{
if (beatmap != requestedBeatmap)
//the beatmap has been changed since we started the lookup.
return;
requestedBeatmap.Metrics = res;
Schedule(() => updateMetrics(res));
};
lookup.Failure += e => Schedule(() => updateMetrics());
api.Queue(lookup);
loading.Show();
return;
}
var b = res.ToBeatmap(rulesets);
updateMetrics();
if (requestedBeatmap.BeatmapSet == null)
requestedBeatmap.BeatmapSet = b.BeatmapSet;
else
requestedBeatmap.BeatmapSet.Metrics = b.BeatmapSet.Metrics;
requestedBeatmap.Metrics = b.Metrics;
updateMetrics();
});
};
lookup.Failure += e =>
{
Schedule(() =>
{
if (beatmap != requestedBeatmap)
//the beatmap has been changed since we started the lookup.
return;
updateMetrics();
});
};
api.Queue(lookup);
loading.Show();
}
private void updateMetrics(BeatmapMetrics metrics = null)
private void updateMetrics()
{
var hasRatings = metrics?.Ratings?.Any() ?? false;
var hasRetriesFails = (metrics?.Retries?.Any() ?? false) && (metrics.Fails?.Any() ?? false);
var hasRatings = beatmap?.BeatmapSet?.Metrics?.Ratings?.Any() ?? false;
var hasRetriesFails = (beatmap?.Metrics?.Retries?.Any() ?? false) && (beatmap?.Metrics.Fails?.Any() ?? false);
if (hasRatings)
{
ratings.Metrics = metrics;
ratings.Metrics = beatmap.BeatmapSet.Metrics;
ratingsContainer.FadeIn(transition_duration);
}
else
{
ratings.Metrics = new BeatmapMetrics
{
Ratings = new int[10],
};
ratings.Metrics = new BeatmapSetMetrics { Ratings = new int[10] };
ratingsContainer.FadeTo(0.25f, transition_duration);
}
if (hasRetriesFails)
{
failRetryGraph.Metrics = metrics;
failRetryGraph.Metrics = beatmap.Metrics;
failRetryContainer.FadeIn(transition_duration);
}
else

View File

@ -20,9 +20,9 @@ public class UserRatings : Container
private readonly Container graphContainer;
private readonly BarGraph graph;
private BeatmapMetrics metrics;
private BeatmapSetMetrics metrics;
public BeatmapMetrics Metrics
public BeatmapSetMetrics Metrics
{
get => metrics;
set