1- using MaiLib ;
1+ using System . Text . RegularExpressions ;
2+ using MaiLib ;
23using Microsoft . AspNetCore . Mvc ;
34using SimaiSharp ;
45using SimaiSharp . Structures ;
@@ -8,7 +9,7 @@ namespace MaiChartManager.Controllers;
89
910[ ApiController ]
1011[ Route ( "MaiChartManagerServlet/[action]Api" ) ]
11- public class ImportChartController ( StaticSettings settings , ILogger < StaticSettings > logger ) : ControllerBase
12+ public partial class ImportChartController ( StaticSettings settings , ILogger < StaticSettings > logger ) : ControllerBase
1213{
1314 public enum MessageLevel
1415 {
@@ -130,6 +131,11 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file)
130131
131132 public record ImportChartResult ( IEnumerable < ImportChartMessage > Errors , bool Fatal ) ;
132133
134+ private record AllChartsEntry ( string chartText , MaiChart simaiSharpChart ) ;
135+
136+ [ GeneratedRegex ( @"\|\|.*$" , RegexOptions . Multiline ) ]
137+ private static partial Regex SimaiCommentRegex ( ) ;
138+
133139 [ HttpPost ]
134140 // 创建完 Music 后调用
135141 public ImportChartResult ImportChart ( [ FromForm ] int id , IFormFile file , [ FromForm ] bool ignoreLevelNum , [ FromForm ] int addVersionId , [ FromForm ] int genreId , [ FromForm ] int version ,
@@ -140,26 +146,26 @@ public ImportChartResult ImportChart([FromForm] int id, IFormFile file, [FromFor
140146 var music = settings . MusicList . First ( it => it . Id == id ) ;
141147 var maiData = new Dictionary < string , string > ( new SimaiFile ( file . OpenReadStream ( ) ) . ToKeyValuePairs ( ) ) ;
142148
143- var allCharts = new Dictionary < int , MaiChart > ( ) ;
149+ var allCharts = new Dictionary < int , AllChartsEntry > ( ) ;
144150 for ( var i = 2 ; i < 9 ; i ++ )
145151 {
146152 if ( ! string . IsNullOrWhiteSpace ( maiData . GetValueOrDefault ( $ "inote_{ i } ") ) )
147153 {
148- allCharts . Add ( i , SimaiConvert . Deserialize ( maiData [ $ "inote_{ i } "] ) ) ;
154+ allCharts . Add ( i , new AllChartsEntry ( maiData [ $ "inote_ { i } " ] , SimaiConvert . Deserialize ( maiData [ $ "inote_{ i } "] ) ) ) ;
149155 }
150156 }
151157
152158 if ( ! string . IsNullOrWhiteSpace ( maiData . GetValueOrDefault ( "inote_0" ) ) )
153159 {
154- allCharts . Add ( 0 , SimaiConvert . Deserialize ( maiData [ "inote_0" ] ) ) ;
160+ allCharts . Add ( 0 , new AllChartsEntry ( maiData [ "inote_0" ] , SimaiConvert . Deserialize ( maiData [ "inote_0" ] ) ) ) ;
155161 }
156162
157163 float . TryParse ( maiData . GetValueOrDefault ( "first" ) , out var first ) ;
158164
159165 float chartPadding = 0 ;
160166 if ( ! noShiftChart )
161167 {
162- var paddings = allCharts . Values . Select ( chart => Converter . CalcMusicPadding ( chart , first ) ) . ToList ( ) ;
168+ var paddings = allCharts . Values . Select ( chart => Converter . CalcMusicPadding ( chart . simaiSharpChart , first ) ) . ToList ( ) ;
163169 // 音频前面被增加了多少
164170 var audioPadding = paddings . Max ( ) ;
165171 // 见下方注释
@@ -172,7 +178,7 @@ public ImportChartResult ImportChart([FromForm] int id, IFormFile file, [FromFor
172178 if ( isUtage && music . Charts [ 0 ] . Enable ) break ;
173179
174180 // var levelPadding = Converter.CalcMusicPadding(chart, first);
175- var bpm = chart . TimingChanges [ 0 ] . tempo ;
181+ var bpm = chart . simaiSharpChart . TimingChanges [ 0 ] . tempo ;
176182 music . Bpm = ( int ) Math . Floor ( bpm ) ;
177183 // 一个小节多少秒
178184 var bar = 60 / bpm * 4 ;
@@ -242,12 +248,54 @@ public ImportChartResult ImportChart([FromForm] int id, IFormFile file, [FromFor
242248 }
243249
244250 targetChart . Designer = maiData . GetValueOrDefault ( $ "des_{ level } ") ?? maiData . GetValueOrDefault ( "des" ) ?? "" ;
245- var maiLibChart = simaiParser . ChartOfToken ( simaiTokenizer . TokensFromText ( SimaiConvert . Serialize ( chart ) ) ) ;
251+ Chart maiLibChart = null ;
252+ try
253+ {
254+ maiLibChart = simaiParser . ChartOfToken ( simaiTokenizer . TokensFromText ( chart . chartText ) ) ;
255+ }
256+ catch ( Exception e )
257+ {
258+ logger . LogWarning ( e , "无法直接解析谱面" ) ;
259+ }
260+
261+ if ( maiLibChart is null )
262+ {
263+ try
264+ {
265+ var normalizedText = chart . chartText
266+ // 不飞的星星
267+ . Replace ( "-?" , "?-" ) ;
268+ // 移除注释
269+ normalizedText = SimaiCommentRegex ( ) . Replace ( normalizedText , "" ) ;
270+ var tokens = simaiTokenizer . TokensFromText ( normalizedText ) ;
271+ for ( var i = 0 ; i < tokens . Length ; i ++ )
272+ {
273+ if ( tokens [ i ] . Contains ( "]b" ) )
274+ {
275+ tokens [ i ] = tokens [ i ] . Replace ( "]b" , "]" ) . Replace ( "[" , "b[" ) ;
276+ }
277+ }
278+
279+ maiLibChart = simaiParser . ChartOfToken ( tokens ) ;
280+ }
281+ catch ( Exception e )
282+ {
283+ logger . LogWarning ( e , "无法在手动修正错误后解析谱面" ) ;
284+ }
285+ }
286+
287+ if ( maiLibChart is null )
288+ {
289+ maiLibChart = simaiParser . ChartOfToken ( simaiTokenizer . TokensFromText ( SimaiConvert . Serialize ( chart . simaiSharpChart ) ) ) ;
290+ errors . Add ( new ImportChartMessage ( "就算修正了一些已知错误,MaiLib 还是无法解析谱面,我们尝试通过 AstroDX 的 SimaiSharp 解析。" +
291+ "如果转换结果发现有什么问题的话,可以试试在 AstroDX 中有没有同样的问题并告诉我们(不试也没关系)" , MessageLevel . Warning ) ) ;
292+ }
293+
246294 var originalConverted = maiLibChart . Compose ( ChartEnum . ChartVersion . Ma2_104 ) ;
247295
248296 if ( debug )
249297 {
250- System . IO . File . WriteAllText ( Path . Combine ( Path . GetDirectoryName ( music . FilePath ) , targetChart . Path + ".afterSimaiSharp.txt" ) , SimaiConvert . Serialize ( chart ) ) ;
298+ System . IO . File . WriteAllText ( Path . Combine ( Path . GetDirectoryName ( music . FilePath ) , targetChart . Path + ".afterSimaiSharp.txt" ) , SimaiConvert . Serialize ( chart . simaiSharpChart ) ) ;
251299 System . IO . File . WriteAllText ( Path . Combine ( Path . GetDirectoryName ( music . FilePath ) , targetChart . Path + ".preShift.ma2" ) , originalConverted ) ;
252300 System . IO . File . WriteAllText ( Path . Combine ( Path . GetDirectoryName ( music . FilePath ) , targetChart . Path + ".preShift.txt" ) , maiLibChart . Compose ( ChartEnum . ChartVersion . SimaiFes ) ) ;
253301 }
0 commit comments