Skip to content

Commit

Permalink
enhance: 将Updater中的更新过程独立出来
Browse files Browse the repository at this point in the history
    * 优化可维护性...大概吧
  • Loading branch information
MATRIX-feather committed Feb 25, 2024
1 parent 9ff421a commit 87b68dd
Show file tree
Hide file tree
Showing 15 changed files with 910 additions and 558 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
<PackageReference Include="ppy.osu.Game.Rulesets.Osu" Version="2024.221.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IGPlayerLoader\IGPlayerLoader.csproj" />
Expand Down
13 changes: 13 additions & 0 deletions osu.Game.Rulesets.IGPlayer/Feature/Gosumemory/Data/Menu/BMData.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Newtonsoft.Json;
using osu.Framework.Graphics.Audio;
using osu.Game.Beatmaps;
Expand Down Expand Up @@ -53,13 +54,25 @@ public void UpdateBeatmap(WorkingBeatmap beatmap)
this.MetaData.Mapper = metadata.Author.Username;
this.MetaData.DiffName = beatmap.BeatmapInfo.DifficultyName;

//todo: 适应Mod变更
var diffInf = beatmap.BeatmapInfo.Difficulty;
this.Stats.AR = diffInf.ApproachRate;
this.Stats.CS = diffInf.CircleSize;
this.Stats.HP = diffInf.DrainRate;
this.Stats.OD = diffInf.OverallDifficulty;
this.Stats.SR = (float)beatmap.BeatmapInfo.StarRating;

this.Stats.BPM.Max = (int)Math.Round(beatmap.Beatmap.ControlPointInfo.BPMMaximum);
this.Stats.BPM.Max = (int)Math.Round(beatmap.Beatmap.ControlPointInfo.BPMMinimum);

this.Path.AudioPath = "~ NOT IMPLEMENTED ~";
this.Path.BackgroundPath = "~ NOT IMPLEMENTED ~";
this.Path.BeatmapFile = "~ NOT IMPLEMENTED ~";
this.Path.BgPath = "~ NOT IMPLEMENTED ~";
this.Path.BeatmapFolder = "~ NOT IMPLEMENTED ~";

this.Stats.MaxCombo = -1;

short rankingStatus;

switch (beatmap.BeatmapInfo.Status)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Rulesets.Mods;

namespace osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Data.Menu
{
Expand All @@ -12,18 +9,5 @@ public struct MenuModsData

[JsonProperty("str")]
public string Acronyms;

public void UpdateFrom(IReadOnlyList<Mod> mods)
{
this.AppliedMods = mods.Count;

if (mods.Count >= 1)
{
string str = mods.Aggregate("", (current, mod) => current + $"{mod.Acronym}");
this.Acronyms = str;
}
else
this.Acronyms = "NM";
}
}
}
6 changes: 6 additions & 0 deletions osu.Game.Rulesets.IGPlayer/Feature/Gosumemory/Data/Root.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Framework.Graphics.Audio;
using osu.Game.Beatmaps;
Expand All @@ -7,6 +8,7 @@
using osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Data.Results;
using osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Data.Settings;
using osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Data.Tourney;
using osu.Game.Rulesets.Mods;

