1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 17:23:22 +08:00

Merge pull request #19379 from frenzibyte/remove-submittable-score

Remove no longer necessary API score models
This commit is contained in:
Dan Balasescu 2022-07-26 14:07:40 +09:00 committed by GitHub
commit a7598c62ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 266 deletions

View File

@ -12,7 +12,6 @@ using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Solo;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods;
@ -110,30 +109,30 @@ namespace osu.Game.Tests.Online
}
[Test]
public void TestDeserialiseSubmittableScoreWithEmptyMods()
public void TestDeserialiseSoloScoreWithEmptyMods()
{
var score = new SubmittableScore(new ScoreInfo
var score = SoloScoreInfo.ForSubmission(new ScoreInfo
{
User = new APIUser(),
Ruleset = new OsuRuleset().RulesetInfo,
});
var deserialised = JsonConvert.DeserializeObject<SubmittableScore>(JsonConvert.SerializeObject(score));
var deserialised = JsonConvert.DeserializeObject<SoloScoreInfo>(JsonConvert.SerializeObject(score));
Assert.That(deserialised?.Mods.Length, Is.Zero);
}
[Test]
public void TestDeserialiseSubmittableScoreWithCustomModSetting()
public void TestDeserialiseSoloScoreWithCustomModSetting()
{
var score = new SubmittableScore(new ScoreInfo
var score = SoloScoreInfo.ForSubmission(new ScoreInfo
{
Mods = new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 2 } } },
User = new APIUser(),
Ruleset = new OsuRuleset().RulesetInfo,
});
var deserialised = JsonConvert.DeserializeObject<SubmittableScore>(JsonConvert.SerializeObject(score));
var deserialised = JsonConvert.DeserializeObject<SoloScoreInfo>(JsonConvert.SerializeObject(score));
Assert.That((deserialised?.Mods[0])?.Settings["speed_change"], Is.EqualTo(2));
}

View File

