Skip to content

Commit 12e4481

Browse files
committed
[F] [SimaiParser] 对1-4[160#2]的正确解析
之前的逻辑实现有问题,看到`context.number()`(2)时,就会忽略`context.asBpm()`部分的内容,导致产生错误的结果。
1 parent 3350aea commit 12e4481

4 files changed

Lines changed: 43 additions & 14 deletions

File tree

parser/mai/SimaiParser.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,11 @@ public sealed override object VisitSlideDuration(P.SlideDurationContext context)
520520
{
521521
var result = new Duration(currNote!);
522522
Duration? waitTime = null;
523-
isRealExactWaitTime = false;
523+
isRealExactWaitTime = false; // 是否通过##,指定了绝对的等待时间值
524+
Rational? anotherBpm = null; // 是否通过类似 160#8:3,指定了显式的BPM,且和当前的实际BPM不同
524525
AlertIfMoreParentheses(context._lp, context._rp);
525526

527+
// 解析绝对的等待时间
526528
if (context.waitTime() != null)
527529
{
528530
waitTime = new Duration(currNote!)
@@ -531,19 +533,26 @@ public sealed override object VisitSlideDuration(P.SlideDurationContext context)
531533
};
532534
isRealExactWaitTime = true;
533535
}
536+
537+
// 解析显式的BPM
538+
if (context.asBpm() != null)
539+
{
540+
var currentBpm = chart.BpmList.Last().Bpm;
541+
var bpm = (decimal)VisitNumber(context.asBpm().number());
542+
if (bpm != currentBpm)
543+
{
544+
anotherBpm = (Rational)bpm;
545+
if (waitTime == null) // 如果未显式指定绝对的waitTime秒数,则waitTime也要变成该强行指定的bpm下的一拍。不然默认就是currentBpm下的一拍了。
546+
waitTime = new Duration(currNote!) { Seconds = 60 / anotherBpm.Value };
547+
}
548+
}
549+
534550
if (context.number() != null) result.Seconds = (Rational)(decimal)VisitNumber(context.number());
535551
else
536552
{
537553
var value = (Rational)VisitBeats(context.beats());
538-
if (context.asBpm() == null) result.InvariantBar = value;
539-
else
540-
{
541-
// 根据强行指定的bpm换算为秒数
542-
var bpm = (Rational)(decimal)VisitNumber(context.asBpm().number());
543-
result.Seconds = value * (240 / bpm);
544-
// 如果未显式指定waitTime,则waitTime也要变成强行指定的bpm下的一拍。不然就是音符所在时刻下的一拍了。
545-
waitTime ??= new Duration(currNote!) { Seconds = 60 / bpm };
546-
}
554+
if (anotherBpm == null) result.InvariantBar = value;
555+
else result.Seconds = value * (240 / anotherBpm.Value); // 显式指定了bpm的情况,需要根据强行指定的bpm换算为秒数
547556
}
548557
return (waitTime, result);
549558
}

tests/mai/MA2转Simai测试.cs

Lines changed: 4 additions & 0 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

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)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
simai: "(120){2}1-4[8:3],1-4[160#8:3],1-4[160#2],1-4[3##1.5],1-4[3##8:3],1-4[3##160#8:3],"
2+
ma2: |
3+
NMSTR 0 0 0
4+
NMSI_ 0 0 0 96 144 3
5+
NMSTR 0 192 0
6+
NMSI_ 0 192 0 72 108 3
7+
NMSTR 1 0 0
8+
NMSI_ 1 0 0 72 384 3
9+
NMSTR 1 192 0
10+
NMSI_ 1 192 0 576 288 3
11+
NMSTR 2 0 0
12+
NMSI_ 2 0 0 576 144 3
13+
NMSTR 2 192 0
14+
NMSI_ 2 192 0 576 108 3

0 commit comments

Comments
 (0)