mirror of
https://github.com/ppy/osu.git
synced 2025-02-13 18:32:55 +08:00
Merge branch 'beatmap-refactor/get-and-present' into beatmap-refactor/beatmap-overlays
This commit is contained in:
commit
8ad33d43d0
@ -8,6 +8,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.Solo;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@ -88,33 +89,27 @@ namespace osu.Game.Tests.Online
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDeserialiseScoreInfoWithEmptyMods()
|
public void TestDeserialiseSubmittableScoreWithEmptyMods()
|
||||||
{
|
{
|
||||||
var score = new ScoreInfo { Ruleset = new OsuRuleset().RulesetInfo };
|
var score = new SubmittableScore(new ScoreInfo { Ruleset = new OsuRuleset().RulesetInfo });
|
||||||
|
|
||||||
var deserialised = JsonConvert.DeserializeObject<ScoreInfo>(JsonConvert.SerializeObject(score));
|
var deserialised = JsonConvert.DeserializeObject<SubmittableScore>(JsonConvert.SerializeObject(score));
|
||||||
|
|
||||||
if (deserialised != null)
|
|
||||||
deserialised.Ruleset = new OsuRuleset().RulesetInfo;
|
|
||||||
|
|
||||||
Assert.That(deserialised?.Mods.Length, Is.Zero);
|
Assert.That(deserialised?.Mods.Length, Is.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDeserialiseScoreInfoWithCustomModSetting()
|
public void TestDeserialiseSubmittableScoreWithCustomModSetting()
|
||||||
{
|
{
|
||||||
var score = new ScoreInfo
|
var score = new SubmittableScore(new ScoreInfo
|
||||||
{
|
{
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
Mods = new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 2 } } }
|
Mods = new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 2 } } }
|
||||||
};
|
});
|
||||||
|
|
||||||
var deserialised = JsonConvert.DeserializeObject<ScoreInfo>(JsonConvert.SerializeObject(score));
|
var deserialised = JsonConvert.DeserializeObject<SubmittableScore>(JsonConvert.SerializeObject(score));
|
||||||
|
|
||||||
if (deserialised != null)
|
Assert.That((deserialised?.Mods[0])?.Settings["speed_change"], Is.EqualTo(2));
|
||||||
deserialised.Ruleset = new OsuRuleset().RulesetInfo;
|
|
||||||
|
|
||||||
Assert.That(((OsuModDoubleTime)deserialised?.Mods[0])?.SpeedChange.Value, Is.EqualTo(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestRuleset : Ruleset
|
private class TestRuleset : Ruleset
|
||||||
|
@ -132,9 +132,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
private ScoreInfo getScoreInfo(bool replayAvailable)
|
private ScoreInfo getScoreInfo(bool replayAvailable)
|
||||||
{
|
{
|
||||||
return new APILegacyScoreInfo
|
return new APIScoreInfo
|
||||||
{
|
{
|
||||||
OnlineScoreID = 2553163309,
|
OnlineID = 2553163309,
|
||||||
OnlineRulesetID = 0,
|
OnlineRulesetID = 0,
|
||||||
Replay = replayAvailable,
|
Replay = replayAvailable,
|
||||||
User = new User
|
User = new User
|
||||||
|
@ -43,11 +43,11 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var allScores = new APILegacyScores
|
var allScores = new APIScoresCollection
|
||||||
{
|
{
|
||||||
Scores = new List<APILegacyScoreInfo>
|
Scores = new List<APIScoreInfo>
|
||||||
{
|
{
|
||||||
new APILegacyScoreInfo
|
new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
TotalScore = 1234567890,
|
TotalScore = 1234567890,
|
||||||
Accuracy = 1,
|
Accuracy = 1,
|
||||||
},
|
},
|
||||||
new APILegacyScoreInfo
|
new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
TotalScore = 1234789,
|
TotalScore = 1234789,
|
||||||
Accuracy = 0.9997,
|
Accuracy = 0.9997,
|
||||||
},
|
},
|
||||||
new APILegacyScoreInfo
|
new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
TotalScore = 12345678,
|
TotalScore = 12345678,
|
||||||
Accuracy = 0.9854,
|
Accuracy = 0.9854,
|
||||||
},
|
},
|
||||||
new APILegacyScoreInfo
|
new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -141,7 +141,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
TotalScore = 1234567,
|
TotalScore = 1234567,
|
||||||
Accuracy = 0.8765,
|
Accuracy = 0.8765,
|
||||||
},
|
},
|
||||||
new APILegacyScoreInfo
|
new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -162,9 +162,9 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var myBestScore = new APILegacyUserTopScoreInfo
|
var myBestScore = new APIScoreWithPosition
|
||||||
{
|
{
|
||||||
Score = new APILegacyScoreInfo
|
Score = new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -185,9 +185,9 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
Position = 1337,
|
Position = 1337,
|
||||||
};
|
};
|
||||||
|
|
||||||
var myBestScoreWithNullPosition = new APILegacyUserTopScoreInfo
|
var myBestScoreWithNullPosition = new APIScoreWithPosition
|
||||||
{
|
{
|
||||||
Score = new APILegacyScoreInfo
|
Score = new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -208,11 +208,11 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
Position = null,
|
Position = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
var oneScore = new APILegacyScores
|
var oneScore = new APIScoresCollection
|
||||||
{
|
{
|
||||||
Scores = new List<APILegacyScoreInfo>
|
Scores = new List<APIScoreInfo>
|
||||||
{
|
{
|
||||||
new APILegacyScoreInfo
|
new APIScoreInfo
|
||||||
{
|
{
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
@ -273,7 +273,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private class TestScoresContainer : ScoresContainer
|
private class TestScoresContainer : ScoresContainer
|
||||||
{
|
{
|
||||||
public new APILegacyScores Scores
|
public new APIScoresCollection Scores
|
||||||
{
|
{
|
||||||
set => base.Scores = value;
|
set => base.Scores = value;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A single beatmap difficulty.
|
/// A single beatmap difficulty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBeatmapInfo : IHasOnlineID
|
public interface IBeatmapInfo : IHasOnlineID<int>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user-specified name given to this beatmap.
|
/// The user-specified name given to this beatmap.
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A representation of a collection of beatmap difficulties, generally packaged as an ".osz" archive.
|
/// A representation of a collection of beatmap difficulties, generally packaged as an ".osz" archive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBeatmapSetInfo : IHasOnlineID
|
public interface IBeatmapSetInfo : IHasOnlineID<int>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date when this beatmap was imported.
|
/// The date when this beatmap was imported.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
public interface IHasOnlineID
|
public interface IHasOnlineID<out T>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID.
|
/// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID.
|
||||||
@ -14,6 +14,6 @@ namespace osu.Game.Database
|
|||||||
/// Generally we use -1 when specifying "missing" in code, but values of 0 are also considered missing as the online source
|
/// Generally we use -1 when specifying "missing" in code, but values of 0 are also considered missing as the online source
|
||||||
/// is generally a MySQL autoincrement value, which can never be 0.
|
/// is generally a MySQL autoincrement value, which can never be 0.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
int OnlineID { get; }
|
T OnlineID { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,21 +9,20 @@ using osu.Game.Online.API.Requests.Responses;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.API.Requests
|
||||||
{
|
{
|
||||||
public class GetScoresRequest : APIRequest<APILegacyScores>
|
public class GetScoresRequest : APIRequest<APIScoresCollection>
|
||||||
{
|
{
|
||||||
private readonly BeatmapInfo beatmapInfo;
|
private readonly IBeatmapInfo beatmapInfo;
|
||||||
private readonly BeatmapLeaderboardScope scope;
|
private readonly BeatmapLeaderboardScope scope;
|
||||||
private readonly RulesetInfo ruleset;
|
private readonly IRulesetInfo ruleset;
|
||||||
private readonly IEnumerable<IMod> mods;
|
private readonly IEnumerable<IMod> mods;
|
||||||
|
|
||||||
public GetScoresRequest(BeatmapInfo beatmapInfo, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global, IEnumerable<IMod> mods = null)
|
public GetScoresRequest(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global, IEnumerable<IMod> mods = null)
|
||||||
{
|
{
|
||||||
if (!beatmapInfo.OnlineBeatmapID.HasValue)
|
if (beatmapInfo.OnlineID <= 0)
|
||||||
throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}.");
|
throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(IBeatmapInfo.OnlineID)}.");
|
||||||
|
|
||||||
if (scope == BeatmapLeaderboardScope.Local)
|
if (scope == BeatmapLeaderboardScope.Local)
|
||||||
throw new InvalidOperationException("Should not attempt to request online scores for a local scoped leaderboard");
|
throw new InvalidOperationException("Should not attempt to request online scores for a local scoped leaderboard");
|
||||||
@ -32,30 +31,9 @@ namespace osu.Game.Online.API.Requests
|
|||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.ruleset = ruleset ?? throw new ArgumentNullException(nameof(ruleset));
|
this.ruleset = ruleset ?? throw new ArgumentNullException(nameof(ruleset));
|
||||||
this.mods = mods ?? Array.Empty<IMod>();
|
this.mods = mods ?? Array.Empty<IMod>();
|
||||||
|
|
||||||
Success += onSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSuccess(APILegacyScores r)
|
protected override string Target => $@"beatmaps/{beatmapInfo.OnlineID}/scores{createQueryParameters()}";
|
||||||
{
|
|
||||||
Debug.Assert(ruleset.ID != null, "ruleset.ID != null");
|
|
||||||
|
|
||||||
foreach (APILegacyScoreInfo score in r.Scores)
|
|
||||||
{
|
|
||||||
score.BeatmapInfo = beatmapInfo;
|
|
||||||
score.OnlineRulesetID = ruleset.ID.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var userScore = r.UserScore;
|
|
||||||
|
|
||||||
if (userScore != null)
|
|
||||||
{
|
|
||||||
userScore.Score.BeatmapInfo = beatmapInfo;
|
|
||||||
userScore.Score.OnlineRulesetID = ruleset.ID.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string Target => $@"beatmaps/{beatmapInfo.OnlineBeatmapID}/scores{createQueryParameters()}";
|
|
||||||
|
|
||||||
private string createQueryParameters()
|
private string createQueryParameters()
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Rulesets;
|
|||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.API.Requests
|
||||||
{
|
{
|
||||||
public class GetUserScoresRequest : PaginatedAPIRequest<List<APILegacyScoreInfo>>
|
public class GetUserScoresRequest : PaginatedAPIRequest<List<APIScoreInfo>>
|
||||||
{
|
{
|
||||||
private readonly long userId;
|
private readonly long userId;
|
||||||
private readonly ScoreType type;
|
private readonly ScoreType type;
|
||||||
|
@ -1,35 +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 System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests.Responses
|
|
||||||
{
|
|
||||||
public class APILegacyScores
|
|
||||||
{
|
|
||||||
[JsonProperty(@"scores")]
|
|
||||||
public List<APILegacyScoreInfo> Scores;
|
|
||||||
|
|
||||||
[JsonProperty(@"userScore")]
|
|
||||||
public APILegacyUserTopScoreInfo UserScore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class APILegacyUserTopScoreInfo
|
|
||||||
{
|
|
||||||
[JsonProperty(@"position")]
|
|
||||||
public int? Position;
|
|
||||||
|
|
||||||
[JsonProperty(@"score")]
|
|
||||||
public APILegacyScoreInfo Score;
|
|
||||||
|
|
||||||
public ScoreInfo CreateScoreInfo(RulesetStore rulesets)
|
|
||||||
{
|
|
||||||
var score = Score.CreateScoreInfo(rulesets);
|
|
||||||
score.Position = Position;
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,9 +15,68 @@ using osu.Game.Users;
|
|||||||
|
|
||||||
namespace osu.Game.Online.API.Requests.Responses
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
{
|
{
|
||||||
public class APILegacyScoreInfo
|
public class APIScoreInfo : IScoreInfo
|
||||||
{
|
{
|
||||||
public ScoreInfo CreateScoreInfo(RulesetStore rulesets)
|
[JsonProperty(@"score")]
|
||||||
|
public long TotalScore { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"max_combo")]
|
||||||
|
public int MaxCombo { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"user")]
|
||||||
|
public User User { get; set; }
|
||||||
|
|
||||||
|
public bool HasReplay { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"id")]
|
||||||
|
public long OnlineID { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"replay")]
|
||||||
|
public bool Replay { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"created_at")]
|
||||||
|
public DateTimeOffset Date { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"beatmap")]
|
||||||
|
public APIBeatmap Beatmap { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("accuracy")]
|
||||||
|
public double Accuracy { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"pp")]
|
||||||
|
public double? PP { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"beatmapset")]
|
||||||
|
public APIBeatmapSet BeatmapSet
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// in the deserialisation case we need to ferry this data across.
|
||||||
|
if (Beatmap is APIBeatmap apiBeatmap)
|
||||||
|
apiBeatmap.BeatmapSet = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonProperty("statistics")]
|
||||||
|
public Dictionary<string, int> Statistics { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"mode_int")]
|
||||||
|
public int OnlineRulesetID { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"mods")]
|
||||||
|
public string[] Mods { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("rank")]
|
||||||
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
|
public ScoreRank Rank { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a <see cref="ScoreInfo"/> from an API score instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rulesets">A ruleset store, used to populate a ruleset instance in the returned score.</param>
|
||||||
|
/// <param name="beatmap">An optional beatmap, copied into the returned score (for cases where the API does not populate the beatmap).</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null)
|
||||||
{
|
{
|
||||||
var ruleset = rulesets.GetRuleset(OnlineRulesetID);
|
var ruleset = rulesets.GetRuleset(OnlineRulesetID);
|
||||||
|
|
||||||
@ -34,10 +93,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
MaxCombo = MaxCombo,
|
MaxCombo = MaxCombo,
|
||||||
User = User,
|
User = User,
|
||||||
Accuracy = Accuracy,
|
Accuracy = Accuracy,
|
||||||
OnlineScoreID = OnlineScoreID,
|
OnlineScoreID = OnlineID,
|
||||||
Date = Date,
|
Date = Date,
|
||||||
PP = PP,
|
PP = PP,
|
||||||
BeatmapInfo = BeatmapInfo,
|
|
||||||
RulesetID = OnlineRulesetID,
|
RulesetID = OnlineRulesetID,
|
||||||
Hash = Replay ? "online" : string.Empty, // todo: temporary?
|
Hash = Replay ? "online" : string.Empty, // todo: temporary?
|
||||||
Rank = Rank,
|
Rank = Rank,
|
||||||
@ -45,6 +103,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
Mods = mods,
|
Mods = mods,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (beatmap != null)
|
||||||
|
scoreInfo.BeatmapInfo = beatmap;
|
||||||
|
|
||||||
if (Statistics != null)
|
if (Statistics != null)
|
||||||
{
|
{
|
||||||
foreach (var kvp in Statistics)
|
foreach (var kvp in Statistics)
|
||||||
@ -81,57 +142,8 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
return scoreInfo;
|
return scoreInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty(@"score")]
|
public IRulesetInfo Ruleset => new RulesetInfo { ID = OnlineRulesetID };
|
||||||
public int TotalScore { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"max_combo")]
|
IBeatmapInfo IScoreInfo.Beatmap => Beatmap;
|
||||||
public int MaxCombo { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"user")]
|
|
||||||
public User User { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"id")]
|
|
||||||
public long OnlineScoreID { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"replay")]
|
|
||||||
public bool Replay { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"created_at")]
|
|
||||||
public DateTimeOffset Date { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"beatmap")]
|
|
||||||
public BeatmapInfo BeatmapInfo { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("accuracy")]
|
|
||||||
public double Accuracy { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"pp")]
|
|
||||||
public double? PP { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"beatmapset")]
|
|
||||||
public BeatmapMetadata Metadata
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
// extract the set ID to its correct place.
|
|
||||||
BeatmapInfo.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = value.ID };
|
|
||||||
value.ID = 0;
|
|
||||||
|
|
||||||
BeatmapInfo.Metadata = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty(@"statistics")]
|
|
||||||
public Dictionary<string, int> Statistics { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"mode_int")]
|
|
||||||
public int OnlineRulesetID { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(@"mods")]
|
|
||||||
public string[] Mods { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("rank")]
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
|
||||||
public ScoreRank Rank { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
|
{
|
||||||
|
public class APIScoreWithPosition
|
||||||
|
{
|
||||||
|
[JsonProperty(@"position")]
|
||||||
|
public int? Position;
|
||||||
|
|
||||||
|
[JsonProperty(@"score")]
|
||||||
|
public APIScoreInfo Score;
|
||||||
|
|
||||||
|
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null)
|
||||||
|
|
||||||
|
{
|
||||||
|
var score = Score.CreateScoreInfo(rulesets, beatmap);
|
||||||
|
score.Position = Position;
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
|
{
|
||||||
|
public class APIScoresCollection
|
||||||
|
{
|
||||||
|
[JsonProperty(@"scores")]
|
||||||
|
public List<APIScoreInfo> Scores;
|
||||||
|
|
||||||
|
[JsonProperty(@"userScore")]
|
||||||
|
public APIScoreWithPosition UserScore;
|
||||||
|
}
|
||||||
|
}
|
@ -16,13 +16,13 @@ namespace osu.Game.Online.Solo
|
|||||||
|
|
||||||
private readonly int beatmapId;
|
private readonly int beatmapId;
|
||||||
|
|
||||||
private readonly ScoreInfo scoreInfo;
|
private readonly SubmittableScore score;
|
||||||
|
|
||||||
public SubmitSoloScoreRequest(int beatmapId, long scoreId, ScoreInfo scoreInfo)
|
public SubmitSoloScoreRequest(int beatmapId, long scoreId, ScoreInfo scoreInfo)
|
||||||
{
|
{
|
||||||
this.beatmapId = beatmapId;
|
this.beatmapId = beatmapId;
|
||||||
this.scoreId = scoreId;
|
this.scoreId = scoreId;
|
||||||
this.scoreInfo = scoreInfo;
|
score = new SubmittableScore(scoreInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override WebRequest CreateWebRequest()
|
protected override WebRequest CreateWebRequest()
|
||||||
@ -32,7 +32,7 @@ namespace osu.Game.Online.Solo
|
|||||||
req.ContentType = "application/json";
|
req.ContentType = "application/json";
|
||||||
req.Method = HttpMethod.Put;
|
req.Method = HttpMethod.Put;
|
||||||
|
|
||||||
req.AddRaw(JsonConvert.SerializeObject(scoreInfo, new JsonSerializerSettings
|
req.AddRaw(JsonConvert.SerializeObject(score, new JsonSerializerSettings
|
||||||
{
|
{
|
||||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
||||||
}));
|
}));
|
||||||
|
75
osu.Game/Online/Solo/SubmittableScore.cs
Normal file
75
osu.Game/Online/Solo/SubmittableScore.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// 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 JetBrains.Annotations;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.Solo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A class specifically for sending scores to the API during score submission.
|
||||||
|
/// This is used instead of <see cref="APIScoreInfo"/> due to marginally different serialisation naming requirements.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class SubmittableScore
|
||||||
|
{
|
||||||
|
[JsonProperty("rank")]
|
||||||
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
|
public ScoreRank Rank { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("total_score")]
|
||||||
|
public long TotalScore { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("accuracy")]
|
||||||
|
public double Accuracy { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"pp")]
|
||||||
|
public double? PP { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("max_combo")]
|
||||||
|
public int MaxCombo { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ruleset_id")]
|
||||||
|
public int RulesetID { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("passed")]
|
||||||
|
public bool Passed { get; set; }
|
||||||
|
|
||||||
|
// Used for API serialisation/deserialisation.
|
||||||
|
[JsonProperty("mods")]
|
||||||
|
public APIMod[] Mods { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("user")]
|
||||||
|
public User User { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("statistics")]
|
||||||
|
public Dictionary<HitResult, int> Statistics { get; set; }
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public SubmittableScore()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubmittableScore(ScoreInfo score)
|
||||||
|
{
|
||||||
|
Rank = score.Rank;
|
||||||
|
TotalScore = score.TotalScore;
|
||||||
|
Accuracy = score.Accuracy;
|
||||||
|
PP = score.PP;
|
||||||
|
MaxCombo = score.MaxCombo;
|
||||||
|
RulesetID = score.RulesetID;
|
||||||
|
Passed = score.Passed;
|
||||||
|
Mods = score.APIMods;
|
||||||
|
User = score.User;
|
||||||
|
Statistics = score.Statistics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -436,11 +436,15 @@ namespace osu.Game
|
|||||||
/// <item>first beatmap from any ruleset.</item>
|
/// <item>first beatmap from any ruleset.</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public void PresentBeatmap(BeatmapSetInfo beatmap, Predicate<BeatmapInfo> difficultyCriteria = null)
|
public void PresentBeatmap(IBeatmapSetInfo beatmap, Predicate<BeatmapInfo> difficultyCriteria = null)
|
||||||
{
|
{
|
||||||
var databasedSet = beatmap.OnlineBeatmapSetID != null
|
BeatmapSetInfo databasedSet = null;
|
||||||
? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID)
|
|
||||||
: BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmap.Hash);
|
if (beatmap.OnlineID > 0)
|
||||||
|
databasedSet = BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineID);
|
||||||
|
|
||||||
|
if (beatmap is BeatmapSetInfo localBeatmap)
|
||||||
|
databasedSet ??= BeatmapManager.QueryBeatmapSet(s => s.Hash == localBeatmap.Hash);
|
||||||
|
|
||||||
if (databasedSet == null)
|
if (databasedSet == null)
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
|
|
||||||
private CancellationTokenSource loadCancellationSource;
|
private CancellationTokenSource loadCancellationSource;
|
||||||
|
|
||||||
protected APILegacyScores Scores
|
protected APIScoresCollection Scores
|
||||||
{
|
{
|
||||||
set => Schedule(() =>
|
set => Schedule(() =>
|
||||||
{
|
{
|
||||||
@ -66,7 +66,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
if (value?.Scores.Any() != true)
|
if (value?.Scores.Any() != true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
scoreManager.OrderByTotalScoreAsync(value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToArray(), loadCancellationSource.Token)
|
scoreManager.OrderByTotalScoreAsync(value.Scores.Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value)).ToArray(), loadCancellationSource.Token)
|
||||||
.ContinueWith(ordered => Schedule(() =>
|
.ContinueWith(ordered => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (loadCancellationSource.IsCancellationRequested)
|
if (loadCancellationSource.IsCancellationRequested)
|
||||||
@ -78,7 +78,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
scoreTable.Show();
|
scoreTable.Show();
|
||||||
|
|
||||||
var userScore = value.UserScore;
|
var userScore = value.UserScore;
|
||||||
var userScoreInfo = userScore?.Score.CreateScoreInfo(rulesets);
|
var userScoreInfo = userScore?.Score.CreateScoreInfo(rulesets, Beatmap.Value);
|
||||||
|
|
||||||
topScoresContainer.Add(new DrawableTopScore(topScore));
|
topScoresContainer.Add(new DrawableTopScore(topScore));
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ using osu.Framework.Localisation;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections.Ranks
|
namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||||
{
|
{
|
||||||
public class PaginatedScoreContainer : PaginatedProfileSubsection<APILegacyScoreInfo>
|
public class PaginatedScoreContainer : PaginatedProfileSubsection<APIScoreInfo>
|
||||||
{
|
{
|
||||||
private readonly ScoreType type;
|
private readonly ScoreType type;
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnItemsReceived(List<APILegacyScoreInfo> items)
|
protected override void OnItemsReceived(List<APIScoreInfo> items)
|
||||||
{
|
{
|
||||||
if (VisiblePages == 0)
|
if (VisiblePages == 0)
|
||||||
drawableItemIndex = 0;
|
drawableItemIndex = 0;
|
||||||
@ -59,12 +59,12 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
base.OnItemsReceived(items);
|
base.OnItemsReceived(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override APIRequest<List<APILegacyScoreInfo>> CreateRequest() =>
|
protected override APIRequest<List<APIScoreInfo>> CreateRequest() =>
|
||||||
new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
|
new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
|
||||||
|
|
||||||
private int drawableItemIndex;
|
private int drawableItemIndex;
|
||||||
|
|
||||||
protected override Drawable CreateDrawableItem(APILegacyScoreInfo model)
|
protected override Drawable CreateDrawableItem(APIScoreInfo model)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A representation of a ruleset's metadata.
|
/// A representation of a ruleset's metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IRulesetInfo : IHasOnlineID
|
public interface IRulesetInfo : IHasOnlineID<int>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user-exposed name of this ruleset.
|
/// The user-exposed name of this ruleset.
|
||||||
|
39
osu.Game/Scoring/IScoreInfo.cs
Normal file
39
osu.Game/Scoring/IScoreInfo.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// 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 osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
namespace osu.Game.Scoring
|
||||||
|
{
|
||||||
|
public interface IScoreInfo : IHasOnlineID<long>
|
||||||
|
{
|
||||||
|
User User { get; }
|
||||||
|
|
||||||
|
long TotalScore { get; }
|
||||||
|
|
||||||
|
int MaxCombo { get; }
|
||||||
|
|
||||||
|
double Accuracy { get; }
|
||||||
|
|
||||||
|
bool HasReplay { get; }
|
||||||
|
|
||||||
|
DateTimeOffset Date { get; }
|
||||||
|
|
||||||
|
double? PP { get; }
|
||||||
|
|
||||||
|
IBeatmapInfo Beatmap { get; }
|
||||||
|
|
||||||
|
IRulesetInfo Ruleset { get; }
|
||||||
|
|
||||||
|
public ScoreRank Rank { get; }
|
||||||
|
|
||||||
|
// Mods is currently missing from this interface as the `IMod` class has properties which can't be fulfilled by `APIMod`,
|
||||||
|
// but also doesn't expose `Settings`. We can consider how to implement this in the future if required.
|
||||||
|
|
||||||
|
// Statistics is also missing. This can be reconsidered once changes in serialisation have been completed.
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
@ -19,47 +18,36 @@ using osu.Game.Utils;
|
|||||||
|
|
||||||
namespace osu.Game.Scoring
|
namespace osu.Game.Scoring
|
||||||
{
|
{
|
||||||
public class ScoreInfo : IHasFiles<ScoreFileInfo>, IHasPrimaryKey, ISoftDelete, IEquatable<ScoreInfo>, IDeepCloneable<ScoreInfo>
|
public class ScoreInfo : IScoreInfo, IHasFiles<ScoreFileInfo>, IHasPrimaryKey, ISoftDelete, IEquatable<ScoreInfo>, IDeepCloneable<ScoreInfo>
|
||||||
{
|
{
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
[JsonProperty("rank")]
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
|
||||||
public ScoreRank Rank { get; set; }
|
public ScoreRank Rank { get; set; }
|
||||||
|
|
||||||
[JsonProperty("total_score")]
|
|
||||||
public long TotalScore { get; set; }
|
public long TotalScore { get; set; }
|
||||||
|
|
||||||
[JsonProperty("accuracy")]
|
|
||||||
[Column(TypeName = "DECIMAL(1,4)")] // TODO: This data type is wrong (should contain more precision). But at the same time, we probably don't need to be storing this in the database.
|
[Column(TypeName = "DECIMAL(1,4)")] // TODO: This data type is wrong (should contain more precision). But at the same time, we probably don't need to be storing this in the database.
|
||||||
public double Accuracy { get; set; }
|
public double Accuracy { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public LocalisableString DisplayAccuracy => Accuracy.FormatAccuracy();
|
public LocalisableString DisplayAccuracy => Accuracy.FormatAccuracy();
|
||||||
|
|
||||||
[JsonProperty(@"pp")]
|
|
||||||
public double? PP { get; set; }
|
public double? PP { get; set; }
|
||||||
|
|
||||||
[JsonProperty("max_combo")]
|
|
||||||
public int MaxCombo { get; set; }
|
public int MaxCombo { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public int Combo { get; set; } // Todo: Shouldn't exist in here
|
public int Combo { get; set; } // Todo: Shouldn't exist in here
|
||||||
|
|
||||||
[JsonProperty("ruleset_id")]
|
|
||||||
public int RulesetID { get; set; }
|
public int RulesetID { get; set; }
|
||||||
|
|
||||||
[JsonProperty("passed")]
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public bool Passed { get; set; } = true;
|
public bool Passed { get; set; } = true;
|
||||||
|
|
||||||
[JsonIgnore]
|
public RulesetInfo Ruleset { get; set; }
|
||||||
public virtual RulesetInfo Ruleset { get; set; }
|
|
||||||
|
|
||||||
private APIMod[] localAPIMods;
|
private APIMod[] localAPIMods;
|
||||||
|
|
||||||
private Mod[] mods;
|
private Mod[] mods;
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public Mod[] Mods
|
public Mod[] Mods
|
||||||
{
|
{
|
||||||
@ -74,7 +62,7 @@ namespace osu.Game.Scoring
|
|||||||
if (mods != null)
|
if (mods != null)
|
||||||
scoreMods = mods;
|
scoreMods = mods;
|
||||||
else if (localAPIMods != null)
|
else if (localAPIMods != null)
|
||||||
scoreMods = apiMods.Select(m => m.ToMod(rulesetInstance)).ToArray();
|
scoreMods = APIMods.Select(m => m.ToMod(rulesetInstance)).ToArray();
|
||||||
|
|
||||||
return scoreMods;
|
return scoreMods;
|
||||||
}
|
}
|
||||||
@ -86,9 +74,8 @@ namespace osu.Game.Scoring
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Used for API serialisation/deserialisation.
|
// Used for API serialisation/deserialisation.
|
||||||
[JsonProperty("mods")]
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
private APIMod[] apiMods
|
public APIMod[] APIMods
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -110,19 +97,16 @@ namespace osu.Game.Scoring
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Used for database serialisation/deserialisation.
|
// Used for database serialisation/deserialisation.
|
||||||
[JsonIgnore]
|
|
||||||
[Column("Mods")]
|
[Column("Mods")]
|
||||||
public string ModsJson
|
public string ModsJson
|
||||||
{
|
{
|
||||||
get => JsonConvert.SerializeObject(apiMods);
|
get => JsonConvert.SerializeObject(APIMods);
|
||||||
set => apiMods = JsonConvert.DeserializeObject<APIMod[]>(value);
|
set => APIMods = JsonConvert.DeserializeObject<APIMod[]>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[JsonProperty("user")]
|
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
[Column("User")]
|
[Column("User")]
|
||||||
public string UserString
|
public string UserString
|
||||||
{
|
{
|
||||||
@ -134,7 +118,6 @@ namespace osu.Game.Scoring
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
[Column("UserID")]
|
[Column("UserID")]
|
||||||
public int? UserID
|
public int? UserID
|
||||||
{
|
{
|
||||||
@ -146,23 +129,18 @@ namespace osu.Game.Scoring
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public int BeatmapInfoID { get; set; }
|
public int BeatmapInfoID { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
[Column("Beatmap")]
|
[Column("Beatmap")]
|
||||||
public virtual BeatmapInfo BeatmapInfo { get; set; }
|
public BeatmapInfo BeatmapInfo { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public long? OnlineScoreID { get; set; }
|
public long? OnlineScoreID { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public DateTimeOffset Date { get; set; }
|
public DateTimeOffset Date { get; set; }
|
||||||
|
|
||||||
[JsonProperty("statistics")]
|
[NotMapped]
|
||||||
public Dictionary<HitResult, int> Statistics = new Dictionary<HitResult, int>();
|
public Dictionary<HitResult, int> Statistics { get; set; } = new Dictionary<HitResult, int>();
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
[Column("Statistics")]
|
[Column("Statistics")]
|
||||||
public string StatisticsJson
|
public string StatisticsJson
|
||||||
{
|
{
|
||||||
@ -180,29 +158,23 @@ namespace osu.Game.Scoring
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[JsonIgnore]
|
|
||||||
public List<HitEvent> HitEvents { get; set; }
|
public List<HitEvent> HitEvents { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public List<ScoreFileInfo> Files { get; set; }
|
public List<ScoreFileInfo> Files { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public string Hash { get; set; }
|
public string Hash { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool DeletePending { get; set; }
|
public bool DeletePending { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The position of this score, starting at 1.
|
/// The position of this score, starting at 1.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[JsonProperty("position")]
|
public int? Position { get; set; } // TODO: remove after all calls to `CreateScoreInfo` are gone.
|
||||||
public int? Position { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this <see cref="ScoreInfo"/> represents a legacy (osu!stable) score.
|
/// Whether this <see cref="ScoreInfo"/> represents a legacy (osu!stable) score.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public bool IsLegacyScore => Mods.OfType<ModClassic>().Any();
|
public bool IsLegacyScore => Mods.OfType<ModClassic>().Any();
|
||||||
|
|
||||||
@ -271,5 +243,11 @@ namespace osu.Game.Scoring
|
|||||||
|
|
||||||
return ReferenceEquals(this, other);
|
return ReferenceEquals(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long OnlineID => OnlineScoreID ?? -1;
|
||||||
|
|
||||||
|
IBeatmapInfo IScoreInfo.Beatmap => BeatmapInfo;
|
||||||
|
IRulesetInfo IScoreInfo.Ruleset => Ruleset;
|
||||||
|
bool IScoreInfo.HasReplay => Files.Any();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
getScoreRequest = new GetScoresRequest(Score.BeatmapInfo, Score.Ruleset);
|
getScoreRequest = new GetScoresRequest(Score.BeatmapInfo, Score.Ruleset);
|
||||||
getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineScoreID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets)));
|
getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value.BeatmapInfo)));
|
||||||
return getScoreRequest;
|
return getScoreRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,14 +192,14 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
req.Success += r =>
|
req.Success += r =>
|
||||||
{
|
{
|
||||||
scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToArray(), loadCancellationSource.Token)
|
scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets, BeatmapInfo)).ToArray(), loadCancellationSource.Token)
|
||||||
.ContinueWith(ordered => Schedule(() =>
|
.ContinueWith(ordered => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (loadCancellationSource.IsCancellationRequested)
|
if (loadCancellationSource.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
scoresCallback?.Invoke(ordered.Result);
|
scoresCallback?.Invoke(ordered.Result);
|
||||||
TopScore = r.UserScore?.CreateScoreInfo(rulesets);
|
TopScore = r.UserScore?.CreateScoreInfo(rulesets, BeatmapInfo);
|
||||||
}), TaskContinuationOptions.OnlyOnRanToCompletion);
|
}), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user