@ -6,7 +6,7 @@
using Newtonsoft.Json;
using NUnit.Framework;
using osu.Game.IO.Serialization;
using osu.Game.Online.Solo;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Online
@ -15,12 +15,12 @@ namespace osu.Game.Tests.Online
/// Basic testing to ensure our attribute-based naming is correctly working.
/// </summary>
[TestFixture]
public class TestSubmittableScoreJsonSerialization
public class TestSoloScoreInfoJsonSerialization
{
[Test]
public void TestScoreSerialisationViaExtensionMethod()
{
var score = new SubmittableScore(TestResources.CreateTestScoreInfo());
var score = SoloScoreInfo.ForSubmission(TestResources.CreateTestScoreInfo());
string serialised = score.Serialize();
@ -31,7 +31,7 @@ namespace osu.Game.Tests.Online
[Test]
public void TestScoreSerialisationWithoutSettings()
{
var score = new SubmittableScore(TestResources.CreateTestScoreInfo());
var score = SoloScoreInfo.ForSubmission(TestResources.CreateTestScoreInfo());
string serialised = JsonConvert.SerializeObject(score);

View File

@ -7,7 +7,6 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Online;
using osu.Game.Online.API.Requests.Responses;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
@ -15,7 +14,6 @@ using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
@ -30,9 +28,6 @@ namespace osu.Game.Tests.Visual.Gameplay
{
private const long online_score_id = 2553163309;
[Resolved]
private RulesetStore rulesets { get; set; }
private TestReplayDownloadButton downloadButton;
[Resolved]
@ -211,21 +206,18 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType<DownloadButton>().First().Enabled.Value);
}
private ScoreInfo getScoreInfo(bool replayAvailable, bool hasOnlineId = true)
private ScoreInfo getScoreInfo(bool replayAvailable, bool hasOnlineId = true) => new ScoreInfo
{
return new APIScore
OnlineID = hasOnlineId ? online_score_id : 0,
Ruleset = new OsuRuleset().RulesetInfo,
BeatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(),
Hash = replayAvailable ? "online" : string.Empty,
User = new APIUser
{
OnlineID = hasOnlineId ? online_score_id : 0,
RulesetID = 0,
Beatmap = CreateAPIBeatmapSet(new OsuRuleset().RulesetInfo).Beatmaps.First(),
HasReplay = replayAvailable,
User = new APIUser
{
Id = 39828,
Username = @"WubWoofWolf",
}
}.CreateScoreInfo(rulesets, beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First());
}
Id = 39828,
Username = @"WubWoofWolf",
}
};
private class TestReplayDownloadButton : ReplayDownloadButton
{

View File

@ -1,162 +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.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
using osu.Game.Users;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIScore : IScoreInfo
{
[JsonProperty(@"score")]
public long TotalScore { get; set; }
[JsonProperty(@"max_combo")]
public int MaxCombo { get; set; }
[JsonProperty(@"user")]
public APIUser User { get; set; }
[JsonProperty(@"id")]
public long OnlineID { get; set; }
[JsonProperty(@"replay")]
public bool HasReplay { get; set; }
[JsonProperty(@"created_at")]
public DateTimeOffset Date { get; set; }
[JsonProperty(@"beatmap")]
[CanBeNull]
public APIBeatmap Beatmap { get; set; }
[JsonProperty("accuracy")]
public double Accuracy { get; set; }
[JsonProperty(@"pp")]
public double? PP { get; set; }
[JsonProperty(@"beatmapset")]
[CanBeNull]
public APIBeatmapSet BeatmapSet
{
set
{
// in the deserialisation case we need to ferry this data across.
// the order of properties returned by the API guarantees that the beatmap is populated by this point.
if (!(Beatmap is APIBeatmap apiBeatmap))
throw new InvalidOperationException("Beatmap set metadata arrived before beatmap metadata in response");
apiBeatmap.BeatmapSet = value;
}
}
[JsonProperty("statistics")]
public Dictionary<string, int> Statistics { get; set; }
[JsonProperty(@"mode_int")]
public int RulesetID { get; set; }
[JsonProperty(@"mods")]
private string[] mods { set => Mods = value.Select(acronym => new APIMod { Acronym = acronym }); }
[NotNull]
public IEnumerable<APIMod> Mods { get; set; } = Array.Empty<APIMod>();
[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(RulesetID) ?? throw new InvalidOperationException($"Ruleset with ID of {RulesetID} not found locally");
var rulesetInstance = ruleset.CreateInstance();
var modInstances = Mods.Select(apiMod => rulesetInstance.CreateModFromAcronym(apiMod.Acronym)).Where(m => m != null).ToArray();
// all API scores provided by this class are considered to be legacy.
modInstances = modInstances.Append(rulesetInstance.CreateMod<ModClassic>()).ToArray();
var scoreInfo = new ScoreInfo
{
TotalScore = TotalScore,
MaxCombo = MaxCombo,
BeatmapInfo = beatmap ?? new BeatmapInfo(),
User = User,
Accuracy = Accuracy,
OnlineID = OnlineID,
Date = Date,
PP = PP,
Hash = HasReplay ? "online" : string.Empty, // todo: temporary?
Rank = Rank,
Ruleset = ruleset,
Mods = modInstances,
};
if (Statistics != null)
{
foreach (var kvp in Statistics)
{
switch (kvp.Key)
{
case @"count_geki":
scoreInfo.SetCountGeki(kvp.Value);
break;
case @"count_300":
scoreInfo.SetCount300(kvp.Value);
break;
case @"count_katu":
scoreInfo.SetCountKatu(kvp.Value);
break;
case @"count_100":
scoreInfo.SetCount100(kvp.Value);
break;
case @"count_50":
scoreInfo.SetCount50(kvp.Value);
break;
case @"count_miss":
scoreInfo.SetCountMiss(kvp.Value);
break;
}
}
}
return scoreInfo;
}
public IRulesetInfo Ruleset => new RulesetInfo { OnlineID = RulesetID };
IEnumerable<INamedFileUsage> IHasNamedFiles.Files => throw new NotImplementedException();
#region Implementation of IScoreInfo
IBeatmapInfo IScoreInfo.Beatmap => Beatmap;
IUser IScoreInfo.User => User;
#endregion
}
}

View File

@ -151,6 +151,23 @@ namespace osu.Game.Online.API.Requests.Responses
PP = PP,
};
/// <summary>
/// Creates a <see cref="SoloScoreInfo"/> from a local score for score submission.
/// </summary>
/// <param name="score">The local score.</param>
public static SoloScoreInfo ForSubmission(ScoreInfo score) => new SoloScoreInfo
{
Rank = score.Rank,
TotalScore = (int)score.TotalScore,
Accuracy = score.Accuracy,
PP = score.PP,
MaxCombo = score.MaxCombo,
RulesetID = score.RulesetID,
Passed = score.Passed,
Mods = score.APIMods,
Statistics = score.Statistics,
};
public long OnlineID => ID ?? -1;
}
}

View File

@ -7,20 +7,20 @@ using System.Net.Http;
using Newtonsoft.Json;
using osu.Framework.IO.Network;
using osu.Game.Online.API;
using osu.Game.Online.Solo;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Scoring;
namespace osu.Game.Online.Rooms
{
public abstract class SubmitScoreRequest : APIRequest<MultiplayerScore>
{
public readonly SubmittableScore Score;
public readonly SoloScoreInfo Score;
protected readonly long ScoreId;
protected SubmitScoreRequest(ScoreInfo scoreInfo, long scoreId)
{
Score = new SubmittableScore(scoreInfo);
Score = SoloScoreInfo.ForSubmission(scoreInfo);
ScoreId = scoreId;
}

View File

@ -1,72 +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.
#nullable disable
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;
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="APIScore"/> 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("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;
Statistics = score.Statistics;
}
}
}