Skip to content

Commit 54315f4

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

1 file changed

Lines changed: 58 additions & 32 deletions

File tree

tests/mai/MA2转Simai测试.cs

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ static IEnumerable<Entry> Canon(IReadOnlyList<Entry> e) =>
114114

115115
private static void AssertNoteEqual(string expected, string actual, int noteIdx, Rational time, MaiChart chart)
116116
{
117-
var expArr = RearrangeNote(expected).Split('/', '`');
118-
var actArr = RearrangeNote(actual).Split('/', '`');
117+
var expArr = RearrangeNote(expected).Split('/', '`', '*');
118+
var actArr = RearrangeNote(actual).Split('/', '`', '*');
119119
var max = Math.Max(expArr.Length, actArr.Length);
120120

121121
for (var i = 0; i < max; i++)
@@ -130,36 +130,7 @@ private static void AssertNoteEqual(string expected, string actual, int noteIdx,
130130
result = exp == act;
131131
}
132132

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

164135
if (!result) Assert.Fail(
165136
$"First difference at Notation {noteIdx + 1} (time {time}):{Environment.NewLine}" +
@@ -169,6 +140,61 @@ private static void AssertNoteEqual(string expected, string actual, int noteIdx,
169140
}
170141
}
171142

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+
172198
private static string RearrangeNote(string s)
173199
{
174200
return string.Join('`', s.Split('`').Select(x =>

0 commit comments

Comments
 (0)