Skip to content

Commit 16ad0d0

Browse files
committed
[T] 给MA2转Simai测试中,对生成的simai,增加“时间标记应当符合某种标准规定语法”的断言。
(cherry picked from commit 54315f4)
1 parent 1d5e454 commit 16ad0d0

2 files changed

Lines changed: 68 additions & 36 deletions

File tree

tests/mai/MA2转Simai测试.cs

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ private void TestChart(TestInput c)
3838
var expectedTimeline = SimaiCommaTimeline.Flatten(inote);
3939
var actualTimeline = SimaiCommaTimeline.Flatten(simai);
4040
SimaiCommaTimeline.AssertTimelineEqual(expectedTimeline, actualTimeline, chart, _output);
41+
42+
// 转出来的simai,重新parse一次、确保没有任何错误
43+
var (_, alertsReparsed) = new SimaiParser(strictLevel: SimaiParser.StrictLevelEnum.Strict).Parse(simai);
44+
Assert.Empty(alertsReparsed);
4145
}
4246
}
4347

@@ -110,8 +114,8 @@ static IEnumerable<Entry> Canon(IReadOnlyList<Entry> e) =>
110114

111115
private static void AssertNoteEqual(string expected, string actual, int noteIdx, Rational time, MaiChart chart)
112116
{
113-
var expArr = RearrangeNote(expected).Split('/', '`');
114-
var actArr = RearrangeNote(actual).Split('/', '`');
117+
var expArr = RearrangeNote(expected).Split('/', '`', '*');
118+
var actArr = RearrangeNote(actual).Split('/', '`', '*');
115119
var max = Math.Max(expArr.Length, actArr.Length);
116120

117121
for (var i = 0; i < max; i++)
@@ -126,36 +130,7 @@ private static void AssertNoteEqual(string expected, string actual, int noteIdx,
126130
result = exp == act;
127131
}
128132

129-
if (!result)
130-
{
131-
// 尝试是否是只有时间不匹配,如果是的话,允许一定的阈值
132-
var expTime = DurationStrRegex().Match(exp);
133-
var actTime = DurationStrRegex().Match(act);
134-
var bpm = chart.BpmList.Find(time).Bpm;
135-
if (expTime.Groups[2].Success && actTime.Groups[4].Success)
136-
{ // exp中是分数时间、act中是小数时间的情况
137-
// 小数时间化为分数时间,看看是否对的上
138-
var numer = decimal.Parse(actTime.Groups[4].Value) / (240 / bpm) * int.Parse(expTime.Groups[2].Value);
139-
if (Math.Round(numer) == int.Parse(expTime.Groups[3].Value)) result = true; // 如果对的上,则不判定为比较失败
140-
}
141-
else if (actTime.Groups[2].Success && expTime.Groups[4].Success)
142-
{ // exp中是小数时间、act中是分数时间的情况
143-
// 分数时间化为小数时间,看是否对的上(差距<1ms)
144-
var sec = new Rational(int.Parse(actTime.Groups[3].Value), int.Parse(actTime.Groups[2].Value)) * (240 / (Rational)bpm);
145-
if (Near((double)sec, double.Parse(expTime.Groups[4].Value))) result = true; // 如果对的上,则不判定为比较失败
146-
}
147-
else if (actTime.Groups[4].Success && expTime.Groups[4].Success)
148-
{ // exp中是小数时间、act中是小数时间的情况
149-
var expSec = double.Parse(expTime.Groups[4].Value);
150-
var actSec = double.Parse(actTime.Groups[4].Value);
151-
if (Near(expSec, actSec)) result = true; // 如果对的上,则不判定为比较失败
152-
}
153-
154-
// 比较等待时间是否相等(没显式写出的就是1拍)
155-
var expWait = expTime.Groups[1].Success ? double.Parse(expTime.Groups[1].Value) : 60 / (double)bpm;
156-
var actWait = actTime.Groups[1].Success ? double.Parse(actTime.Groups[1].Value) : 60 / (double)bpm;
157-
if (!Near(expWait, actWait)) result = false; // 如果等待时间对不上,则仍判定为比较失败
158-
}
133+
if (!result) result = CompareDurationStr(exp, act, time, chart);
159134

160135
if (!result) Assert.Fail(
161136
$"First difference at Notation {noteIdx + 1} (time {time}):{Environment.NewLine}" +
@@ -165,6 +140,61 @@ private static void AssertNoteEqual(string expected, string actual, int noteIdx,
165140
}
166141
}
167142

143+
private static bool CompareDurationStr(string exp, string act, Rational time, MaiChart chart)
144+
{
145+
bool result = false;
146+
// 尝试是否是只有时间不匹配,如果是的话,允许一定的阈值
147+
var expTime = DurationStrRegex().Match(exp);
148+
var actTime = DurationStrRegex().Match(act);
149+
if (!expTime.Success || !actTime.Success) return result;
150+
var expRemain = exp[..expTime.Index] + exp[(expTime.Index + expTime.Length)..];
151+
var actRemain = act[..expTime.Index] + act[(actTime.Index + actTime.Length)..];
152+
if (actRemain != expRemain) return result; // 如果除了时间以外还有其他不一样的,那么直接返回false
153+
154+
// 对act产生的时间标记,做规范性检查。对齐到标准中的每一条
155+
if (actRemain.Contains('h'))
156+
{ // Hold / TouchHold
157+
Assert.False(actTime.Groups[1].Success, $"Hold/TouchHold不应该有等待时间!{act}");
158+
if (actTime.Groups[4].Success)
159+
{ // 绝对时长的情况
160+
Assert.True(act[actTime.Groups[4].Index - 1] == '#', $"Hold/TouchHold格式不正确,绝对时长的前面必须带一个井号!{act}");
161+
}
162+
}
163+
else
164+
{
165+
if (actTime.Groups[4].Success)
166+
{ // 绝对时长的情况,前面必须是'bpm#'或'等待时间##'。我们不考虑前面一种情况,则应该断言一定是第二种情况出现了
167+
Assert.True(actTime.Groups[1].Success && actTime.Groups[1].Index + actTime.Groups[1].Length == actTime.Groups[4].Index, $"星星持续时长使用了非标准语法!{act}");
168+
}
169+
}
170+
171+
var bpm = chart.BpmList.Find(time).Bpm;
172+
if (expTime.Groups[2].Success && actTime.Groups[4].Success)
173+
{ // exp中是分数时间、act中是小数时间的情况
174+
// 小数时间化为分数时间,看看是否对的上
175+
var numer = decimal.Parse(actTime.Groups[4].Value) / (240 / bpm) * int.Parse(expTime.Groups[2].Value);
176+
if (Math.Round(numer) == int.Parse(expTime.Groups[3].Value)) result = true; // 如果对的上,则不判定为比较失败
177+
}
178+
else if (actTime.Groups[2].Success && expTime.Groups[4].Success)
179+
{ // exp中是小数时间、act中是分数时间的情况
180+
// 分数时间化为小数时间,看是否对的上(差距<1ms)
181+
var sec = new Rational(int.Parse(actTime.Groups[3].Value), int.Parse(actTime.Groups[2].Value)) * (240 / (Rational)bpm);
182+
if (Near((double)sec, double.Parse(expTime.Groups[4].Value))) result = true; // 如果对的上,则不判定为比较失败
183+
}
184+
else if (actTime.Groups[4].Success && expTime.Groups[4].Success)
185+
{ // exp中是小数时间、act中是小数时间的情况
186+
var expSec = double.Parse(expTime.Groups[4].Value);
187+
var actSec = double.Parse(actTime.Groups[4].Value);
188+
if (Near(expSec, actSec)) result = true; // 如果对的上,则不判定为比较失败
189+
}
190+
191+
// 比较等待时间是否相等(没显式写出的就是1拍)
192+
var expWait = expTime.Groups[1].Success ? double.Parse(expTime.Groups[1].Value) : 60 / (double)bpm;
193+
var actWait = actTime.Groups[1].Success ? double.Parse(actTime.Groups[1].Value) : 60 / (double)bpm;
194+
if (!Near(expWait, actWait)) result = false; // 如果等待时间对不上,则仍判定为比较失败
195+
return result;
196+
}
197+
168198
private static string RearrangeNote(string s)
169199
{
170200
return string.Join('`', s.Split('`').Select(x =>

tests/mai/Simai转MA2测试.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ private void TestChart(TestInput input)
3030
_output.WriteLine(string.Join('\n', alerts));
3131
_output.WriteLine(string.Join('\n', alerts2));
3232

33-
Assert.Equal(maidata.ClockCount * 96, TestUtils.TryParseMa2ClkDef(ma2));
34-
ma2 = KeepNotesOnly(ma2);
35-
expectedMa2 = KeepNotesOnly(expectedMa2);
36-
AssertTextEqual(expectedMa2, ma2);
33+
Assert.Equal(maidata.ClockCount * 96, TryParseMa2ClkDef(ma2));
34+
AssertTextEqual(KeepNotesOnly(expectedMa2), KeepNotesOnly(ma2));
35+
36+
// 转出来的MA2,重新parse一次、确保没有任何错误
37+
var (_, alertsReparsed) = new MA2Parser().Parse(ma2);
38+
Assert.Empty(alertsReparsed);
3739
}
3840

3941
private static (int, int, string) GetSlideTime(string slide)

0 commit comments

Comments
 (0)