Skip to content

Commit 825cd81

Browse files
authored
Merge pull request #63 from neogeek/feature/calculate-score-utilities
[feat] Added FindPositionNearGivenTick and CalculateScore methods.
2 parents d2823d3 + f6bf32c commit 825cd81

File tree

6 files changed

+215
-0
lines changed

6 files changed

+215
-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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
#include <cmath>
44
#include <map>
5+
#include <optional>
56
#include <vector>
67

8+
#include "Common.hpp"
79
#include "Structs/BeatBar.h"
810
#include "Structs/Note.h"
911

@@ -110,6 +112,35 @@ std::vector<BeatBar> CalculateBeatBars(std::map<int, int> bpmChanges,
110112
return beatBars;
111113
}
112114

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

153194
} // 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)