From 27920408dab36919785d16e4b7886245bdec1e1d Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 27 May 2026 17:53:14 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E5=BD=93=E9=81=87=E5=88=B0=E7=89=A9?= =?UTF-8?q?=E9=87=8F=E4=B8=BA0=E7=9A=84=E8=B0=B1=E9=9D=A2=E6=97=B6?= =?UTF-8?q?=E4=BC=9A=E6=8A=9B=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Charts/ImportChartController.cs | 20 +++++++++++-------- .../Charts/Services/MaidataImportService.cs | 12 ++++++++--- MaiChartManager/Locale.Designer.cs | 9 +++++++++ MaiChartManager/Locale.resx | 3 +++ MaiChartManager/Locale.zh-hans.resx | 3 +++ MaiChartManager/Locale.zh-hant.resx | 3 +++ MuConvert | 2 +- 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/MaiChartManager/Controllers/Charts/ImportChartController.cs b/MaiChartManager/Controllers/Charts/ImportChartController.cs index 186c5dc..fc90352 100644 --- a/MaiChartManager/Controllers/Charts/ImportChartController.cs +++ b/MaiChartManager/Controllers/Charts/ImportChartController.cs @@ -76,13 +76,6 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file, [FromForm] bool i } # endregion - if (targetLevelMap.Count == 0) // 没有能够被映射的谱面 - { - errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal)); - fatal = true; - return new ImportChartCheckResult(!fatal, errors, new Dictionary(), false, title, 0, null); - } - var first = maiData.First; var isDx = false; List resultCharts = []; @@ -118,8 +111,13 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file, [FromForm] bool i { // ↓ 此处的参数应该不会影响 check 的结果 var (chart, alerts1) = new SimaiParser(false, maiData.ClockCount).Parse(data.Inote); - resultCharts.Add(chart); alerts.AddRange(alerts1); + if (chart.TotalNotes == 0) + { + errors.Add(new ImportChartMessage(string.Format(Locale.ChartNoNotes, lv), MessageLevel.Warning)); + continue; + } + resultCharts.Add(chart); var (_, alerts2) = new MA2Generator().Generate(chart); alerts.AddRange(alerts2); isDx = isDx || chart.IsDxChart; @@ -135,6 +133,12 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file, [FromForm] bool i if (m != null) errors.Add(m); } } + + if (resultCharts.Count == 0) // 没有解析成功的谱面 + { + errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal)); + fatal = true; + } Dictionary chartPaddingsSec = new(); if (!fatal && resultCharts.Count > 0) diff --git a/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs b/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs index 82b3dc0..da03a70 100644 --- a/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs +++ b/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs @@ -192,7 +192,7 @@ public ImportChartResult ImportMaidata( } // 先执行第一步:Parser,因为可能涉及对Chart做出调整 - List<(int lv, int targetLevel, MaidataLevel data, MaiChart chart, List alerts)> parserOutput = []; + List<(int lv, int targetLevel, MaidataLevel data, MaiChart? chart, List alerts)> parserOutput = []; foreach (var (lv, data) in maiData.Levels) { if (!targetLevelMap.ContainsKey(lv)) continue; @@ -204,17 +204,22 @@ public ImportChartResult ImportMaidata( { var parser = new SimaiParser(!isUtage && lv is 2 or 3, maiData.ClockCount); var (chart, alerts) = parser.Parse(data.Inote); + if (chart.TotalNotes == 0) + { + errors.Add(new ImportChartMessage(string.Format(Locale.ChartNoNotes, lv), MessageLevel.Warning)); + chart = null; + } parserOutput.Add((lv, targetLevel, data, chart, alerts)); } catch (ConversionException e) { - parserOutput.Add((lv, targetLevel, data, null!, e.Alerts)); + parserOutput.Add((lv, targetLevel, data, null, e.Alerts)); MergeAlertsIntoImportChartMessages(); return new ImportChartResult(errors, true); } } - var chartPaddingDict = CalcChartPadding(parserOutput.Select(x=>x.chart).ToList()); + var chartPaddingDict = CalcChartPadding(parserOutput.Where(x=>x.chart != null).Select(x=>x.chart!).ToList()); var chartPadding = chartPaddingDict[shift]; // 当前所选择的模式所具体对应的chartPadding foreach (var c in music.Charts) { c.Enable = false; } // 先把所有难度标记为关闭(马上后面"第二步"的逻辑,会对存在的难度打开) @@ -223,6 +228,7 @@ public ImportChartResult ImportMaidata( // 再执行第二步 foreach (var (lv, targetLevel, data, chart, alerts) in parserOutput) { + if (chart == null) continue; var targetChart = music.Charts[targetLevel]; targetChart.Path = $"{id:000000}_0{targetLevel}.ma2"; diff --git a/MaiChartManager/Locale.Designer.cs b/MaiChartManager/Locale.Designer.cs index 4d05054..5eb7b54 100644 --- a/MaiChartManager/Locale.Designer.cs +++ b/MaiChartManager/Locale.Designer.cs @@ -214,6 +214,15 @@ internal static string ChartMaiLibParseError { } } + /// + /// Looks up a localized string similar to Chart difficulty {0} has no notes. This difficulty will not be imported.. + /// + internal static string ChartNoNotes { + get { + return ResourceManager.GetString("ChartNoNotes", resourceCulture); + } + } + /// /// Looks up a localized string similar to It looks like some notes were lost! This is likely a bug. We'd really appreciate it if you could provide the chart file!. /// diff --git a/MaiChartManager/Locale.resx b/MaiChartManager/Locale.resx index e2c2e0d..d16b23f 100644 --- a/MaiChartManager/Locale.resx +++ b/MaiChartManager/Locale.resx @@ -206,6 +206,9 @@ If you notice any issues with the conversion result, you can try testing it in A Failed to parse chart difficulty {0} + + + Chart difficulty {0} has no notes. This difficulty will not be imported. Chart parsing failed (global) diff --git a/MaiChartManager/Locale.zh-hans.resx b/MaiChartManager/Locale.zh-hans.resx index 721d3a6..5fde1bf 100644 --- a/MaiChartManager/Locale.zh-hans.resx +++ b/MaiChartManager/Locale.zh-hans.resx @@ -198,6 +198,9 @@ 谱面难度 {0} 解析失败 + + + 谱面难度 {0} 中没有音符。将不会导入此难度。 谱面解析失败(大) diff --git a/MaiChartManager/Locale.zh-hant.resx b/MaiChartManager/Locale.zh-hant.resx index 5f3b3bb..4d7ea64 100644 --- a/MaiChartManager/Locale.zh-hant.resx +++ b/MaiChartManager/Locale.zh-hant.resx @@ -198,6 +198,9 @@ 譜面難度 {0} 解析失敗 + + + 譜面難度 {0} 中沒有音符。將不會匯入此難度。 譜面解析失敗(大) diff --git a/MuConvert b/MuConvert index 7dbc2a0..578c749 160000 --- a/MuConvert +++ b/MuConvert @@ -1 +1 @@ -Subproject commit 7dbc2a00947528b82f1ce273f186b400007dae03 +Subproject commit 578c749153ab9d1fa4bc9fbce2ee38df0f996cd6 From 8653457118c15c3a2324e12932c733bb7191640e Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 27 May 2026 17:59:32 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=E5=B8=B8=E8=A7=84=E8=B0=B1=E9=9D=A2?= =?UTF-8?q?=E9=81=87=E5=88=B0=E8=AF=B8=E5=A6=8213=3F=E8=BF=99=E7=A7=8D?= =?UTF-8?q?=E7=AD=89=E7=BA=A7=E4=B9=9F=E4=BC=9A=E6=97=A0=E6=B3=95=E8=A7=A3?= =?UTF-8?q?=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Charts/Services/MaidataImportService.cs | 16 ++--------- MaiChartManager/Utils/MaiUtils.cs | 28 +++++++++++++++++-- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs b/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs index da03a70..3d55618 100644 --- a/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs +++ b/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs @@ -1,4 +1,4 @@ -using MaiChartManager.Models; +using MaiChartManager.Models; using MaiChartManager.Utils; using MuConvert.mai; using MuConvert.utils; @@ -233,18 +233,8 @@ public ImportChartResult ImportMaidata( targetChart.Path = $"{id:000000}_0{targetLevel}.ma2"; #region 计算等级(定数)相关 - var levelNumStr = data.Level; - if (!string.IsNullOrWhiteSpace(levelNumStr)) - { - if (isUtage && !char.IsDigit(levelNumStr[0])) - { - music.UtageKanji = levelNumStr.Substring(0, 1); - levelNumStr = levelNumStr.Substring(1).Replace("?", ""); // 为了处理类似“奏13+?”这种情况,留下13+给后面的逻辑处理 - } - levelNumStr = levelNumStr.Replace("+", ".7"); - } - - float.TryParse(levelNumStr, out var levelNum); + MaiUtils.ParseLevelStr(data.Level, out var levelNum, out var utageKanji); + if (isUtage) music.UtageKanji = utageKanji; targetChart.LevelId = MaiUtils.GetLevelId((int)(levelNum * 10)); // 忽略定数 if (!ignoreLevelNum) diff --git a/MaiChartManager/Utils/MaiUtils.cs b/MaiChartManager/Utils/MaiUtils.cs index d8a1101..ee3db4e 100644 --- a/MaiChartManager/Utils/MaiUtils.cs +++ b/MaiChartManager/Utils/MaiUtils.cs @@ -1,7 +1,31 @@ -namespace MaiChartManager.Utils; +using System.Text.RegularExpressions; -public static class MaiUtils +namespace MaiChartManager.Utils; + +public static partial class MaiUtils { + [GeneratedRegex(@"^-?\d+(\.\d+)?")] + private static partial Regex LeadingFloatRegex(); + + // 尝试解析字符串开头的浮点数部分,忽略后续无法解析的字符(如 "13?" -> 13)。 + public static bool ParseLevelStr(string? input, out float value, out string utageKanji) + { + utageKanji = ""; + value = 0; + if (string.IsNullOrEmpty(input)) return false; + + if (!char.IsDigit(input[0])) + { // 如果不以数字开头,说明是utageKanji的情况 + utageKanji = input.Substring(0, 1); + input = input.Substring(1); + } + input = input.Replace("+", ".7"); + + var match = LeadingFloatRegex().Match(input); // 结尾有可能会有一个?,或者是其他的什么东西。为了让这些东西不要影响处理,所以通过正则匹配开头的数字部分,不然如果直接送进float.TryParse的话,类似"13?"这种的就解析不出来、返回false了。 + if (!match.Success) return false; + return float.TryParse(match.Value, System.Globalization.CultureInfo.InvariantCulture, out value); + } + public static int GetLevelId(int levelX10) { return levelX10 switch From dc6e5e5633591eb5e440bd01d2885d2f4e50d192 Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 27 May 2026 20:38:56 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8B=A5=E5=B9=B2?= =?UTF-8?q?=E5=B0=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Charts/ImportChartController.cs | 2 +- .../Charts/Services/MaidataImportService.cs | 13 +++++++------ MaiChartManager/Utils/MaiUtils.cs | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/MaiChartManager/Controllers/Charts/ImportChartController.cs b/MaiChartManager/Controllers/Charts/ImportChartController.cs index fc90352..b065440 100644 --- a/MaiChartManager/Controllers/Charts/ImportChartController.cs +++ b/MaiChartManager/Controllers/Charts/ImportChartController.cs @@ -134,7 +134,7 @@ public ImportChartCheckResult ImportChartCheck(IFormFile file, [FromForm] bool i } } - if (resultCharts.Count == 0) // 没有解析成功的谱面 + if ((StaticSettings.Config.UseLegacyMaiLib ? legacyCharts.Count : resultCharts.Count) == 0) // 没有解析成功的谱面 { errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal)); fatal = true; diff --git a/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs b/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs index 3d55618..695f666 100644 --- a/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs +++ b/MaiChartManager/Controllers/Charts/Services/MaidataImportService.cs @@ -185,11 +185,6 @@ public ImportChartResult ImportMaidata( var lineNoDict = GetLevelLineNo(maiDataText); var targetLevelMap = MapMaidataLevelToGame(maiData); - if (targetLevelMap.Count == 0) // 没有能够被映射的谱面 - { - errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal)); - return new ImportChartResult(errors, true); - } // 先执行第一步:Parser,因为可能涉及对Chart做出调整 List<(int lv, int targetLevel, MaidataLevel data, MaiChart? chart, List alerts)> parserOutput = []; @@ -219,7 +214,13 @@ public ImportChartResult ImportMaidata( } } - var chartPaddingDict = CalcChartPadding(parserOutput.Where(x=>x.chart != null).Select(x=>x.chart!).ToList()); + var validCharts = parserOutput.Where(x=> x.chart != null).Select(x => x.chart!).ToList(); + if (validCharts.Count == 0) + { + errors.Add(new ImportChartMessage(Locale.MusicNoCharts, MessageLevel.Fatal)); + return new ImportChartResult(errors, true); + } + var chartPaddingDict = CalcChartPadding(validCharts); var chartPadding = chartPaddingDict[shift]; // 当前所选择的模式所具体对应的chartPadding foreach (var c in music.Charts) { c.Enable = false; } // 先把所有难度标记为关闭(马上后面"第二步"的逻辑,会对存在的难度打开) diff --git a/MaiChartManager/Utils/MaiUtils.cs b/MaiChartManager/Utils/MaiUtils.cs index ee3db4e..ebe7638 100644 --- a/MaiChartManager/Utils/MaiUtils.cs +++ b/MaiChartManager/Utils/MaiUtils.cs @@ -12,7 +12,8 @@ public static bool ParseLevelStr(string? input, out float value, out string utag { utageKanji = ""; value = 0; - if (string.IsNullOrEmpty(input)) return false; + input = input?.Trim(); + if (string.IsNullOrWhiteSpace(input)) return false; if (!char.IsDigit(input[0])) { // 如果不以数字开头,说明是utageKanji的情况