Skip to content

Commit 9640b73

Browse files
authored
fix: 当遇到物量为0的谱面时会抛异常,和优化生成levelId的逻辑 (#67)
* fix: 当遇到物量为0的谱面时会抛异常 * fix: 常规谱面遇到诸如13?这种等级也会无法解析 * fix: 修复若干小问题
1 parent c4b0647 commit 9640b73

8 files changed

Lines changed: 76 additions & 32 deletions

File tree

MaiChartManager/Controllers/Charts/ImportChartController.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,6 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file, [FromForm] bool i
7676
}
7777
# endregion
7878

79-
if (targetLevelMap.Count == 0) // 没有能够被映射的谱面
80-
{
81-
errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal));
82-
fatal = true;
83-
return new ImportChartCheckResult(!fatal, errors, new Dictionary<ShiftMethod, float>(), false, title, 0, null);
84-
}
85-
8679
var first = maiData.First;
8780
var isDx = false;
8881
List<MaiChart> resultCharts = [];
@@ -118,8 +111,13 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file, [FromForm] bool i
118111
{
119112
// ↓ 此处的参数应该不会影响 check 的结果
120113
var (chart, alerts1) = new SimaiParser(false, maiData.ClockCount).Parse(data.Inote);
121-
resultCharts.Add(chart);
122114
alerts.AddRange(alerts1);
115+
if (chart.TotalNotes == 0)
116+
{
117+
errors.Add(new ImportChartMessage(string.Format(Locale.ChartNoNotes, lv), MessageLevel.Warning));
118+
continue;
119+
}
120+
resultCharts.Add(chart);
123121
var (_, alerts2) = new MA2Generator().Generate(chart);
124122
alerts.AddRange(alerts2);
125123
isDx = isDx || chart.IsDxChart;
@@ -135,6 +133,12 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file, [FromForm] bool i
135133
if (m != null) errors.Add(m);
136134
}
137135
}
136+
137+
if ((StaticSettings.Config.UseLegacyMaiLib ? legacyCharts.Count : resultCharts.Count) == 0) // 没有解析成功的谱面
138+
{
139+
errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal));
140+
fatal = true;
141+
}
138142

139143
Dictionary<ShiftMethod, float> chartPaddingsSec = new();
140144
if (!fatal && resultCharts.Count > 0)

MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using MaiChartManager.Models;
1+
using MaiChartManager.Models;
22
using MaiChartManager.Utils;
33
using MuConvert.mai;
44
using MuConvert.utils;
@@ -185,14 +185,9 @@ public ImportChartResult ImportMaidata(
185185
var lineNoDict = GetLevelLineNo(maiDataText);
186186

187187
var targetLevelMap = MapMaidataLevelToGame(maiData);
188-
if (targetLevelMap.Count == 0) // 没有能够被映射的谱面
189-
{
190-
errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal));
191-
return new ImportChartResult(errors, true);
192-
}
193188

194189
// 先执行第一步:Parser,因为可能涉及对Chart做出调整
195-
List<(int lv, int targetLevel, MaidataLevel data, MaiChart chart, List<Alert> alerts)> parserOutput = [];
190+
List<(int lv, int targetLevel, MaidataLevel data, MaiChart? chart, List<Alert> alerts)> parserOutput = [];
196191
foreach (var (lv, data) in maiData.Levels)
197192
{
198193
if (!targetLevelMap.ContainsKey(lv)) continue;
@@ -204,17 +199,28 @@ public ImportChartResult ImportMaidata(
204199
{
205200
var parser = new SimaiParser(!isUtage && lv is 2 or 3, maiData.ClockCount);
206201
var (chart, alerts) = parser.Parse(data.Inote);
202+
if (chart.TotalNotes == 0)
203+
{
204+
errors.Add(new ImportChartMessage(string.Format(Locale.ChartNoNotes, lv), MessageLevel.Warning));
205+
chart = null;
206+
}
207207
parserOutput.Add((lv, targetLevel, data, chart, alerts));
208208
}
209209
catch (ConversionException e)
210210
{
211-
parserOutput.Add((lv, targetLevel, data, null!, e.Alerts));
211+
parserOutput.Add((lv, targetLevel, data, null, e.Alerts));
212212
MergeAlertsIntoImportChartMessages();
213213
return new ImportChartResult(errors, true);
214214
}
215215
}
216216

217-
var chartPaddingDict = CalcChartPadding(parserOutput.Select(x=>x.chart).ToList());
217+
var validCharts = parserOutput.Where(x=> x.chart != null).Select(x => x.chart!).ToList();
218+
if (validCharts.Count == 0)
219+
{
220+
errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal));
221+
return new ImportChartResult(errors, true);
222+
}
223+
var chartPaddingDict = CalcChartPadding(validCharts);
218224
var chartPadding = chartPaddingDict[shift]; // 当前所选择的模式所具体对应的chartPadding
219225

