Skip to content

Commit 7c7bad5

Browse files
committed
Added FindPositionNearGivenTick and CalculateScore methods.
Added tests.
1 parent 0091c71 commit 7c7bad5

File tree

6 files changed

+214
-0
lines changed

6 files changed

+214
-0
lines changed

RhythmGameUtilities.Tests/UtilitiesTest.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,38 @@ public void TestCalculateBeatBars()
7373
Assert.That(beatBars.Count, Is.EqualTo(440));
7474
}
7575

76+
[Test]
77+
public void TestFindPositionNearGivenTick()
78+
{
79+
var notes = new List<Note>
80+
{
81+
new() { Position = 768 },
82+
new() { Position = 960 },
83+
new() { Position = 1152 },
84+
new() { Position = 1536 },
85+
new() { Position = 1728 },
86+
new() { Position = 1920 },
87+
new() { Position = 2304 },
88+
new() { Position = 2496 },
89+
new() { Position = 2688 },
90+
new() { Position = 3072 },
91+
new() { Position = 3264 },
92+
};
93+
94+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 100), Is.Null);
95+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 750), Is.Not.Null);
96+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 1500), Is.Not.Null);
97+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 3200), Is.Null);
98+
}
99+
100+
[Test]
101+
public void TestCalculateScore()
102+
{
103+
Assert.That(Utilities.CalculateScore(750, 100), Is.EqualTo(0));
104+
Assert.That(Utilities.CalculateScore(750, 750), Is.EqualTo(1));
105+
Assert.That(Utilities.CalculateScore(750, 725), Is.EqualTo(0.5f));
106+
}
107+
76108
}
77109

78110
}

RhythmGameUtilities/Scripts/Utilities.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ public static extern int ConvertSecondsToTicksInternal(float seconds, int resolu
4646
#endif
4747
public static extern int RoundUpToTheNearestMultiplier(int value, int multiplier);
4848

49+
#if WINDOWS_BUILD || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
50+
[DllImport("libRhythmGameUtilities.dll", CallingConvention = CallingConvention.Cdecl)]
51+
#elif MACOS_BUILD || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
52+
[DllImport("libRhythmGameUtilities.dylib", CallingConvention = CallingConvention.Cdecl)]
53+
#elif LINUX_BUILD || UNITY_EDITOR_LINUX || UNITY_STANDALONE_LINUX
54+
[DllImport("libRhythmGameUtilities.so", CallingConvention = CallingConvention.Cdecl)]
55+
#endif
56+
public static extern float CalculateScore(int position, int tickOffset, int delta);
57+
4958
#if WINDOWS_BUILD || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
5059
[DllImport("libRhythmGameUtilities.dll", CallingConvention = CallingConvention.Cdecl)]
5160
#elif MACOS_BUILD || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
@@ -107,6 +116,39 @@ public static List<BeatBar> CalculateBeatBars(Dictionary<int, int> bpmChanges, i
107116
return beatBars;
108117
}
109118

119+
public static Note? FindPositionNearGivenTick(List<Note> notes, int tick, int delta = 50)
120+
{
121+
var left = 0;
122+
var right = notes.Count - 1;
123+
124+
while (left <= right)
125+
{
126+
var mid = (left + right) / 2;
127+
128+
var currentPosition = notes[mid].Position;
129+
130+
if (currentPosition + delta < tick)
131+
{
132+
left = mid + 1;
133+
}
134+
else if (currentPosition - delta > tick)
135+
{
136+
right = mid - 1;
137+
}
138+
else
139+
{
140+
return notes[mid];
141+
}
142+
}
143+
144+
return null;
145+
}
146+
147+
public static float CalculateScore(int position, int tickOffset, int delta = 50)
148+
{
149+
return UtilitiesInternal.CalculateScore(position, tickOffset, delta);
150+
}
151+
110152
}
111153

112154
}

UnityPackage/Editor/Tests/UtilitiesTest.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,38 @@ public void TestCalculateBeatBars()
7373
Assert.That(beatBars.Count, Is.EqualTo(440));
7474
}
7575

76+
[Test]
77+
public void TestFindPositionNearGivenTick()
78+
{
79+
var notes = new List<Note>
80+
{
81+
new() { Position = 768 },
82+
new() { Position = 960 },
83+
new() { Position = 1152 },
84+
new() { Position = 1536 },
85+
new() { Position = 1728 },
86+
new() { Position = 1920 },
87+
new() { Position = 2304 },
88+
new() { Position = 2496 },
89+
new() { Position = 2688 },
90+
new() { Position = 3072 },
91+
new() { Position = 3264 },
92+
};
93+
94+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 100), Is.Null);
95+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 750), Is.Not.Null);
96+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 1500), Is.Not.Null);
97+
Assert.That(Utilities.FindPositionNearGivenTick(notes, 3200), Is.Null);
98+
}
99+
100+
[Test]
101+
public void TestCalculateScore()
102+
{
103+
Assert.That(Utilities.CalculateScore(750, 100), Is.EqualTo(0));
104+
Assert.That(Utilities.CalculateScore(750, 750), Is.EqualTo(1));
105+
Assert.That(Utilities.CalculateScore(750, 725), Is.EqualTo(0.5f));
106+
}
107+
76108
}
77109

78110
}

