Merge remote-tracking branch 'upstream/master' into smoogipoo-editor-timeline-rework

This commit is contained in:
Dean Herbert 2018-06-11 20:17:41 +09:00
commit 37ea4c273b
34 changed files with 561 additions and 479 deletions

View File

@ -277,8 +277,13 @@ namespace osu.Game.Rulesets.Mania.UI
if (action != Action)
return false;
var hitObject = HitObjects.Objects.LastOrDefault(h => h.HitObject.StartTime > Time.Current) ?? HitObjects.Objects.FirstOrDefault();
hitObject?.PlaySamples();
var nextObject =
HitObjects.AliveObjects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current) ??
// fallback to non-alive objects to find next off-screen object
HitObjects.Objects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current) ??
HitObjects.Objects.LastOrDefault();
nextObject?.PlaySamples();
return true;
}

View File

@ -64,9 +64,7 @@ namespace osu.Game.Rulesets.Osu.UI
public override void PostProcess()
{
connectionLayer.HitObjects = HitObjects.Objects
.Select(d => d.HitObject)
.OrderBy(h => h.StartTime).OfType<OsuHitObject>();
connectionLayer.HitObjects = HitObjects.Objects.Select(d => d.HitObject).OfType<OsuHitObject>();
}
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)

View File

@ -6,7 +6,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.MathUtils;
using osu.Game.Graphics;
using osu.Game.Online.API.Requests;
using osu.Game.Overlays.BeatmapSet.Scores;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
@ -15,6 +14,7 @@ using osu.Game.Users;
using System.Collections.Generic;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets.Osu;
namespace osu.Game.Tests.Visual
@ -22,9 +22,9 @@ namespace osu.Game.Tests.Visual
[System.ComponentModel.Description("in BeatmapOverlay")]
public class TestCaseBeatmapScoresContainer : OsuTestCase
{
private readonly IEnumerable<OnlineScore> scores;
private readonly IEnumerable<OnlineScore> anotherScores;
private readonly OnlineScore topScore;
private readonly IEnumerable<APIScore> scores;
private readonly IEnumerable<APIScore> anotherScores;
private readonly APIScore topScore;
private readonly Box background;
public TestCaseBeatmapScoresContainer()
@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual
scores = new[]
{
new OnlineScore
new APIScore
{
User = new User
{
@ -80,7 +80,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234567890,
Accuracy = 1,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234789,
Accuracy = 0.9997,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 12345678,
Accuracy = 0.9854,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -143,7 +143,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234567,
Accuracy = 0.8765,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -169,7 +169,7 @@ namespace osu.Game.Tests.Visual
anotherScores = new[]
{
new OnlineScore
new APIScore
{
User = new User
{
@ -191,7 +191,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234789,
Accuracy = 0.9997,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -214,7 +214,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234567890,
Accuracy = 1,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -230,7 +230,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 123456,
Accuracy = 0.6543,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -251,7 +251,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 12345678,
Accuracy = 0.9854,
},
new OnlineScore
new APIScore
{
User = new User
{
@ -279,7 +279,7 @@ namespace osu.Game.Tests.Visual
s.Statistics.Add(HitResult.Meh, RNG.Next(2000));
}
topScore = new OnlineScore
topScore = new APIScore
{
User = new User
{

View File

@ -12,6 +12,7 @@ using osu.Game.Overlays.Profile.Sections.Recent;
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Tests.Visual
{
@ -49,15 +50,15 @@ namespace osu.Game.Tests.Visual
};
}
private IEnumerable<RecentActivity> createDummyActivities()
private IEnumerable<APIRecentActivity> createDummyActivities()
{
var dummyBeatmap = new RecentActivity.RecentActivityBeatmap
var dummyBeatmap = new APIRecentActivity.RecentActivityBeatmap
{
Title = @"Dummy beatmap",
Url = "/b/1337",
};
var dummyUser = new RecentActivity.RecentActivityUser
var dummyUser = new APIRecentActivity.RecentActivityUser
{
Username = "DummyReborn",
Url = "/u/666",
@ -66,61 +67,61 @@ namespace osu.Game.Tests.Visual
return new[]
{
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.Achievement,
Achievement = new RecentActivity.RecentActivityAchievement
Achievement = new APIRecentActivity.RecentActivityAchievement
{
Name = @"Feelin' It",
Slug = @"all-secret-feelinit",
},
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.BeatmapPlaycount,
Count = 1337,
Beatmap = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.BeatmapsetApprove,
Approval = BeatmapApproval.Qualified,
Beatmapset = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.BeatmapsetDelete,
Beatmapset = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.BeatmapsetRevive,
Beatmapset = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.BeatmapsetRevive,
Beatmapset = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.BeatmapsetUpdate,
Beatmapset = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.BeatmapsetUpload,
Beatmapset = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.Rank,
@ -128,29 +129,29 @@ namespace osu.Game.Tests.Visual
Mode = "osu!",
Beatmap = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.RankLost,
Mode = "osu!",
Beatmap = dummyBeatmap,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.UsernameChange,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.UserSupportAgain,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.UserSupportFirst,
},
new RecentActivity
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.UserSupportGift,

View File

@ -5,6 +5,7 @@ using osu.Framework.Configuration;
using osu.Framework.Configuration.Tracking;
using osu.Framework.Platform;
using osu.Game.Overlays;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Select;
namespace osu.Game.Configuration
@ -80,6 +81,8 @@ namespace osu.Game.Configuration
Set(OsuSetting.FloatingComments, false);
Set(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised);
Set(OsuSetting.SpeedChangeVisualisation, SpeedChangeVisualisationMethod.Sequential);
Set(OsuSetting.IncreaseFirstObjectVisibility, true);
@ -147,6 +150,7 @@ namespace osu.Game.Configuration
SongSelectRightMouseScroll,
BeatmapSkins,
BeatmapHitsounds,
IncreaseFirstObjectVisibility
IncreaseFirstObjectVisibility,
ScoreDisplayMode
}
}

View File

@ -1,149 +0,0 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using System;
namespace osu.Game.Online.API.Requests
{
public class APIResponseBeatmapSet : BeatmapMetadata // todo: this is a bit wrong...
{
[JsonProperty(@"covers")]
private BeatmapSetOnlineCovers covers { get; set; }
[JsonProperty(@"preview_url")]
private string preview { get; set; }
[JsonProperty(@"play_count")]
private int playCount { get; set; }
[JsonProperty(@"favourite_count")]
private int favouriteCount { get; set; }
[JsonProperty(@"bpm")]
private double bpm { get; set; }
[JsonProperty(@"video")]
private bool hasVideo { get; set; }
[JsonProperty(@"storyboard")]
private bool hasStoryboard { get; set; }
[JsonProperty(@"status")]
private BeatmapSetOnlineStatus status { get; set; }
[JsonProperty(@"submitted_date")]
private DateTimeOffset submitted { get; set; }
[JsonProperty(@"ranked_date")]
private DateTimeOffset ranked { get; set; }
[JsonProperty(@"last_updated")]
private DateTimeOffset lastUpdated { get; set; }
[JsonProperty(@"user_id")]
private long creatorId {
set { Author.Id = value; }
}
[JsonProperty(@"beatmaps")]
private IEnumerable<APIResponseBeatmap> beatmaps { get; set; }
public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets)
{
return new BeatmapSetInfo
{
OnlineBeatmapSetID = OnlineBeatmapSetID,
Metadata = this,
OnlineInfo = new BeatmapSetOnlineInfo
{
Covers = covers,
Preview = preview,
PlayCount = playCount,
FavouriteCount = favouriteCount,
BPM = bpm,
Status = status,
HasVideo = hasVideo,
HasStoryboard = hasStoryboard,
Submitted = submitted,
Ranked = ranked,
LastUpdated = lastUpdated,
},
Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(),
};
}
private class APIResponseBeatmap : BeatmapMetadata
{
[JsonProperty(@"id")]
private int onlineBeatmapID { get; set; }
[JsonProperty(@"playcount")]
private int playCount { get; set; }
[JsonProperty(@"passcount")]
private int passCount { get; set; }
[JsonProperty(@"mode_int")]
private int ruleset { get; set; }
[JsonProperty(@"difficulty_rating")]
private double starDifficulty { get; set; }
[JsonProperty(@"drain")]
private float drainRate { get; set; }
[JsonProperty(@"cs")]
private float circleSize { get; set; }
[JsonProperty(@"ar")]
private float approachRate { get; set; }
[JsonProperty(@"accuracy")]
private float overallDifficulty { get; set; }
[JsonProperty(@"total_length")]
private double length { get; set; }
[JsonProperty(@"count_circles")]
private int circleCount { get; set; }
[JsonProperty(@"count_sliders")]
private int sliderCount { get; set; }
[JsonProperty(@"version")]
private string version { get; set; }
public BeatmapInfo ToBeatmap(RulesetStore rulesets)
{
return new BeatmapInfo
{
Metadata = this,
Ruleset = rulesets.GetRuleset(ruleset),
StarDifficulty = starDifficulty,
OnlineBeatmapID = onlineBeatmapID,
Version = version,
BaseDifficulty = new BeatmapDifficulty
{
DrainRate = drainRate,
CircleSize = circleSize,
ApproachRate = approachRate,
OverallDifficulty = overallDifficulty,
},
OnlineInfo = new BeatmapOnlineInfo
{
PlayCount = playCount,
PassCount = passCount,
Length = length,
CircleCount = circleCount,
SliderCount = sliderCount,
},
};
}
}
}
}

View File

@ -1,12 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetBeatmapDetailsRequest : APIRequest<GetBeatmapDetailsResponse>
public class GetBeatmapDetailsRequest : APIRequest<APIBeatmapMetrics>
{
private readonly BeatmapInfo beatmap;
@ -19,28 +19,4 @@ namespace osu.Game.Online.API.Requests
protected override string Target => $@"beatmaps/{lookupString}";
}
public class GetBeatmapDetailsResponse : 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

@ -1,9 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetBeatmapSetRequest : APIRequest<APIResponseBeatmapSet>
public class GetBeatmapSetRequest : APIRequest<APIBeatmapSet>
{
private readonly int id;
private readonly BeatmapSetLookupType type;

View File

@ -2,20 +2,15 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Users;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Select.Leaderboards;
using osu.Framework.IO.Network;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetScoresRequest : APIRequest<GetScoresResponse>
public class GetScoresRequest : APIRequest<APIScores>
{
private readonly BeatmapInfo beatmap;
private readonly LeaderboardScope scope;
@ -36,9 +31,9 @@ namespace osu.Game.Online.API.Requests
Success += onSuccess;
}
private void onSuccess(GetScoresResponse r)
private void onSuccess(APIScores r)
{
foreach (OnlineScore score in r.Scores)
foreach (APIScore score in r.Scores)
score.ApplyBeatmap(beatmap);
}
@ -55,112 +50,4 @@ namespace osu.Game.Online.API.Requests
protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}/scores";
}
public class GetScoresResponse
{
[JsonProperty(@"scores")]
public IEnumerable<OnlineScore> Scores;
}
public class OnlineScore : Score
{
[JsonProperty(@"score")]
private double totalScore
{
set { TotalScore = value; }
}
[JsonProperty(@"max_combo")]
private int maxCombo
{
set { MaxCombo = value; }
}
[JsonProperty(@"user")]
private User user
{
set { User = value; }
}
[JsonProperty(@"replay_data")]
private Replay replay
{
set { Replay = value; }
}
[JsonProperty(@"mode_int")]
public int OnlineRulesetID { get; set; }
[JsonProperty(@"score_id")]
private long onlineScoreID
{
set { OnlineScoreID = value; }
}
[JsonProperty(@"created_at")]
private DateTimeOffset date
{
set { Date = value; }
}
[JsonProperty(@"beatmap")]
private BeatmapInfo beatmap
{
set { Beatmap = value; }
}
[JsonProperty(@"beatmapset")]
private BeatmapMetadata metadata
{
set { Beatmap.Metadata = value; }
}
[JsonProperty(@"statistics")]
private Dictionary<string, object> jsonStats
{
set
{
foreach (var kvp in value)
{
HitResult newKey;
switch (kvp.Key)
{
case @"count_300":
newKey = HitResult.Great;
break;
case @"count_100":
newKey = HitResult.Good;
break;
case @"count_50":
newKey = HitResult.Meh;
break;
case @"count_miss":
newKey = HitResult.Miss;
break;
default:
continue;
}
Statistics.Add(newKey, kvp.Value);
}
}
}
[JsonProperty(@"mods")]
private string[] modStrings { get; set; }
public void ApplyBeatmap(BeatmapInfo beatmap)
{
Beatmap = beatmap;
ApplyRuleset(beatmap.Ruleset);
}
public void ApplyRuleset(RulesetInfo ruleset)
{
Ruleset = ruleset;
// Evaluate the mod string
Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.ShortenedName)).ToArray();
}
}
}

View File

@ -3,10 +3,11 @@
using Humanizer;
using System.Collections.Generic;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetUserBeatmapsRequest : APIRequest<List<APIResponseBeatmapSet>>
public class GetUserBeatmapsRequest : APIRequest<List<APIBeatmapSet>>
{
private readonly long userId;
private readonly int offset;

View File

@ -1,14 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using System.Collections.Generic;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetUserMostPlayedBeatmapsRequest : APIRequest<List<MostPlayedBeatmap>>
public class GetUserMostPlayedBeatmapsRequest : APIRequest<List<APIUserMostPlayedBeatmap>>
{
private readonly long userId;
private readonly int offset;
@ -21,28 +19,4 @@ namespace osu.Game.Online.API.Requests
protected override string Target => $@"users/{userId}/beatmapsets/most_played?offset={offset}";
}
public class MostPlayedBeatmap
{
[JsonProperty("beatmap_id")]
public int BeatmapID;
[JsonProperty("count")]
public int PlayCount;
[JsonProperty]
private BeatmapInfo beatmap;
[JsonProperty]
private APIResponseBeatmapSet beatmapSet;
public BeatmapInfo GetBeatmapInfo(RulesetStore rulesets)
{
BeatmapSetInfo setInfo = beatmapSet.ToBeatmapSet(rulesets);
beatmap.BeatmapSet = setInfo;
beatmap.OnlineBeatmapSetID = setInfo.OnlineBeatmapSetID;
beatmap.Metadata = setInfo.Metadata;
return beatmap;
}
}
}

View File

@ -1,15 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Game.Rulesets.Scoring;
using Humanizer;
using System;
using System.Collections.Generic;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetUserRecentActivitiesRequest : APIRequest<List<RecentActivity>>
public class GetUserRecentActivitiesRequest : APIRequest<List<APIRecentActivity>>
{
private readonly long userId;
private readonly int offset;
@ -23,86 +20,6 @@ namespace osu.Game.Online.API.Requests
protected override string Target => $"users/{userId}/recent_activity?offset={offset}";
}
public class RecentActivity
{
[JsonProperty("id")]
public int ID;
[JsonProperty("createdAt")]
public DateTimeOffset CreatedAt;
[JsonProperty]
private string type
{
set => Type = (RecentActivityType)Enum.Parse(typeof(RecentActivityType), value.Pascalize());
}
public RecentActivityType Type;
[JsonProperty]
private string scoreRank
{
set => ScoreRank = (ScoreRank)Enum.Parse(typeof(ScoreRank), value);
}
public ScoreRank ScoreRank;
[JsonProperty("rank")]
public int Rank;
[JsonProperty("approval")]
public BeatmapApproval Approval;
[JsonProperty("count")]
public int Count;
[JsonProperty("mode")]
public string Mode;
[JsonProperty("beatmap")]
public RecentActivityBeatmap Beatmap;
[JsonProperty("beatmapset")]
public RecentActivityBeatmap Beatmapset;
[JsonProperty("user")]
public RecentActivityUser User;
[JsonProperty("achievement")]
public RecentActivityAchievement Achievement;
public class RecentActivityBeatmap
{
[JsonProperty("title")]
public string Title;
[JsonProperty("url")]
public string Url;
}
public class RecentActivityUser
{
[JsonProperty("username")]
public string Username;
[JsonProperty("url")]
public string Url;
[JsonProperty("previousUsername")]
public string PreviousUsername;
}
public class RecentActivityAchievement
{
[JsonProperty("slug")]
public string Slug;
[JsonProperty("name")]
public string Name;
}
}
public enum RecentActivityType
{
Achievement,

View File

@ -2,10 +2,11 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetUserScoresRequest : APIRequest<List<OnlineScore>>
public class GetUserScoresRequest : APIRequest<List<APIScore>>
{
private readonly long userId;
private readonly ScoreType type;

View File

@ -2,19 +2,12 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Game.Users;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetUsersRequest : APIRequest<List<RankingEntry>>
public class GetUsersRequest : APIRequest<List<APIUser>>
{
protected override string Target => @"rankings/osu/performance";
}
public class RankingEntry
{
[JsonProperty]
public User User;
}
}

View File

@ -0,0 +1,78 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIBeatmap : BeatmapMetadata
{
[JsonProperty(@"id")]
private int onlineBeatmapID { get; set; }
[JsonProperty(@"playcount")]
private int playCount { get; set; }
[JsonProperty(@"passcount")]
private int passCount { get; set; }
[JsonProperty(@"mode_int")]
private int ruleset { get; set; }
[JsonProperty(@"difficulty_rating")]
private double starDifficulty { get; set; }
[JsonProperty(@"drain")]
private float drainRate { get; set; }
[JsonProperty(@"cs")]
private float circleSize { get; set; }
[JsonProperty(@"ar")]
private float approachRate { get; set; }
[JsonProperty(@"accuracy")]
private float overallDifficulty { get; set; }
[JsonProperty(@"total_length")]
private double length { get; set; }
[JsonProperty(@"count_circles")]
private int circleCount { get; set; }
[JsonProperty(@"count_sliders")]
private int sliderCount { get; set; }
[JsonProperty(@"version")]
private string version { get; set; }
public BeatmapInfo ToBeatmap(RulesetStore rulesets)
{
return new BeatmapInfo
{
Metadata = this,
Ruleset = rulesets.GetRuleset(ruleset),
StarDifficulty = starDifficulty,
OnlineBeatmapID = onlineBeatmapID,
Version = version,
BaseDifficulty = new BeatmapDifficulty
{
DrainRate = drainRate,
CircleSize = circleSize,
ApproachRate = approachRate,
OverallDifficulty = overallDifficulty,
},
OnlineInfo = new BeatmapOnlineInfo
{
PlayCount = playCount,
PassCount = passCount,
Length = length,
CircleCount = circleCount,
SliderCount = sliderCount,
},
};
}
}
}

View File

@ -0,0 +1,29 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
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

@ -0,0 +1,81 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIBeatmapSet : BeatmapMetadata // todo: this is a bit wrong...
{
[JsonProperty(@"covers")]
private BeatmapSetOnlineCovers covers { get; set; }
[JsonProperty(@"preview_url")]
private string preview { get; set; }
[JsonProperty(@"play_count")]
private int playCount { get; set; }
[JsonProperty(@"favourite_count")]
private int favouriteCount { get; set; }
[JsonProperty(@"bpm")]
private double bpm { get; set; }
[JsonProperty(@"video")]
private bool hasVideo { get; set; }
[JsonProperty(@"storyboard")]
private bool hasStoryboard { get; set; }
[JsonProperty(@"status")]
private BeatmapSetOnlineStatus status { get; set; }
[JsonProperty(@"submitted_date")]
private DateTimeOffset submitted { get; set; }
[JsonProperty(@"ranked_date")]
private DateTimeOffset ranked { get; set; }
[JsonProperty(@"last_updated")]
private DateTimeOffset lastUpdated { get; set; }
[JsonProperty(@"user_id")]
private long creatorId
{
set { Author.Id = value; }
}
[JsonProperty(@"beatmaps")]
private IEnumerable<APIBeatmap> beatmaps { get; set; }
public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets)
{
return new BeatmapSetInfo
{
OnlineBeatmapSetID = OnlineBeatmapSetID,
Metadata = this,
OnlineInfo = new BeatmapSetOnlineInfo
{
Covers = covers,
Preview = preview,
PlayCount = playCount,
FavouriteCount = favouriteCount,
BPM = bpm,
Status = status,
HasVideo = hasVideo,
HasStoryboard = hasStoryboard,
Submitted = submitted,
Ranked = ranked,
LastUpdated = lastUpdated,
},
Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(),
};
}
}
}

View File

@ -0,0 +1,89 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using Humanizer;
using Newtonsoft.Json;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIRecentActivity
{
[JsonProperty("id")]
public int ID;
[JsonProperty("createdAt")]
public DateTimeOffset CreatedAt;
[JsonProperty]
private string type
{
set => Type = (RecentActivityType)Enum.Parse(typeof(RecentActivityType), value.Pascalize());
}
public RecentActivityType Type;
[JsonProperty]
private string scoreRank
{
set => ScoreRank = (ScoreRank)Enum.Parse(typeof(ScoreRank), value);
}
public ScoreRank ScoreRank;
[JsonProperty("rank")]
public int Rank;
[JsonProperty("approval")]
public BeatmapApproval Approval;
[JsonProperty("count")]
public int Count;
[JsonProperty("mode")]
public string Mode;
[JsonProperty("beatmap")]
public RecentActivityBeatmap Beatmap;
[JsonProperty("beatmapset")]
public RecentActivityBeatmap Beatmapset;
[JsonProperty("user")]
public RecentActivityUser User;
[JsonProperty("achievement")]
public RecentActivityAchievement Achievement;
public class RecentActivityBeatmap
{
[JsonProperty("title")]
public string Title;
[JsonProperty("url")]
public string Url;
}
public class RecentActivityUser
{
[JsonProperty("username")]
public string Username;
[JsonProperty("url")]
public string Url;
[JsonProperty("previousUsername")]
public string PreviousUsername;
}
public class RecentActivityAchievement
{
[JsonProperty("slug")]
public string Slug;
[JsonProperty("name")]
public string Name;
}
}
}

