Browse Source

完成合冲刑处理

master
hejl 1 month ago
parent
commit
ee48c7b1e3
  1. 226
      win_text_editor/lib/modules/pdf_parse/services/excel_deal_service.dart

226
win_text_editor/lib/modules/pdf_parse/services/excel_deal_service.dart

@ -6,11 +6,55 @@ import 'package:win_text_editor/app/providers/logger.dart'; @@ -6,11 +6,55 @@ import 'package:win_text_editor/app/providers/logger.dart';
class ExcelDealService {
static const String _logTag = 'ExcelDealService';
static const Map<int, String> _columnTitles = {
4: '',
5: '',
6: '',
7: '',
8: '',
9: '',
10: '',
11: '',
12: '',
13: '',
14: '',
15: '',
16: '',
17: '',
};
static const List<Set<String>> harmonyGroups = [
{'', '', ''}, //
{'', '', ''}, //
{'', '', ''}, //
{'', '', ''}, //
];
static const List<Set<String>> conflictGroups = [
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', ''}, //
];
static const List<Set<String>> punishmentGroups = [
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', ''}, //
{'', '', ''}, //
{'', '', ''}, //
];
Future<void> exportToExcel(String processedContent, {String? fileName}) async {
try {
final excel = Excel.createExcel();
final sheet = excel['Sheet1']!;
final sheet = excel['Sheet1'];
final lines = processedContent.split('\n');
bool isHeaderProcessed = false;
@ -51,27 +95,20 @@ class ExcelDealService { @@ -51,27 +95,20 @@ class ExcelDealService {
final cell = sheet.cell(CellIndex.indexByColumnRow(columnIndex: col, rowIndex: rowIndex));
cell.value = TextCellValue(cellValue);
//
if (isHeaderProcessed && col == cells.length - 1) {
for (int i = 0; i < 3; i++) {
sheet
.cell(
CellIndex.indexByColumnRow(columnIndex: cells.length + i, rowIndex: rowIndex),
)
.value = TextCellValue('');
}
}
// 7-14(6-13)
if (col >= 6 && col <= 13) {
_applyConditionalFormatting(cell, cellValue);
}
}
//
if (isHeaderProcessed && rowIndex > 0) {
_calculateRelationships(sheet, rowIndex, cells);
}
}
//
for (var i = 1; i < 18; i++) {
//
sheet.setColumnWidth(i, 8.0);
}
@ -98,20 +135,179 @@ class ExcelDealService { @@ -98,20 +135,179 @@ class ExcelDealService {
}
}
void _calculateRelationships(Sheet sheet, int rowIndex, List<String> cells) {
final List<CellData> validCells = [];
// 1. Extract valid cells (columns 5-18, excluding 15-16) with degree, zodiac and minute
for (int col = 4; col <= 17; col++) {
if (col == 14 || col == 15) continue; // Skip South/North columns
if (col < cells.length) {
final data = _parseCellData(cells[col]);
if (data != null && data.isValid()) {
validCells.add(data..columnIndex = col);
}
}
}
final List<String> heRelations = []; //
final List<String> chongRelations = []; //
final List<String> xingRelations = []; //
// 2. Compare all valid cells pairwise
for (int i = 0; i < validCells.length; i++) {
for (int j = i + 1; j < validCells.length; j++) {
final cell1 = validCells[i];
final cell2 = validCells[j];
// Get column titles
final title1 = _columnTitles[cell1.columnIndex] ?? '';
final title2 = _columnTitles[cell2.columnIndex] ?? '';
// Check for harmony ()
if (_isHarmony(cell1, cell2)) {
heRelations.add('$title1$title2合');
}
// Check for conflict ()
if (_isConflict(cell1.zodiac, cell2.zodiac)) {
chongRelations.add('$title1$title2冲');
}
// Check for punishment ()
if (_isPunishment(cell1.zodiac, cell2.zodiac)) {
xingRelations.add('$title1$title2刑');
}
}
}
// 3. (19-21)
if (heRelations.isNotEmpty) {
sheet
.cell(CellIndex.indexByColumnRow(columnIndex: cells.length, rowIndex: rowIndex))
.value = TextCellValue(heRelations.join(' '));
}
if (chongRelations.isNotEmpty) {
sheet
.cell(CellIndex.indexByColumnRow(columnIndex: cells.length + 1, rowIndex: rowIndex))
.value = TextCellValue(chongRelations.join(' '));
}
if (xingRelations.isNotEmpty) {
sheet
.cell(CellIndex.indexByColumnRow(columnIndex: cells.length + 2, rowIndex: rowIndex))
.value = TextCellValue(xingRelations.join(' '));
}
}
CellData? _parseCellData(String cellValue) {
//
// 1. "12酉34"
// 2. '秒(如"10丑48'49""11°50'00")
final match = RegExp(
r"^(\d+)([^\d\s°\']+)(\d+)(?:[\'](\d{1,2}))?$",
).firstMatch(cellValue.trim());
if (match == null) return null;
final degreeStr = match.group(1);
final zodiac = match.group(2);
final minuteStr = match.group(3);
final secondStr = match.group(4); // null
if (degreeStr == null || zodiac == null || minuteStr == null) return null;
// double类型的度
final degree = double.tryParse(degreeStr);
final minute = double.tryParse(minuteStr);
final second = secondStr != null ? double.tryParse(secondStr) : 0.0;
if (degree == null || minute == null) return null;
// 60=1
final totalMinutes = minute + (second ?? 0) / 60;
return CellData(degree: degree, zodiac: zodiac, minute: totalMinutes);
}
bool _isHarmony(CellData cell1, CellData cell2) {
//
if (cell1.zodiac == cell2.zodiac) return false;
// 1. 1
final totalDiff = (cell1.totalMinutes - cell2.totalMinutes).abs();
final isDegreeMatch = totalDiff <= 60;
if (isDegreeMatch) {
// 1true
return true;
}
// 2. r
var isZodiacMatch = false;
for (final group in harmonyGroups) {
if (group.contains(cell1.zodiac) && group.contains(cell2.zodiac)) {
isZodiacMatch = true;
break;
}
}
//
return isDegreeMatch || isZodiacMatch;
}
bool _isConflict(String zodiac1, String zodiac2) {
//
if (zodiac1 == zodiac2) return false;
for (final group in conflictGroups) {
if (group.contains(zodiac1) && group.contains(zodiac2)) {
return true;
}
}
return false;
}
bool _isPunishment(String zodiac1, String zodiac2) {
//
if (zodiac1 == zodiac2) return false;
for (final group in punishmentGroups) {
if (group.contains(zodiac1) && group.contains(zodiac2)) {
return true;
}
}
return false;
}
//
final List<bool> _columnRedStates = List.filled(14, false);
void _applyConditionalFormatting(Data cell, String value) {
//
if (value.contains('R')) {
_columnRedStates[cell.cellIndex.columnIndex] = true;
} else if (value.contains('D')) {
_columnRedStates[cell.cellIndex.columnIndex] = false;
}
//
if (_columnRedStates[cell.cellIndex.columnIndex]) {
cell.cellStyle = CellStyle(fontColorHex: ExcelColor.red);
}
}
}
class CellData {
final double? degree;
final String zodiac;
final double? minute;
int columnIndex = -1;
//
static const validZodiacs = {'', '', '', '', '', '', '', '', '', '', '', ''};
CellData({this.degree, required this.zodiac, this.minute});
bool isValid() {
return degree != null && minute != null && validZodiacs.contains(zodiac);
}
double get totalMinutes => (degree ?? 0) * 60 + (minute ?? 0);
}

Loading…
Cancel
Save