UnityPackage/Scripts/Utilities.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ public static extern int ConvertSecondsToTicksInternal(float seconds, int resolu
4646
#endif
4747
public static extern int RoundUpToTheNearestMultiplier(int value, int multiplier);
4848

49+
#if WINDOWS_BUILD || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
50+
[DllImport("libRhythmGameUtilities.dll", CallingConvention = CallingConvention.Cdecl)]
51+
#elif MACOS_BUILD || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
52+
[DllImport("libRhythmGameUtilities.dylib", CallingConvention = CallingConvention.Cdecl)]
53+
#elif LINUX_BUILD || UNITY_EDITOR_LINUX || UNITY_STANDALONE_LINUX
54+
[DllImport("libRhythmGameUtilities.so", CallingConvention = CallingConvention.Cdecl)]
55+
#endif
56+
public static extern float CalculateScore(int position, int tickOffset, int delta);
57+
4958
#if WINDOWS_BUILD || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
5059
[DllImport("libRhythmGameUtilities.dll", CallingConvention = CallingConvention.Cdecl)]
5160
#elif MACOS_BUILD || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
@@ -107,6 +116,39 @@ public static List<BeatBar> CalculateBeatBars(Dictionary<int, int> bpmChanges, i
107116
return beatBars;
108117
}
109118

119+
public static Note? FindPositionNearGivenTick(List<Note> notes, int tick, int delta = 50)
120+
{
121+
var left = 0;
122+
var right = notes.Count - 1;
123+
124+
while (left <= right)
125+
{
126+
var mid = (left + right) / 2;
127+
128+
var currentPosition = notes[mid].Position;
129+
130+
if (currentPosition + delta < tick)
131+
{
132+
left = mid + 1;
133+
}
134+
else if (currentPosition - delta > tick)
135+
{
136+
right = mid - 1;
137+
}
138+
else
139+
{
140+
return notes[mid];
141+
}
142+
}
143+
144+
return null;
145+
}
146+
147+
public static float CalculateScore(int position, int tickOffset, int delta = 50)
148+
{
149+
return UtilitiesInternal.CalculateScore(position, tickOffset, delta);
150+
}
151+
110152
}
111153

112154
}

includes/RhythmGameUtilities/Utilities.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <map>
55
#include <vector>
66

7+
#include "Common.hpp"
78
#include "Structs/BeatBar.h"
89
#include "Structs/Note.h"
910

@@ -110,6 +111,35 @@ std::vector<BeatBar> CalculateBeatBars(std::map<int, int> bpmChanges,
110111
return beatBars;
111112
}
112113

114+
std::optional<Note> FindPositionNearGivenTick(std::vector<Note> notes, int tick,
115+
int delta = 50)
116+
{
117+
auto left = 0;
118+
auto right = static_cast<int>(notes.size()) - 1;
119+
120+
while (left <= right)
121+
{
122+
auto mid = (left + right) / 2;
123+
124+
auto currentPosition = notes[mid].Position;
125+
126+
if (currentPosition + delta < tick)
127+
{
128+
left = mid + 1;
129+
}
130+
else if (currentPosition - delta > tick)
131+
{
132+
right = mid - 1;
133+
}
134+
else
135+
{
136+
return notes[mid];
137+
}
138+
}
139+
140+
return std::nullopt;
141+
}
142+
113143
extern "C"
114144
{
115145
/**
@@ -148,6 +178,16 @@ extern "C"
148178
{
149179
return (int)std::ceil((float)value / multiplier) * multiplier;
150180
}
181+
182+
PACKAGE_API float CalculateScore(int position, int tickOffset,
183+
int delta = 50)
184+
{
185+
auto diff = position - tickOffset;
186+
187+
auto ratio = InverseLerp(delta, 0, std::abs(diff));
188+
189+
return ratio;
190+
}
151191
}
152192

153193
} // namespace RhythmGameUtilities

tests/RhythmGameUtilities/Utilities.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,30 @@ void testIsOnTheBeat()
3434
std::cout << ".";
3535
}
3636

37+
void testFindPositionNearGivenTick()
38+
{
39+
std::vector<Note> notes = {{768, 0, 0}, {960, 0, 0}, {1152, 0, 0},
40+
{1536, 0, 0}, {1728, 0, 0}, {1920, 0, 0},
41+
{2304, 0, 0}, {2496, 0, 0}, {2688, 0, 0},
42+
{3072, 0, 0}, {3264, 0, 0}};
43+
44+
assert(std::nullopt == FindPositionNearGivenTick(notes, 100));
45+
assert(768 == FindPositionNearGivenTick(notes, 750)->Position);
46+
assert(1536 == FindPositionNearGivenTick(notes, 1500)->Position);
47+
assert(std::nullopt == FindPositionNearGivenTick(notes, 3200));
48+
49+
std::cout << ".";
50+
}
51+
52+
void testCalculateScore()
53+
{
54+
assert(0 == CalculateScore(750, 100));
55+
assert(1 == CalculateScore(750, 750));
56+
assert(0.5f == CalculateScore(750, 725));
57+
58+
std::cout << ".";
59+
}
60+
3761
void testRoundUpToTheNearestMultiplier()
3862
{
3963
assert(20 == RoundUpToTheNearestMultiplier(12, 10));
@@ -74,6 +98,8 @@ int main()
7498
testConvertTickToPosition();
7599
testConvertSecondsToTicks();
76100
testIsOnTheBeat();
101+
testFindPositionNearGivenTick();
102+
testCalculateScore();
77103
testRoundUpToTheNearestMultiplier();
78104
testGenerateAdjacentKeyPairs();
79105
testCalculateBeatBars();

0 commit comments

Comments
 (0)