View File

@ -0,0 +1,117 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
using osu.Game.Users;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIScore : Score
{
[JsonProperty(@"score")]
private double totalScore
{
set => TotalScore = value;
}
[JsonProperty(@"max_combo")]
private int maxCombo
{
set => MaxCombo = value;
}
[JsonProperty(@"user")]
private User user
{
set => User = value;
}
[JsonProperty(@"replay_data")]
private Replay replay
{
set => Replay = value;
}
[JsonProperty(@"mode_int")]
public int OnlineRulesetID { get; set; }
[JsonProperty(@"score_id")]
private long onlineScoreID
{
set => OnlineScoreID = value;
}
[JsonProperty(@"created_at")]
private DateTimeOffset date
{
set => Date = value;
}
[JsonProperty(@"beatmap")]
private BeatmapInfo beatmap
{
set => Beatmap = value;
}
[JsonProperty(@"beatmapset")]
private BeatmapMetadata metadata
{
set => Beatmap.Metadata = value;
}
[JsonProperty(@"statistics")]
private Dictionary<string, object> jsonStats
{
set
{
foreach (var kvp in value)
{
HitResult newKey;
switch (kvp.Key)
{
case @"count_300":
newKey = HitResult.Great;
break;
case @"count_100":
newKey = HitResult.Good;
break;
case @"count_50":
newKey = HitResult.Meh;
break;
case @"count_miss":
newKey = HitResult.Miss;
break;
default:
continue;
}
Statistics.Add(newKey, kvp.Value);
}
}
}
[JsonProperty(@"mods")]
private string[] modStrings { get; set; }
public void ApplyBeatmap(BeatmapInfo beatmap)
{
Beatmap = beatmap;
ApplyRuleset(beatmap.Ruleset);
}
public void ApplyRuleset(RulesetInfo ruleset)
{
Ruleset = ruleset;
// Evaluate the mod string
Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.ShortenedName)).ToArray();
}
}
}

