Skip to content

Commit

Permalink
Merge pull request #14 from hongaaronc/unsnapped-last-note-hiding-bar…
Browse files Browse the repository at this point in the history
…line-check

Add check for unsnapped last note hiding bar line
  • Loading branch information
Hiviexd authored Oct 1, 2023
2 parents b165352 + 8a162f2 commit 0bd32bb
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 0 deletions.
102 changes: 102 additions & 0 deletions Checks/Compose/LastNoteHidingBarlineCheck.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System.Collections.Generic;
using System.Linq;

using MapsetParser.objects;
using MapsetParser.objects.hitobjects;
using MapsetParser.statics;

using MapsetVerifierFramework.objects;
using MapsetVerifierFramework.objects.attributes;
using MapsetVerifierFramework.objects.metadata;

using MVTaikoChecks.Utils;

using static MVTaikoChecks.Aliases.Mode;
using static MVTaikoChecks.Aliases.Level;

namespace MVTaikoChecks.Checks.Compose
{
[Check]
public class LastNoteHidingBarlineCheck : BeatmapCheck
{
private const string _MINOR = nameof(_MINOR);
private const string _PROBLEM = nameof(_PROBLEM);

public override CheckMetadata GetMetadata() =>
new BeatmapCheckMetadata()
{
Author = "Nostril",
Category = "Compose",
Message = "Unsnapped last note hiding barline",
Modes = new Beatmap.Mode[] { MODE_TAIKO },
Documentation = new Dictionary<string, string>()
{
{
"Purpose",
@"
Check if the last object in the beatmap is not 1ms earlier than a barline."
},
{
"Reasoning",
@"
This causes the last barline in the map to not be rendered."
}
}
};

public override Dictionary<string, IssueTemplate> GetTemplates() =>
new Dictionary<string, IssueTemplate>()
{
{
_MINOR,

new IssueTemplate(
LEVEL_MINOR,
"{0} Last spinner/slider end in the map is hiding its barline, due to being unsnapped 1ms early",
"timestamp - "
).WithCause("The spinner/slider end is unsnapped 1ms early.")
},
{
_PROBLEM,

new IssueTemplate(
LEVEL_PROBLEM,
"{0} Last note in the map is hiding its barline, due to being unsnapped 1ms early",
"timestamp - "
).WithCause("The note is unsnapped 1ms early.")
}
};

public override IEnumerable<Issue> GetIssues(Beatmap beatmap)
{
if (beatmap.hitObjects.Count == 0)
{
yield break;
}

var lastObject = beatmap.hitObjects.Last();

var unsnapFromLastBarline = lastObject.GetTailOffsetFromNextBarlineMs();

if (unsnapFromLastBarline > -2.0 && unsnapFromLastBarline <= -1.0)
{
if (lastObject is Circle)
{
yield return new Issue(
GetTemplate(_PROBLEM),
beatmap,
Timestamp.Get(lastObject.GetEndTime())
);
}
else
{
yield return new Issue(
GetTemplate(_MINOR),
beatmap,
Timestamp.Get(lastObject.GetEndTime())
);
}
}
}
}
}
10 changes: 10 additions & 0 deletions Utils/GeneralUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,15 @@ public static void AddRange<TKey, TValue>(this Dictionary<TKey, TValue> dictiona

public static T SafeGetIndex<T>(this List<T> collection, int index)
=> index < collection.Count ? collection[index] : default;

public static double TakeLowerAbsValue(double first, double second)
{
return Math.Abs(first) < Math.Abs(second) ? first : second;
}

public static double TakeHigherAbsValue(double first, double second)
{
return Math.Abs(first) > Math.Abs(second) ? first : second;
}
}
}
53 changes: 53 additions & 0 deletions Utils/TaikoUtils.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using MapsetParser.objects;
using MapsetParser.objects.hitobjects;
using MapsetParser.objects.timinglines;
using System;

using static MVTaikoChecks.Utils.GeneralUtils;

namespace MVTaikoChecks.Utils
{
public static class TaikoUtils
Expand Down Expand Up @@ -108,5 +111,55 @@ public static double GetPatternSpacingMs(this HitObject current)
// if in middle of pattern, pattern spacing is based on which side has the smaller snap divisor
return Math.Min(gapBeforeMs, gapAfterMs);
}

public static double GetHeadOffsetFromPrevBarlineMs(this HitObject current)
{
var timing = current.beatmap.GetTimingLine<UninheritedLine>(current.time);
var barlineGap = timing.msPerBeat * timing.meter;

return (current.time - timing.offset) % barlineGap;
}

public static double GetHeadOffsetFromNextBarlineMs(this HitObject current)
{
var timing = current.beatmap.GetTimingLine<UninheritedLine>(current.time);
var barlineGap = timing.msPerBeat * timing.meter;

var offsetFromNextImplicitBarline = ((current.time - timing.offset) % barlineGap) - barlineGap;
var nextPotentialRedLine = current.beatmap.GetTimingLine<UninheritedLine>(current.time + offsetFromNextImplicitBarline);
var offsetFromNextPotentialRedline = current.time - nextPotentialRedLine.offset;

return TakeLowerAbsValue(offsetFromNextImplicitBarline, offsetFromNextPotentialRedline);
}

public static double GetHeadOffsetFromNearestBarlineMs(this HitObject current)
{
return TakeLowerAbsValue(current.GetHeadOffsetFromPrevBarlineMs(), current.GetHeadOffsetFromNextBarlineMs());
}

public static double GetTailOffsetFromPrevBarlineMs(this HitObject current)
{
var timing = current.beatmap.GetTimingLine<UninheritedLine>(current.GetEndTime());
var barlineGap = timing.msPerBeat * timing.meter;

return (current.GetEndTime() - timing.offset) % barlineGap;
}

public static double GetTailOffsetFromNextBarlineMs(this HitObject current)
{
var timing = current.beatmap.GetTimingLine<UninheritedLine>(current.GetEndTime());
var barlineGap = timing.msPerBeat * timing.meter;

var offsetFromNextImplicitBarline = ((current.GetEndTime() - timing.offset) % barlineGap) - barlineGap;
var nextPotentialRedLine = current.beatmap.GetTimingLine<UninheritedLine>(current.GetEndTime() + offsetFromNextImplicitBarline);
var offsetFromNextPotentialRedline = current.GetEndTime() - nextPotentialRedLine.offset;

return TakeLowerAbsValue(offsetFromNextImplicitBarline, offsetFromNextPotentialRedline);
}

public static double GetTailOffsetFromNearestBarlineMs(this HitObject current)
{
return TakeLowerAbsValue(current.GetTailOffsetFromPrevBarlineMs(), current.GetTailOffsetFromNextBarlineMs());
}
}
}

0 comments on commit 0bd32bb

Please sign in to comment.