Skip to content

Commit

Permalink
Attempt to make !timeleft a bit more accurate
Browse files Browse the repository at this point in the history
  • Loading branch information
matte-ek committed Sep 22, 2023
1 parent 7002545 commit 58bc340
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 3 deletions.
30 changes: 27 additions & 3 deletions BanchoMultiplayerBot/Behaviour/MapManagerBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ private void OnMatchStarted()
_lobby.UpdateSettings();
}

private void OnUserMessage(PlayerMessage msg)
private async void OnUserMessage(PlayerMessage msg)
{
if (msg.Content.ToLower().EndsWith("!r") || msg.Content.ToLower().StartsWith("!regulations"))
{
Expand Down Expand Up @@ -199,9 +199,32 @@ private void OnUserMessage(PlayerMessage msg)

if (msg.Content.ToLower().StartsWith("!timeleft") && _lobby.MultiplayerLobby.MatchInProgress)
{
var timeLeft = (_matchStartTime.Add(CurrentBeatmap.Length) - DateTime.Now).ToString(@"mm\:ss");
try
{
var finishTime = _matchStartTime.Add(CurrentBeatmap.Length);

// Add a few seconds to account for people loading/finishing the map
finishTime = finishTime.AddSeconds(15);

// If we know where the map starts, we can be a bit more clever and try to account for that.
// This obviously assumes that the players skip, and skip at around 50% of that time.
var beginSkipTime = await BeatmapParser.GetBeatmapStartTime(CurrentBeatmap.Id);
if (beginSkipTime != null)
{
finishTime = finishTime.Subtract(TimeSpan.FromSeconds(beginSkipTime.Value * 0.5));
}

msg.Reply($"Estimated time left of current map: {timeLeft}");
var timeLeft = (finishTime - DateTime.Now).ToString(@"mm\:ss");

msg.Reply($"Estimated time left of current map: {timeLeft}");

if (beginSkipTime == null)
Log.Information("Unable to get map begin time during !timeleft estimation.");
}
catch (Exception)
{
// ignored.
}
}
}

Expand Down Expand Up @@ -325,6 +348,7 @@ private async Task EnforceBeatmapLimits(BeatmapModel beatmap, MapValidator.MapSt
SetId = int.Parse(beatmap.BeatmapsetId ?? "0"),
Name = $"{beatmap.Artist} - {beatmap.Title}",
Length = TimeSpan.FromSeconds(int.Parse(beatmap.TotalLength ?? "0", CultureInfo.InvariantCulture)),
DrainLength = TimeSpan.FromSeconds(int.Parse(beatmap.HitLength ?? "0", CultureInfo.InvariantCulture)),
StarRating = float.Parse(beatmap.DifficultyRating ?? "0", CultureInfo.InvariantCulture)
};

Expand Down
2 changes: 2 additions & 0 deletions BanchoMultiplayerBot/Data/BeatmapInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class BeatmapInfo

public TimeSpan Length { get; set; }

public TimeSpan DrainLength { get; set; }

public float StarRating { get; set; }

}
50 changes: 50 additions & 0 deletions BanchoMultiplayerBot/Utilities/BeatmapParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace BanchoMultiplayerBot.Utilities;

public class BeatmapParser
{

// Attempt to find the first hit object in seconds, relies on the map being downloaded beforehand
public static async Task<int?> GetBeatmapStartTime(int beatmapId)
{
const string cacheDir = $"cache";
var beatmapFilePath = $"{cacheDir}/{beatmapId}.osu";

try
{
if (!File.Exists(beatmapFilePath))
{
return null;
}

var inHitObjectsSection = false;
foreach (var line in await File.ReadAllLinesAsync(beatmapFilePath))
{
if (!line.Any())
{
continue;
}

if (line.StartsWith("[HitObjects]"))
{
inHitObjectsSection = true;
continue;
}

if (!inHitObjectsSection)
{
continue;
}

return int.Parse(line.Split(',')[2]) / 1000;
}
}
catch (Exception)
{
// ignored
}

return null;
}


}

0 comments on commit 58bc340

Please sign in to comment.