|
|
|
@ -1,434 +0,0 @@
@@ -1,434 +0,0 @@
|
|
|
|
|
import 'package:excel/excel.dart'; |
|
|
|
|
|
|
|
|
|
class ExcelDataAdjustmentService { |
|
|
|
|
static const Map<String, int> palaceDegreeAdjustments = { |
|
|
|
|
'子': 300, |
|
|
|
|
'丑': 270, |
|
|
|
|
'寅': 240, |
|
|
|
|
'卯': 210, |
|
|
|
|
'辰': 180, |
|
|
|
|
'巳': 150, |
|
|
|
|
'午': 120, |
|
|
|
|
'未': 90, |
|
|
|
|
'申': 60, |
|
|
|
|
'酉': 30, |
|
|
|
|
'戌': 0, |
|
|
|
|
'亥': 330, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// 星宿数据:度数范围到星宿名称的映射 |
|
|
|
|
static const List<Map<String, dynamic>> starConstellations = [ |
|
|
|
|
{'name': '娄', 'start': 34.342, 'end': 47.315}, // 34°20'32" -> 34.342°, 47°18'52" -> 47.315° |
|
|
|
|
{'name': '胃', 'start': 47.315, 'end': 59.795}, // 47°18'52" -> 47.315°, 59°47'43" -> 59.795° |
|
|
|
|
{'name': '昴', 'start': 59.795, 'end': 68.863}, // 59°47'43" -> 59.795°, 68°51'47" -> 68.863° |
|
|
|
|
{'name': '毕', 'start': 68.863, 'end': 84.063}, // 68°51'47" -> 68.863°, 84°03'48" -> 84.063° |
|
|
|
|
{'name': '觜', 'start': 84.063, 'end': 85.064}, // 84°03'48" -> 84.063°, 85°03'51" -> 85.064° |
|
|
|
|
{'name': '参', 'start': 85.064, 'end': 95.680}, // 85°03'51" -> 85.064°, 95°40'47" -> 95.680° |
|
|
|
|
{'name': '井', 'start': 95.680, 'end': 126.129}, // 95°40'47" -> 95.680°, 126°07'46" -> 126.129° |
|
|
|
|
{'name': '鬼', 'start': 126.129, 'end': 131.118}, // 126°07'46" -> 126.129°, 131°07'06" -> 131.118° |
|
|
|
|
{'name': '柳', 'start': 131.118, 'end': 147.100}, // 131°07'06" -> 131.118°, 147°06'02" -> 147.100° |
|
|
|
|
{'name': '星', 'start': 147.100, 'end': 155.092}, // 147°06'02" -> 147.100°, 155°05'30" -> 155.092° |
|
|
|
|
{'name': '张', 'start': 155.092, 'end': 174.165}, // 155°05'30" -> 155.092°, 174°09'53" -> 174.165° |
|
|
|
|
{'name': '翼', 'start': 174.165, 'end': 191.096}, // 174°09'53" -> 174.165°, 191°05'46" -> 191.096° |
|
|
|
|
{'name': '轸', 'start': 191.096, 'end': 203.901}, // 191°05'46" -> 191.096°, 203°54'05" -> 203.901° |
|
|
|
|
{'name': '角', 'start': 203.901, 'end': 214.888}, // 203°54'05" -> 203.901°, 214°53'14" -> 214.888° |
|
|
|
|
{'name': '亢', 'start': 214.888, 'end': 225.477}, // 214°53'14" -> 214.888°, 225°28'37" -> 225.477° |
|
|
|
|
{'name': '氐', 'start': 225.477, 'end': 243.325}, // 225°28'37" -> 225.477°, 243°19'30" -> 243.325° |
|
|
|
|
{'name': '房', 'start': 243.325, 'end': 248.175}, // 243°19'30" -> 243.325°, 248°10'29" -> 248.175° |
|
|
|
|
{'name': '心', 'start': 248.175, 'end': 256.429}, // 248°10'29" -> 248.175°, 256°25'44" -> 256.429° |
|
|
|
|
{'name': '尾', 'start': 256.429, 'end': 271.624}, // 256°25'44" -> 256.429°, 271°37'27" -> 271.624° |
|
|
|
|
{'name': '箕', 'start': 271.624, 'end': 280.561}, // 271°37'27" -> 271.624°, 280°33'40" -> 280.561° |
|
|
|
|
{'name': '斗', 'start': 280.561, 'end': 304.477}, // 280°33'40" -> 280.561°, 304°28'37" -> 304.477° |
|
|
|
|
{'name': '牛', 'start': 304.477, 'end': 312.144}, // 304°28'37" -> 304.477°, 312°08'39" -> 312.144° |
|
|
|
|
{'name': '女', 'start': 312.144, 'end': 323.812}, // 312°08'39" -> 312.144°, 323°48'42" -> 323.812° |
|
|
|
|
{'name': '虚', 'start': 323.812, 'end': 333.781}, // 323°48'42" -> 323.812°, 333°46'51" -> 333.781° |
|
|
|
|
{'name': '危', 'start': 333.781, 'end': 353.851}, // 333°46'51" -> 333.781°, 353°51'04" -> 353.851° |
|
|
|
|
{'name': '室', 'start': 353.851, 'end': 10.603}, // 353°51'04" -> 353.851°, 10°36'11" -> 10.603° |
|
|
|
|
{'name': '壁', 'start': 10.603, 'end': 22.824}, // 10°36'11" -> 10.603°, 22°49'26" -> 22.824° |
|
|
|
|
{'name': '奎', 'start': 22.824, 'end': 34.342}, // 22°49'26" -> 22.824°, 34°20'32" -> 34.342° |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
// 根据度数确定星宿名称 |
|
|
|
|
String getStarConstellation(double degrees) { |
|
|
|
|
// 处理跨越0度的情况(如室、壁、奎) |
|
|
|
|
for (final constellation in starConstellations) { |
|
|
|
|
final start = constellation['start'] as double; |
|
|
|
|
final end = constellation['end'] as double; |
|
|
|
|
|
|
|
|
|
if (start <= end) { |
|
|
|
|
// 正常情况:start < end |
|
|
|
|
if (degrees >= start && degrees < end) { |
|
|
|
|
return constellation['name'] as String; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// 跨越0度的情况:start > end(如室:353.851° -> 10.603°) |
|
|
|
|
if (degrees >= start || degrees < end) { |
|
|
|
|
return constellation['name'] as String; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return ''; // 如果没有找到匹配的星宿 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 从单元格值中提取度数(转换为小数形式) |
|
|
|
|
double? _extractDegreesFromCell(String cellValue) { |
|
|
|
|
if (cellValue.isEmpty) return null; |
|
|
|
|
|
|
|
|
|
// 移除 R/D 标记和多余的引号 |
|
|
|
|
String cleanedValue = cellValue.replaceAll(RegExp(r'[RD]'), ''); |
|
|
|
|
cleanedValue = cleanedValue.replaceAll(RegExp(r'[""]+'), ''); // 移除多余的引号 |
|
|
|
|
|
|
|
|
|
// 尝试多种度数格式匹配 |
|
|
|
|
// 格式1: "15°30'45" 或 "15°30" |
|
|
|
|
var match = RegExp(r"^(\d+)\s*°\s*(\d+)\s*(?:['′]\s*(\d{1,2})\s*)?$").firstMatch(cleanedValue); |
|
|
|
|
if (match != null) { |
|
|
|
|
try { |
|
|
|
|
final degrees = int.parse(match.group(1)!); |
|
|
|
|
final minutes = int.parse(match.group(2)!); |
|
|
|
|
final seconds = match.group(3) != null ? int.parse(match.group(3)!) : 0; |
|
|
|
|
|
|
|
|
|
// 转换为小数度数 |
|
|
|
|
return degrees + (minutes / 60.0) + (seconds / 3600.0); |
|
|
|
|
} catch (e) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 格式2: "15.5°" 或 "15.5" |
|
|
|
|
match = RegExp(r"^(\d+\.?\d*)\s*°?\s*$").firstMatch(cleanedValue); |
|
|
|
|
if (match != null) { |
|
|
|
|
try { |
|
|
|
|
return double.parse(match.group(1)!); |
|
|
|
|
} catch (e) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 格式3: "15" (纯数字) |
|
|
|
|
match = RegExp(r"^(\d+)\s*$").firstMatch(cleanedValue); |
|
|
|
|
if (match != null) { |
|
|
|
|
try { |
|
|
|
|
return double.parse(match.group(1)!); |
|
|
|
|
} catch (e) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 调试:如果无法匹配,输出清理后的值 |
|
|
|
|
print(' - 清理后值: "$cleanedValue" (无法匹配任何度数格式)'); |
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 获取列标题 |
|
|
|
|
String _getColumnTitle(int colIndex) { |
|
|
|
|
const Map<int, String> columnTitles = { |
|
|
|
|
4: '日', |
|
|
|
|
5: '月', |
|
|
|
|
6: '紫', // 新增:紫星 |
|
|
|
|
7: '水', |
|
|
|
|
8: '金', |
|
|
|
|
9: '火', |
|
|
|
|
10: '木', |
|
|
|
|
11: '土', |
|
|
|
|
12: '天', |
|
|
|
|
13: '海', |
|
|
|
|
14: '冥', |
|
|
|
|
15: '南', |
|
|
|
|
16: '北', |
|
|
|
|
17: '孛', |
|
|
|
|
18: '凯', |
|
|
|
|
}; |
|
|
|
|
return columnTitles[colIndex] ?? '未知'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static final _degreeFormatRegex = RegExp( |
|
|
|
|
r"^(\d+)\s*([^\d\s°']+)\s*(\d+)\s*(?:['′]\s*(\d{1,2})\s*)?$", |
|
|
|
|
caseSensitive: false, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// 处理数据行,添加宫位数据列 |
|
|
|
|
List<String?> processRowData( |
|
|
|
|
List<String> cells, |
|
|
|
|
Map<int, String> previousPalaces, |
|
|
|
|
Sheet sheet, |
|
|
|
|
int rowIndex, |
|
|
|
|
int startCol, // 新增参数:起始列位置 |
|
|
|
|
) { |
|
|
|
|
List<String?> currentRowPalaces = List.filled(15, null); // 15列:日、月、紫、水、金、火、木、土、天、海、冥、南、北、孛、凯 |
|
|
|
|
int outputCol = startCol; // 使用传入的起始列 |
|
|
|
|
|
|
|
|
|
// 调试日志:只输出前五行的宫宿计算信息 |
|
|
|
|
bool isDebugRow = rowIndex < 5; |
|
|
|
|
|
|
|
|
|
// 步骤1-2:处理日、月列(前两列) |
|
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
|
final col = 4 + i; // 4=日, 5=月 |
|
|
|
|
final cellValue = col < cells.length ? cells[col] : ''; |
|
|
|
|
|
|
|
|
|
// 1. 解析宫位 |
|
|
|
|
final palace = _extractPalace(cellValue); |
|
|
|
|
String palaceToWrite = palace; |
|
|
|
|
|
|
|
|
|
// 如果宫位无效或为R/D,则使用上一行的宫位 |
|
|
|
|
if (palaceToWrite.isEmpty || palaceToWrite == 'R' || palaceToWrite == 'D') { |
|
|
|
|
palaceToWrite = previousPalaces[col] ?? ''; |
|
|
|
|
} else { |
|
|
|
|
// 更新上一行的宫位 |
|
|
|
|
previousPalaces[col] = palaceToWrite; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 2. 先处理原始单元格(带宫位修正) |
|
|
|
|
final displayValue = _getFormattedValueWithAdjustment(cellValue, palaceToWrite); |
|
|
|
|
|
|
|
|
|
// 3. 基于修正后的度数进行星宿判断 |
|
|
|
|
String palaceWithConstellation = palaceToWrite; |
|
|
|
|
String starConstellation = ''; |
|
|
|
|
double? adjustedDegrees = null; |
|
|
|
|
|
|
|
|
|
if (palaceToWrite.isNotEmpty) { |
|
|
|
|
// 从修正后的值中提取度数 |
|
|
|
|
adjustedDegrees = _extractDegreesFromCell(displayValue); |
|
|
|
|
if (adjustedDegrees != null) { |
|
|
|
|
starConstellation = getStarConstellation(adjustedDegrees); |
|
|
|
|
if (starConstellation.isNotEmpty) { |
|
|
|
|
palaceWithConstellation = '$palaceToWrite$starConstellation'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 调试日志 |
|
|
|
|
if (isDebugRow) { |
|
|
|
|
final columnTitle = _getColumnTitle(col); |
|
|
|
|
final originalDegrees = _extractDegreesFromCell(cellValue); |
|
|
|
|
if (adjustedDegrees != null) { |
|
|
|
|
print('第${rowIndex + 1}行 ${columnTitle}: 原始坐标${originalDegrees?.toStringAsFixed(3) ?? "未知"}° -> 宫位:$palaceToWrite -> 修正后坐标${adjustedDegrees.toStringAsFixed(3)}° -> 星宿:$starConstellation -> 结果:$palaceWithConstellation'); |
|
|
|
|
} else { |
|
|
|
|
print('第${rowIndex + 1}行 ${columnTitle}: 无法解析修正后坐标 -> 宫位:$palaceToWrite, 星宿:$starConstellation -> 结果:$palaceWithConstellation'); |
|
|
|
|
print(' - 原始值: "$cellValue"'); |
|
|
|
|
print(' - 修正后值: "$displayValue"'); |
|
|
|
|
print(' - 宫位: "$palaceToWrite"'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
currentRowPalaces[i] = palaceWithConstellation; |
|
|
|
|
|
|
|
|
|
// 4. 写入宫列(包含星宿信息) |
|
|
|
|
sheet.cell(CellIndex.indexByColumnRow( |
|
|
|
|
columnIndex: outputCol, |
|
|
|
|
rowIndex: rowIndex |
|
|
|
|
)).value = TextCellValue(palaceWithConstellation); |
|
|
|
|
outputCol++; |
|
|
|
|
|
|
|
|
|
// 5. 写入原始单元格(带修正) |
|
|
|
|
sheet.cell(CellIndex.indexByColumnRow( |
|
|
|
|
columnIndex: outputCol, |
|
|
|
|
rowIndex: rowIndex |
|
|
|
|
)).value = TextCellValue(displayValue); |
|
|
|
|
outputCol++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 步骤3:插入紫宫列和紫星列(在月亮和水星之间) |
|
|
|
|
// 从extendedCells中获取紫星数据 |
|
|
|
|
final purpleCellValue = cells.length > 6 ? cells[6] : ''; |
|
|
|
|
final purplePalace = _extractPalace(purpleCellValue); |
|
|
|
|
String purplePalaceToWrite = purplePalace; |
|
|
|
|
|
|
|
|
|
// 如果宫位无效或为R/D,则使用上一行的宫位 |
|
|
|
|
if (purplePalaceToWrite.isEmpty || purplePalaceToWrite == 'R' || purplePalaceToWrite == 'D') { |
|
|
|
|
purplePalaceToWrite = previousPalaces[6] ?? ''; |
|
|
|
|
} else { |
|
|
|
|
// 更新上一行的宫位 |
|
|
|
|
previousPalaces[6] = purplePalaceToWrite; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 处理紫星数据(带宫位修正) |
|
|
|
|
final purpleDisplayValue = _getFormattedValueWithAdjustment(purpleCellValue, purplePalaceToWrite); |
|
|
|
|
|
|
|
|
|
// 基于修正后的度数进行星宿判断 |
|
|
|
|
String purplePalaceWithConstellation = purplePalaceToWrite; |
|
|
|
|
String purpleStarConstellation = ''; |
|
|
|
|
double? purpleAdjustedDegrees = null; |
|
|
|
|
|
|
|
|
|
if (purplePalaceToWrite.isNotEmpty) { |
|
|
|
|
// 从修正后的值中提取度数 |
|
|
|
|
purpleAdjustedDegrees = _extractDegreesFromCell(purpleDisplayValue); |
|
|
|
|
if (purpleAdjustedDegrees != null) { |
|
|
|
|
purpleStarConstellation = getStarConstellation(purpleAdjustedDegrees); |
|
|
|
|
if (purpleStarConstellation.isNotEmpty) { |
|
|
|
|
purplePalaceWithConstellation = '$purplePalaceToWrite$purpleStarConstellation'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 调试日志 |
|
|
|
|
if (isDebugRow) { |
|
|
|
|
final originalDegrees = _extractDegreesFromCell(purpleCellValue); |
|
|
|
|
if (purpleAdjustedDegrees != null) { |
|
|
|
|
print('第${rowIndex + 1}行 紫: 原始坐标${originalDegrees?.toStringAsFixed(3) ?? "未知"}° -> 宫位:$purplePalaceToWrite -> 修正后坐标${purpleAdjustedDegrees.toStringAsFixed(3)}° -> 星宿:$purpleStarConstellation -> 结果:$purplePalaceWithConstellation'); |
|
|
|
|
} else { |
|
|
|
|
print('第${rowIndex + 1}行 紫: 无法解析修正后坐标 -> 宫位:$purplePalaceToWrite, 星宿:$purpleStarConstellation -> 结果:$purplePalaceWithConstellation'); |
|
|
|
|
print(' - 原始值: "$purpleCellValue"'); |
|
|
|
|
print(' - 修正后值: "$purpleDisplayValue"'); |
|
|
|
|
print(' - 宫位: "$purplePalaceToWrite"'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
currentRowPalaces[2] = purplePalaceWithConstellation; |
|
|
|
|
|
|
|
|
|
// 写入紫宫列(紫星宫位+星宿) |
|
|
|
|
sheet.cell(CellIndex.indexByColumnRow( |
|
|
|
|
columnIndex: outputCol, |
|
|
|
|
rowIndex: rowIndex |
|
|
|
|
)).value = TextCellValue(purplePalaceWithConstellation); |
|
|
|
|
outputCol++; |
|
|
|
|
|
|
|
|
|
// 写入紫星列(紫星度数) |
|
|
|
|
sheet.cell(CellIndex.indexByColumnRow( |
|
|
|
|
columnIndex: outputCol, |
|
|
|
|
rowIndex: rowIndex |
|
|
|
|
)).value = TextCellValue(purpleDisplayValue); |
|
|
|
|
outputCol++; |
|
|
|
|
|
|
|
|
|
// 步骤4:处理水星到凯星列(第4列到第14列) |
|
|
|
|
for (int i = 3; i < 15; i++) { |
|
|
|
|
final col = 4 + i; // 6=水, 7=金, 8=火, 9=木, 10=土, 11=天, 12=海, 13=冥, 14=南, 15=北, 16=孛, 17=凯 |
|
|
|
|
final cellValue = col < cells.length ? cells[col] : ''; |
|
|
|
|
|
|
|
|
|
// 1. 解析宫位 |
|
|
|
|
final palace = _extractPalace(cellValue); |
|
|
|
|
String palaceToWrite = palace; |
|
|
|
|
|
|
|
|
|
// 如果宫位无效或为R/D,则使用上一行的宫位 |
|
|
|
|
if (palaceToWrite.isEmpty || palaceToWrite == 'R' || palaceToWrite == 'D') { |
|
|
|
|
palaceToWrite = previousPalaces[col] ?? ''; |
|
|
|
|
} else { |
|
|
|
|
// 更新上一行的宫位 |
|
|
|
|
previousPalaces[col] = palaceToWrite; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 2. 先处理原始单元格(带宫位修正) |
|
|
|
|
final displayValue = _getFormattedValueWithAdjustment(cellValue, palaceToWrite); |
|
|
|
|
|
|
|
|
|
// 3. 基于修正后的度数进行星宿判断 |
|
|
|
|
String palaceWithConstellation = palaceToWrite; |
|
|
|
|
String starConstellation = ''; |
|
|
|
|
double? adjustedDegrees = null; |
|
|
|
|
|
|
|
|
|
if (palaceToWrite.isNotEmpty) { |
|
|
|
|
// 从修正后的值中提取度数 |
|
|
|
|
adjustedDegrees = _extractDegreesFromCell(displayValue); |
|
|
|
|
if (adjustedDegrees != null) { |
|
|
|
|
starConstellation = getStarConstellation(adjustedDegrees); |
|
|
|
|
if (starConstellation.isNotEmpty) { |
|
|
|
|
palaceWithConstellation = '$palaceToWrite$starConstellation'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 调试日志 |
|
|
|
|
if (isDebugRow) { |
|
|
|
|
final columnTitle = _getColumnTitle(col); |
|
|
|
|
final originalDegrees = _extractDegreesFromCell(cellValue); |
|
|
|
|
if (adjustedDegrees != null) { |
|
|
|
|
print('第${rowIndex + 1}行 ${columnTitle}: 原始坐标${originalDegrees?.toStringAsFixed(3) ?? "未知"}° -> 宫位:$palaceToWrite -> 修正后坐标${adjustedDegrees.toStringAsFixed(3)}° -> 星宿:$starConstellation -> 结果:$palaceWithConstellation'); |
|
|
|
|
} else { |
|
|
|
|
print('第${rowIndex + 1}行 ${columnTitle}: 无法解析修正后坐标 -> 宫位:$palaceToWrite, 星宿:$starConstellation -> 结果:$palaceWithConstellation'); |
|
|
|
|
print(' - 原始值: "$cellValue"'); |
|
|
|
|
print(' - 修正后值: "$displayValue"'); |
|
|
|
|
print(' - 宫位: "$palaceToWrite"'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
currentRowPalaces[i] = palaceWithConstellation; |
|
|
|
|
|
|
|
|
|
// 4. 写入宫列(包含星宿信息) |
|
|
|
|
sheet.cell(CellIndex.indexByColumnRow( |
|
|
|
|
columnIndex: outputCol, |
|
|
|
|
rowIndex: rowIndex |
|
|
|
|
)).value = TextCellValue(palaceWithConstellation); |
|
|
|
|
outputCol++; |
|
|
|
|
|
|
|
|
|
// 5. 写入原始单元格(带修正) |
|
|
|
|
sheet.cell(CellIndex.indexByColumnRow( |
|
|
|
|
columnIndex: outputCol, |
|
|
|
|
rowIndex: rowIndex |
|
|
|
|
)).value = TextCellValue(displayValue); |
|
|
|
|
outputCol++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return currentRowPalaces; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String _getFormattedValueWithAdjustment(String originalValue, String palace) { |
|
|
|
|
// 0. 提取并移除 R/D 标记 |
|
|
|
|
final rdMatches = RegExp(r'[RD]').allMatches(originalValue).map((m) => m.group(0)!).toList(); |
|
|
|
|
final rdFlags = rdMatches.join(); |
|
|
|
|
|
|
|
|
|
// 1. 标准化输入并去除 R/D 标记,避免干扰解析与修正 |
|
|
|
|
String normalized = originalValue.replaceAll('′', "'").replaceAll(' ', '').replaceAll(' ', ''); |
|
|
|
|
String normalizedNoFlags = normalized.replaceAll(RegExp(r'[RD]'), ''); |
|
|
|
|
|
|
|
|
|
// 2. 解析并替换地支为度符号 |
|
|
|
|
String withDegreeSymbol = _replaceZodiacWithDegreeSymbol(normalizedNoFlags); |
|
|
|
|
|
|
|
|
|
// 3. 应用宫位修正 |
|
|
|
|
String adjusted = withDegreeSymbol; |
|
|
|
|
if (palace.isNotEmpty && palaceDegreeAdjustments.containsKey(palace)) { |
|
|
|
|
adjusted = _adjustDegreeByPalace(withDegreeSymbol, palace); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4. 将 R/D 标记补回(追加在末尾),确保只有一个引号 |
|
|
|
|
String result = rdFlags.isNotEmpty ? '$adjusted$rdFlags' : adjusted; |
|
|
|
|
|
|
|
|
|
// 清理多余的引号 |
|
|
|
|
result = result.replaceAll(RegExp(r'[""]+'), '"'); |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String _replaceZodiacWithDegreeSymbol(String value) { |
|
|
|
|
// 首先检查是否已经是正确的度数格式 |
|
|
|
|
if (value.contains('°')) { |
|
|
|
|
return value; // 如果已经包含度数符号,直接返回 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
final match = _degreeFormatRegex.firstMatch(value); |
|
|
|
|
if (match == null) return value; |
|
|
|
|
|
|
|
|
|
final degreeStr = match.group(1); |
|
|
|
|
final minuteStr = match.group(3); |
|
|
|
|
final secondStr = match.group(4); |
|
|
|
|
|
|
|
|
|
if (degreeStr == null || minuteStr == null) return value; |
|
|
|
|
|
|
|
|
|
return '${degreeStr}°${minuteStr.padLeft(2, '0')}' |
|
|
|
|
'${secondStr != null ? "'${secondStr.padLeft(2, '0')}\"" : ""}'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String _adjustDegreeByPalace(String valueWithDegree, String palace) { |
|
|
|
|
final match = RegExp(r"^(\d+)°(\d+)(?:['](\d{1,2}))?").firstMatch(valueWithDegree); |
|
|
|
|
if (match == null) return valueWithDegree; |
|
|
|
|
|
|
|
|
|
final degreeStr = match.group(1); |
|
|
|
|
final minuteStr = match.group(2); |
|
|
|
|
final secondStr = match.group(3); |
|
|
|
|
|
|
|
|
|
if (degreeStr == null || minuteStr == null) return valueWithDegree; |
|
|
|
|
|
|
|
|
|
final originalDegree = int.tryParse(degreeStr) ?? 0; |
|
|
|
|
final adjustment = palaceDegreeAdjustments[palace] ?? 0; |
|
|
|
|
var adjustedDegree = originalDegree + adjustment; |
|
|
|
|
|
|
|
|
|
adjustedDegree %= 360; |
|
|
|
|
if (adjustedDegree < 0) adjustedDegree += 360; |
|
|
|
|
|
|
|
|
|
return '${adjustedDegree}°${minuteStr.padLeft(2, '0')}' |
|
|
|
|
'${secondStr != null ? "'${secondStr.padLeft(2, '0')}\"" : ""}'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String _extractPalace(String cellValue) { |
|
|
|
|
final match = RegExp(r"[^\d\s°\'RDL]").firstMatch(cellValue.trim()); |
|
|
|
|
return match?.group(0) ?? ''; |
|
|
|
|
} |
|
|
|
|
} |