220226
foreach (var c in music.Charts) { c.Enable = false; } // 先把所有难度标记为关闭(马上后面"第二步"的逻辑,会对存在的难度打开)
@@ -223,22 +229,13 @@ public ImportChartResult ImportMaidata(
223229
// 再执行第二步
224230
foreach (var (lv, targetLevel, data, chart, alerts) in parserOutput)
225231
{
232+
if (chart == null) continue;
226233
var targetChart = music.Charts[targetLevel];
227234
targetChart.Path = $"{id:000000}_0{targetLevel}.ma2";
228235

229236
#region 计算等级(定数)相关
230-
var levelNumStr = data.Level;
231-
if (!string.IsNullOrWhiteSpace(levelNumStr))
232-
{
233-
if (isUtage && !char.IsDigit(levelNumStr[0]))
234-
{
235-
music.UtageKanji = levelNumStr.Substring(0, 1);
236-
levelNumStr = levelNumStr.Substring(1).Replace("?", ""); // 为了处理类似“奏13+?”这种情况,留下13+给后面的逻辑处理
237-
}
238-
levelNumStr = levelNumStr.Replace("+", ".7");
239-
}
240-
241-
float.TryParse(levelNumStr, out var levelNum);
237+
MaiUtils.ParseLevelStr(data.Level, out var levelNum, out var utageKanji);
238+
if (isUtage) music.UtageKanji = utageKanji;
242239
targetChart.LevelId = MaiUtils.GetLevelId((int)(levelNum * 10));
243240
// 忽略定数
244241
if (!ignoreLevelNum)

MaiChartManager/Locale.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MaiChartManager/Locale.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ If you notice any issues with the conversion result, you can try testing it in A
206206
</data>
207207
<data name="ChartDifficultyParseFailed" xml:space="preserve">
208208
<value>Failed to parse chart difficulty {0}</value>
209+
</data>
210+
<data name="ChartNoNotes" xml:space="preserve">
211+
<value>Chart difficulty {0} has no notes. This difficulty will not be imported.</value>
209212
</data>
210213
<data name="ChartParseFailedGlobal" xml:space="preserve">
211214
<value>Chart parsing failed (global)</value>

MaiChartManager/Locale.zh-hans.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@
198198
</data>
199199
<data name="ChartDifficultyParseFailed" xml:space="preserve">
200200
<value>谱面难度 {0} 解析失败</value>
201+
</data>
202+
<data name="ChartNoNotes" xml:space="preserve">
203+
<value>谱面难度 {0} 中没有音符。将不会导入此难度。</value>
201204
</data>
202205
<data name="ChartParseFailedGlobal" xml:space="preserve">
203206
<value>谱面解析失败(大)</value>

MaiChartManager/Locale.zh-hant.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@
198198
</data>
199199
<data name="ChartDifficultyParseFailed" xml:space="preserve">
200200
<value>譜面難度 {0} 解析失敗</value>
201+
</data>
202+
<data name="ChartNoNotes" xml:space="preserve">
203+
<value>譜面難度 {0} 中沒有音符。將不會匯入此難度。</value>
201204
</data>
202205
<data name="ChartParseFailedGlobal" xml:space="preserve">
203206
<value>譜面解析失敗(大)</value>

MaiChartManager/Utils/MaiUtils.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,32 @@
1-
namespace MaiChartManager.Utils;
1+
using System.Text.RegularExpressions;
22

3-
public static class MaiUtils
3+
namespace MaiChartManager.Utils;
4+
5+
public static partial class MaiUtils
46
{
7+
[GeneratedRegex(@"^-?\d+(\.\d+)?")]
8+
private static partial Regex LeadingFloatRegex();
9+
10+
// 尝试解析字符串开头的浮点数部分,忽略后续无法解析的字符(如 "13?" -> 13)。
11+
public static bool ParseLevelStr(string? input, out float value, out string utageKanji)
12+
{
13+
utageKanji = "";
14+
value = 0;
15+
input = input?.Trim();
16+
if (string.IsNullOrWhiteSpace(input)) return false;
17+
18+
if (!char.IsDigit(input[0]))
19+
{ // 如果不以数字开头,说明是utageKanji的情况
20+
utageKanji = input.Substring(0, 1);
21+
input = input.Substring(1);
22+
}
23+
input = input.Replace("+", ".7");
24+
25+
var match = LeadingFloatRegex().Match(input); // 结尾有可能会有一个?,或者是其他的什么东西。为了让这些东西不要影响处理,所以通过正则匹配开头的数字部分,不然如果直接送进float.TryParse的话,类似"13?"这种的就解析不出来、返回false了。
26+
if (!match.Success) return false;
27+
return float.TryParse(match.Value, System.Globalization.CultureInfo.InvariantCulture, out value);
28+
}
29+
530
public static int GetLevelId(int levelX10)
631
{
732
return levelX10 switch

MuConvert

0 commit comments

Comments
 (0)