namespace osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Data
{
Expand All @@ -28,6 +30,10 @@ public class DataRoot : ISelfUpdatableFromBeatmap, ISelfUpdatableFromAudio
[JsonProperty("tourney")]
public TourneyValues TourneyValues = new TourneyValues();

public void ApplyMods(IList<Mod> mods)
{
}

public void UpdateBeatmap(WorkingBeatmap workingBeatmap)
{
MenuValues.UpdateBeatmap(workingBeatmap);
Expand Down
29 changes: 19 additions & 10 deletions osu.Game.Rulesets.IGPlayer/Feature/Gosumemory/GosuCompatInjector.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Web;
using osuTK;

namespace osu.Game.Rulesets.IGPlayer.Feature.Gosumemory
{
public partial class GosuCompatInjector : Component
{
public static Updater? Updater { get; private set; }
public TrackerHub? Updater { get; private set; }

private Container getContainerFromGame(string containerName, OsuGame game)
{
Expand All @@ -33,38 +34,46 @@ private Container getContainerFromGame(string containerName, OsuGame game)

private void initializeUpdater()
{
if (game == null)
{
Logger.Log("OsuGame is null, returning...");
return;
}

var children = new Drawable[]
{
handler = new WsLoader
handler = new WebSocketLoader
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
},
Updater = new Updater(handler)
Updater = new TrackerHub(handler)
};

if (game != null)
{
var container = this.getContainerFromGame("mfosu Gosumemory compat container", game);
var container = this.getContainerFromGame("mfosu Gosumemory compat container", game);
container.AddRange(children);

if (container.Children.Count == 0)
container.AddRange(children);
}
Logger.Log("Added gosu compat!");
}

[BackgroundDependencyLoader]
private void load(OsuGame? game)
{
Logger.Log("Gosu compat injector!");

AlwaysPresent = true;

this.Anchor = Anchor.Centre;
this.Origin = Anchor.Centre;

this.RelativeSizeAxes = Axes.Both;
this.Size = new Vector2(0.6f);

Logger.Log($"Updater is {Updater}");
if (Updater == null)
initializeUpdater();
}

private WsLoader? handler;
private WebSocketLoader? handler;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Timing;
using osu.Game.Graphics.Sprites;

namespace osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Tracker;

public partial class AbstractTracker : CompositeDrawable
{
protected TrackerHub Hub { get; private set; }

public AbstractTracker(TrackerHub hub)
{
this.Hub = hub;
AlwaysPresent = true;

InternalChild = new OsuSpriteText
{
Text = $"{this}",
Margin = new MarginPadding(30)
};
}

[BackgroundDependencyLoader]
private void load()
{
this.Clock = new FramedClock(null, false);
}

public virtual void UpdateValues()
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Logging;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;

namespace osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Tracker;

/// <summary>
/// 计算pp/密度表
/// </summary>
public partial class BeatmapStrainTracker : AbstractTracker
{
public BeatmapStrainTracker(TrackerHub hub)
: base(hub)
{
}

private double invokeTime = 0d;
private WorkingBeatmap? beatmapOnInvoke;

private CancellationTokenSource? ppStrainCancellationTokenSource;

private bool scheduleStrainComputes;

private readonly Bindable<WorkingBeatmap> working = new Bindable<WorkingBeatmap>();

[BackgroundDependencyLoader]
private void load(Bindable<WorkingBeatmap> globalWorking)
{
this.working.BindTo(globalWorking);
}

protected override void LoadComplete()
{
base.LoadComplete();

working.BindValueChanged(e =>
{
this.UpdateStrain(e.NewValue);
});
}

protected override void Update()
{
if (scheduleStrainComputes && beatmapOnInvoke == working.Value)
UpdateStrain(this.working.Value);
}

public void UpdateStrain(WorkingBeatmap workingBeatmap)
{
this.invokeTime = Clock.CurrentTime;
beatmapOnInvoke = workingBeatmap;
scheduleStrainComputes = false;

ppStrainCancellationTokenSource?.Cancel();
ppStrainCancellationTokenSource = new CancellationTokenSource();

Task.Run(async () => await updateStrain(workingBeatmap), ppStrainCancellationTokenSource.Token)
.ContinueWith(task =>
{
if (!task.IsCompleted) return;

if (task.Exception != null)
{
Logging.LogError(task.Exception, "Error occurred while updating strain");
return;
}

this.Schedule(() =>
{
float[] result = task.GetResultSafely();
Hub.GetDataRoot().MenuValues.pp.Strains = result;
});
});
}

private Task<float[]> updateStrain(WorkingBeatmap workingBeatmap)
{
try
{
double length = workingBeatmap.Track.Length;

//WorkingBeatmap.TrackLoaded: true + WorkingBeatmap.Track.IsLoaded: false -> Track Length: 0
if (length <= 0)
{
//持续5秒都没有音频,可能已经损坏,清空分布
//todo: 没有音频的时候使用谱面长度来计算并更新分布和进度
if (Clock.CurrentTime - invokeTime >= 10 * 1000)
{
Hub.GetDataRoot().MenuValues.pp.Strains = new[] { 0f };

Logger.Log("谱面音频在10秒内都没有加载,将放弃计算物件分布...", level: LogLevel.Important);
return Task.FromResult(new[] { 0f });
}

scheduleStrainComputes = true;
return Task.FromResult(new [] { 0f });
}

scheduleStrainComputes = false;

// 最大分段数和密度缩放
int maximumSegments = 512;
double segmentScale = 1;

// 根据歌曲长度分段,总共分为 (歌曲总时间(秒) * segScale) 段
int targetSegments = (int)(TimeSpan.FromMilliseconds(length).TotalSeconds * segmentScale);

// 限制最大分段数量
targetSegments = Math.Min(maximumSegments, targetSegments);
if (targetSegments <= 0) targetSegments = 1;

// 尝试自动转谱
var converter = workingBeatmap.BeatmapInfo.Ruleset.CreateInstance().CreateBeatmapConverter(workingBeatmap.Beatmap);
IBeatmap? beatmap = null;

//Logger.Log($"Track length: {length} ~ Segments {targetSegments} ~ Conv? {converter.CanConvert()} ~ Loaded? {workingBeatmap.Track.IsLoaded} ~ Track? {workingBeatmap.Track}");
if (converter.CanConvert()) beatmap = converter.Convert();
var hitObjects = beatmap?.HitObjects ?? new HitObject[] { };

//获取每段的音频跨度
double audioStep = length / targetSegments;

//Segment -> Count
var segments = new Dictionary<int, float>();

for (int i = 0; i < targetSegments; i++)
{
//此段的音频跨度
double startTime = i * audioStep;
double endTime = (1 + i) * audioStep;

//将跨度内的所有物件添加进来
//o -> [startTime, endTime)
int count = hitObjects.Count(o => o.StartTime < endTime && o.StartTime >= startTime);

segments.TryAdd(i, count);
}

//最后将其返回
return Task.FromResult(segments.Values.ToArray());
}
catch (Exception e)
{
return Task.FromException<float[]>(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Logging;
using osu.Game.Beatmaps;

namespace osu.Game.Rulesets.IGPlayer.Feature.Gosumemory.Tracker;

public partial class BeatmapTracker : AbstractTracker
{
public BeatmapTracker(TrackerHub hub)
: base(hub)
{
}

private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();

[BackgroundDependencyLoader]
private void load(Bindable<WorkingBeatmap> globalBeatmap)
{
this.beatmap.BindTo(globalBeatmap);
}

protected override void LoadComplete()
{
Logger.Log("DDDLOADCOMPLETE");
base.LoadComplete();

this.beatmap.BindValueChanged(e =>
{
this.onBeatmapChanged(e.NewValue);
}, true);
}

private void onBeatmapChanged(WorkingBeatmap newBeatmap)
{
Hub.GetDataRoot().UpdateBeatmap(newBeatmap);
}
}
Loading

0 comments on commit 87b68dd

Please sign in to comment.