126 lines
5.2 KiB
Python
126 lines
5.2 KiB
Python
import os
|
||
import re
|
||
from typing import List, Tuple, Optional
|
||
|
||
from agent.models import ProgramMeta
|
||
|
||
|
||
PGM_PATTERN_MAP = {
|
||
'マッチング(1:1)': 'マッチング(1-1).md',
|
||
'マッチング(1:N)': 'マッチング(1-N).md',
|
||
'マッチング(N:1)': 'マッチング(N-1).md',
|
||
'マッチング(M:N)': 'マッチング(M-N).md',
|
||
'レイアウト編集のみ(GETPUT)': 'レイアウト編集のみ(GETPUT).md',
|
||
'レイアウト編集のみ(GETPUT)': 'レイアウト編集のみ(GETPUT).md',
|
||
'レイアウト編集のみ': 'レイアウト編集のみ(GETPUT).md',
|
||
'GETPUT(編集出力)': 'GETPUT(編集出力).md',
|
||
'項目チェック': '項目チェック.md',
|
||
'項目チェック(重複なし)': '項目チェック.md',
|
||
'振り分け': '振り分け.md',
|
||
'振り分け(IF文、EVALUATE文)': '振り分け.md',
|
||
'キーブレイク': 'キーブレイク(集計).md',
|
||
'キーブレイク(集計)': 'キーブレイク(集計).md',
|
||
'キーブレイク(集約)': 'キーブレイク(集約).md',
|
||
'キーブレイク(集約)': 'キーブレイク(集約).md',
|
||
'キーブレイク(集計、集約)': 'キーブレイク(集計、集約).md',
|
||
'キーブレイク(集計、集約の以外)': 'キーブレイク(集計).md',
|
||
'1:Nキーブレイク(同キー集約)': 'キーブレイク(集計、集約).md',
|
||
'1:N+キーブレイク(同キー)': 'キーブレイク(集計、集約).md',
|
||
'DB更新': 'DB更新.md',
|
||
'DB更新 + SYSIN読込(P28)': 'DB更新.md',
|
||
'SELECT処理': 'SELECT処理.md',
|
||
'SELECT条件': 'SELECT処理.md',
|
||
'50分割': '50分割.md',
|
||
'MERGE(複数ファイル結合)': 'MERGE.md',
|
||
'CSV→FB変換(改行あり)': 'CSV→FB変換.md',
|
||
}
|
||
|
||
SPECIAL_FEATURE_CHECKS = [
|
||
(['場合', 'EVALUATE', 'IF'], '条件分支.md'),
|
||
]
|
||
|
||
|
||
class RuleLoader:
|
||
"""根据程序特征加载对应的数据生成规则。"""
|
||
|
||
def __init__(self, rules_dir: str):
|
||
self.pgm_pattern_dir = os.path.join(rules_dir, 'pgm_pattern')
|
||
self.special_feature_dir = os.path.join(rules_dir, 'special_feature')
|
||
|
||
def load(self, meta: ProgramMeta) -> Tuple[str, List[str], int]:
|
||
"""加载所有相关规则,返回 (合并后的规则文本, 组描述列表, 组数)。"""
|
||
pgm_rule = self._load_pgm_pattern_rule(meta.pgm_pattern)
|
||
if pgm_rule is None:
|
||
raise FileNotFoundError(
|
||
f"PGM模式 '{meta.pgm_pattern}' の規則ファイルが見つかりません。"
|
||
f"{self.pgm_pattern_dir} に .md ファイルを追加してください。"
|
||
)
|
||
|
||
group_descriptions, group_count = self._parse_group_info(pgm_rule)
|
||
|
||
parts = [pgm_rule]
|
||
for keywords, rule_file in SPECIAL_FEATURE_CHECKS:
|
||
if self._detect_feature(meta.process_detail, keywords):
|
||
feature_rule = self._read_rule_file(
|
||
os.path.join(self.special_feature_dir, rule_file)
|
||
)
|
||
if feature_rule:
|
||
parts.append(feature_rule)
|
||
|
||
combined = '\n\n---\n\n'.join(parts)
|
||
return combined, group_descriptions, group_count
|
||
|
||
def _load_pgm_pattern_rule(self, pgm_pattern: str) -> Optional[str]:
|
||
"""根据 PGMパターン 加载对应的规则文件。"""
|
||
filename = PGM_PATTERN_MAP.get(pgm_pattern)
|
||
if filename:
|
||
path = os.path.join(self.pgm_pattern_dir, filename)
|
||
if os.path.exists(path):
|
||
return self._read_rule_file(path)
|
||
|
||
if os.path.isdir(self.pgm_pattern_dir):
|
||
available = sorted(os.listdir(self.pgm_pattern_dir))
|
||
# 对每个规则文件名(去掉.md),检查它是否出现在 PGMパターン 中
|
||
pgm_lower = pgm_pattern.lower()
|
||
for fname in available:
|
||
if fname.endswith('.md'):
|
||
rule_name = fname[:-3].lower()
|
||
if rule_name in pgm_lower:
|
||
return self._read_rule_file(os.path.join(self.pgm_pattern_dir, fname))
|
||
|
||
return None
|
||
|
||
@staticmethod
|
||
def _read_rule_file(path: str) -> str:
|
||
with open(path, 'r', encoding='utf-8') as f:
|
||
return f.read()
|
||
|
||
@staticmethod
|
||
def _parse_group_info(rule_text: str) -> Tuple[List[str], int]:
|
||
"""从规则文本中解析组信息。"""
|
||
descriptions = []
|
||
group_count = 0
|
||
|
||
for line in rule_text.split('\n'):
|
||
line = line.strip()
|
||
if line.startswith('|') and not re.match(r'^\|[\s\-:]+\|', line):
|
||
cells = [c.strip() for c in line.split('|')[1:-1]]
|
||
if len(cells) >= 2:
|
||
try:
|
||
group_num = int(cells[0])
|
||
if group_num > group_count:
|
||
group_count = group_num
|
||
descriptions.append(cells[1])
|
||
except ValueError:
|
||
pass
|
||
|
||
return descriptions, group_count
|
||
|
||
@staticmethod
|
||
def _detect_feature(process_detail: str, keywords: List[str]) -> bool:
|
||
"""检测処理詳細中是否包含特定关键词。"""
|
||
for kw in keywords:
|
||
if kw in process_detail:
|
||
return True
|
||
return False
|