View File

@ -0,0 +1,14 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using Newtonsoft.Json;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIScores
{
[JsonProperty(@"scores")]
public IEnumerable<APIScore> Scores;
}
}

View File

@ -0,0 +1,14 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Game.Users;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIUser
{
[JsonProperty]
public User User;
}
}

View File

@ -0,0 +1,33 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIUserMostPlayedBeatmap
{
[JsonProperty("beatmap_id")]
public int BeatmapID;
[JsonProperty("count")]
public int PlayCount;
[JsonProperty]
private BeatmapInfo beatmap;
[JsonProperty]
private APIBeatmapSet beatmapSet;
public BeatmapInfo GetBeatmapInfo(RulesetStore rulesets)
{
BeatmapSetInfo setInfo = beatmapSet.ToBeatmapSet(rulesets);
beatmap.BeatmapSet = setInfo;
beatmap.OnlineBeatmapSetID = setInfo.OnlineBeatmapSetID;
beatmap.Metadata = setInfo.Metadata;
return beatmap;
}
}
}

View File

@ -3,13 +3,14 @@
using System.Collections.Generic;
using System.ComponentModel;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Direct;
using osu.Game.Rulesets;
namespace osu.Game.Online.API.Requests
{
public class SearchBeatmapSetsRequest : APIRequest<IEnumerable<APIResponseBeatmapSet>>
public class SearchBeatmapSetsRequest : APIRequest<IEnumerable<APIBeatmapSet>>
{
private readonly string query;
private readonly RulesetInfo ruleset;

View File

@ -9,7 +9,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.Profile.Sections.Ranks;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
@ -26,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
private readonly Box background;
public DrawableScore(int index, OnlineScore score)
public DrawableScore(int index, APIScore score)
{
ScoreModsContainer modsContainer;

View File

@ -11,7 +11,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.Profile.Sections.Ranks;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
@ -42,8 +42,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
private readonly InfoColumn statistics;
private readonly ScoreModsContainer modsContainer;
private OnlineScore score;
public OnlineScore Score
private APIScore score;
public APIScore Score
{
get { return score; }
set

View File

@ -11,6 +11,7 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.BeatmapSet.Scores
{
@ -28,10 +29,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration);
}
private IEnumerable<OnlineScore> scores;
private IEnumerable<APIScore> scores;
private BeatmapInfo beatmap;
public IEnumerable<OnlineScore> Scores
public IEnumerable<APIScore> Scores
{
get { return scores; }
set

View File

@ -8,6 +8,7 @@ using osu.Game.Online.API.Requests;
using osu.Game.Users;
using System;
using System.Linq;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
@ -49,7 +50,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
MissingText.Hide();
foreach (OnlineScore score in scores)
foreach (APIScore score in scores)
{
DrawableProfileScore drawableScore;

View File

@ -8,6 +8,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Chat;
using osu.Game.Screens.Select.Leaderboards;
@ -17,11 +18,11 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
{
private APIAccess api;
private readonly RecentActivity activity;
private readonly APIRecentActivity activity;
private LinkFlowContainer content;
public DrawableRecentActivity(RecentActivity activity)
public DrawableRecentActivity(APIRecentActivity activity)
{
this.activity = activity;
}

View File

@ -6,6 +6,7 @@ using osu.Framework.Graphics;
using osu.Game.Online.API.Requests;
using osu.Game.Users;
using System.Linq;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Profile.Sections.Recent
{
@ -36,7 +37,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
MissingText.Hide();
foreach (RecentActivity activity in activities)
foreach (APIRecentActivity activity in activities)
{
ItemsContainer.Add(new DrawableRecentActivity(activity));
}

View File

@ -4,6 +4,7 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Configuration;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Overlays.Settings.Sections.Gameplay
{
@ -38,6 +39,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
LabelText = "Always show key overlay",
Bindable = config.GetBindable<bool>(OsuSetting.KeyOverlay)
},
new SettingsEnumDropdown<ScoringMode>
{
LabelText = "Score display mode",
Bindable = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode)
}
};
}
}

View File

@ -27,8 +27,7 @@ namespace osu.Game.Rulesets.Mods
public virtual void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
{
// todo: fix ordering of objects so we don't have to do this (#2740).
foreach (var d in drawables.Reverse().Skip(IncreaseFirstObjectVisibility ? 1 : 0))
foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility ? 1 : 0))
d.ApplyCustomUpdateState += ApplyHiddenState;
}

View File

@ -65,6 +65,11 @@ namespace osu.Game.Rulesets.Scoring
/// </summary>
public readonly BindableInt HighestCombo = new BindableInt();
/// <summary>
/// The <see cref="ScoringMode"/> used to calculate scores.
/// </summary>
public readonly Bindable<ScoringMode> Mode = new Bindable<ScoringMode>();
/// <summary>
/// Whether all <see cref="Judgement"/>s have been processed.
/// </summary>
@ -169,8 +174,6 @@ namespace osu.Game.Rulesets.Scoring
private const double combo_portion = 0.7;
private const double max_score = 1000000;
public readonly Bindable<ScoringMode> Mode = new Bindable<ScoringMode>();
protected sealed override bool HasCompleted => JudgedHits == MaxHits;
protected int MaxHits { get; private set; }
@ -199,16 +202,18 @@ namespace osu.Game.Rulesets.Scoring
if (maxBaseScore == 0 || maxHighestCombo == 0)
{
Mode.Value = ScoringMode.Exponential;
Mode.Value = ScoringMode.Classic;
Mode.Disabled = true;
}
Mode.ValueChanged += _ => updateScore();
}
/// <summary>
/// Simulates an autoplay of <see cref="HitObject"/>s that will be judged by this <see cref="ScoreProcessor{TObject}"/>
/// by adding <see cref="Judgement"/>s for each <see cref="HitObject"/> in the <see cref="Beatmap{TObject}"/>.
/// <para>
/// This is required for <see cref="ScoringMode.Standardised"/> to work, otherwise <see cref="ScoringMode.Exponential"/> will be used.
/// This is required for <see cref="ScoringMode.Standardised"/> to work, otherwise <see cref="ScoringMode.Classic"/> will be used.
/// </para>
/// </summary>
/// <param name="beatmap">The <see cref="Beatmap{TObject}"/> containing the <see cref="HitObject"/>s that will be judged by this <see cref="ScoreProcessor{TObject}"/>.</param>
@ -295,8 +300,9 @@ namespace osu.Game.Rulesets.Scoring
case ScoringMode.Standardised:
TotalScore.Value = max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore;
break;
case ScoringMode.Exponential:
TotalScore.Value = (baseScore + bonusScore) * Math.Log(HighestCombo + 1, 2);
case ScoringMode.Classic:
// should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1)
TotalScore.Value = bonusScore + baseScore * (1 + Math.Max(0, HighestCombo - 1) / 25);
break;
}
}
@ -322,6 +328,6 @@ namespace osu.Game.Rulesets.Scoring
public enum ScoringMode
{
Standardised,
Exponential
Classic
}
}

View File

@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.UI
{
public class HitObjectContainer : CompositeDrawable
{
public virtual IEnumerable<DrawableHitObject> Objects => InternalChildren.Cast<DrawableHitObject>();
public virtual IEnumerable<DrawableHitObject> AliveObjects => AliveInternalChildren.Cast<DrawableHitObject>();
public IEnumerable<DrawableHitObject> Objects => InternalChildren.Cast<DrawableHitObject>().OrderBy(h => h.HitObject.StartTime);
public IEnumerable<DrawableHitObject> AliveObjects => AliveInternalChildren.Cast<DrawableHitObject>().OrderBy(h => h.HitObject.StartTime);
public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject);
public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject);

View File

@ -158,6 +158,7 @@ namespace osu.Game.Screens.Play
userAudioOffset.TriggerChange();
ScoreProcessor = RulesetContainer.CreateScoreProcessor();
config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
Children = new Drawable[]
{