-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoutput_generator.py
More file actions
276 lines (221 loc) · 9.98 KB
/
output_generator.py
File metadata and controls
276 lines (221 loc) · 9.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
"""
코드 ID: OUTPUT_GENERATOR_001
연결 요구사항: AI-REQ-F-001 (문서 분석 및 요구사항 자동 추출)
작성자: AI System
작성일: 2025-09-01
설명: 분석 결과를 다양한 형식(JSON, Excel, Word)으로 출력하는 모듈
"""
import json
import pandas as pd
from docx import Document
from docx.shared import Inches
import openpyxl
from typing import List, Dict, Any, Optional
import logging
from datetime import datetime
import os
# 코드 ID: OUTPUT_GENERATOR_001
class OutputGenerator:
"""
분석 결과 출력 클래스
- JSON, Excel, Word 형식 지원
- 요구사항 ID: AI-REQ-F-001과 연결
"""
def __init__(self, output_dir: str = "./output"):
self.output_dir = output_dir
self.logger = logging.getLogger(__name__)
# 출력 디렉터리 생성
os.makedirs(output_dir, exist_ok=True)
def generate_json_report(self, analysis_results: Dict[str, Any], filename: Optional[str] = None) -> str:
"""
JSON 형식 보고서 생성
Args:
analysis_results: 분석 결과 딕셔너리
filename: 출력 파일명 (None이면 자동 생성)
Returns:
str: 생성된 파일 경로
"""
if filename is None:
filename = f"requirement_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
filepath = os.path.join(self.output_dir, filename)
# 메타데이터 추가
output_data = {
"metadata": {
"generated_at": datetime.now().isoformat(),
"generator": "OUTPUT_GENERATOR_001",
"linked_requirement": "AI-REQ-F-001",
"version": "1.0"
},
"analysis_results": analysis_results
}
try:
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(output_data, f, ensure_ascii=False, indent=2)
self.logger.info(f"JSON 보고서 생성 완료: {filepath}")
return filepath
except Exception as e:
self.logger.error(f"JSON 보고서 생성 오류: {e}")
raise
def generate_excel_report(self, requirements_data: List[Dict[str, Any]], filename: Optional[str] = None) -> str:
"""
Excel 형식 보고서 생성
Args:
requirements_data: 요구사항 데이터 리스트
filename: 출력 파일명
Returns:
str: 생성된 파일 경로
"""
if filename is None:
filename = f"requirement_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
filepath = os.path.join(self.output_dir, filename)
try:
with pd.ExcelWriter(filepath, engine='openpyxl') as writer:
# 요구사항 목록 시트
if requirements_data:
df_requirements = pd.DataFrame(requirements_data)
df_requirements.to_excel(writer, sheet_name='요구사항 목록', index=False)
# 통계 시트
self._generate_statistics_sheet(writer, requirements_data)
# 요약 시트
self._generate_summary_sheet(writer, requirements_data)
self.logger.info(f"Excel 보고서 생성 완료: {filepath}")
return filepath
except Exception as e:
self.logger.error(f"Excel 보고서 생성 오류: {e}")
raise
def generate_word_report(self, analysis_results: Dict[str, Any], filename: Optional[str] = None) -> str:
"""
Word 형식 보고서 생성
Args:
analysis_results: 분석 결과
filename: 출력 파일명
Returns:
str: 생성된 파일 경로
"""
if filename is None:
filename = f"requirement_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.docx"
filepath = os.path.join(self.output_dir, filename)
try:
doc = Document()
# 제목
title = doc.add_heading('요구사항 분석 보고서', 0)
title.alignment = 1 # 중앙 정렬
# 메타데이터
doc.add_heading('1. 분석 개요', level=1)
doc.add_paragraph(f'생성일시: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}')
doc.add_paragraph(f'연결 요구사항: AI-REQ-F-001')
doc.add_paragraph(f'생성 모듈: OUTPUT_GENERATOR_001')
# 분석 결과
if 'requirements' in analysis_results:
doc.add_heading('2. 추출된 요구사항', level=1)
requirements = analysis_results['requirements']
for i, req in enumerate(requirements[:10], 1): # 상위 10개만
doc.add_heading(f'2.{i} {req.get("id", f"REQ-{i:03d}")}', level=2)
doc.add_paragraph(f'내용: {req.get("text", "")}')
doc.add_paragraph(f'유형: {req.get("type", "")}')
doc.add_paragraph(f'우선순위: {req.get("priority", "")}')
doc.add_paragraph(f'카테고리: {req.get("category", "")}')
doc.add_paragraph(f'신뢰도: {req.get("confidence_score", 0):.2f}')
doc.add_paragraph() # 빈 줄
# 통계
doc.add_heading('3. 분석 통계', level=1)
if 'statistics' in analysis_results:
stats = analysis_results['statistics']
doc.add_paragraph(f'총 추출 요구사항 수: {stats.get("total_requirements", 0)}개')
doc.add_paragraph(f'기능 요구사항: {stats.get("functional_count", 0)}개')
doc.add_paragraph(f'비기능 요구사항: {stats.get("non_functional_count", 0)}개')
doc.add_paragraph(f'평균 신뢰도: {stats.get("average_confidence", 0):.2f}')
# 권장사항
doc.add_heading('4. 권장사항', level=1)
doc.add_paragraph('1. 추출된 요구사항에 대한 이해관계자 검토가 필요합니다.')
doc.add_paragraph('2. 신뢰도가 낮은 요구사항은 추가 분석을 권장합니다.')
doc.add_paragraph('3. 중복되거나 모호한 요구사항은 정제 작업이 필요합니다.')
doc.save(filepath)
self.logger.info(f"Word 보고서 생성 완료: {filepath}")
return filepath
except Exception as e:
self.logger.error(f"Word 보고서 생성 오류: {e}")
raise
def _generate_statistics_sheet(self, writer, requirements_data: List[Dict[str, Any]]):
"""통계 시트 생성"""
if not requirements_data:
return
# 기본 통계 계산
total_count = len(requirements_data)
type_counts = {}
priority_counts = {}
category_counts = {}
for req in requirements_data:
# 타입별 카운트
req_type = req.get('type', '기타')
type_counts[req_type] = type_counts.get(req_type, 0) + 1
# 우선순위별 카운트
priority = req.get('priority', '중')
priority_counts[priority] = priority_counts.get(priority, 0) + 1
# 카테고리별 카운트
category = req.get('category', '일반')
category_counts[category] = category_counts.get(category, 0) + 1
# 통계 데이터 구성
statistics_data = [
['항목', '값'],
['총 요구사항 수', total_count],
['', ''], # 빈 행
['유형별 분포', ''],
]
for type_name, count in type_counts.items():
statistics_data.append([f' {type_name}', count])
statistics_data.extend([
['', ''], # 빈 행
['우선순위별 분포', '']
])
for priority, count in priority_counts.items():
statistics_data.append([f' {priority}', count])
# DataFrame으로 변환 후 Excel에 저장
df_stats = pd.DataFrame(statistics_data)
df_stats.to_excel(writer, sheet_name='통계', index=False, header=False)
def _generate_summary_sheet(self, writer, requirements_data: List[Dict[str, Any]]):
"""요약 시트 생성"""
summary_data = {
'생성일시': [datetime.now().strftime('%Y-%m-%d %H:%M:%S')],
'연결 요구사항': ['AI-REQ-F-001'],
'생성 모듈': ['OUTPUT_GENERATOR_001'],
'총 요구사항 수': [len(requirements_data)],
'분석 완료': ['Yes' if requirements_data else 'No']
}
df_summary = pd.DataFrame(summary_data)
df_summary.to_excel(writer, sheet_name='요약', index=False)
def generate_comprehensive_report(self, analysis_results: Dict[str, Any]) -> Dict[str, str]:
"""
모든 형식의 보고서를 한번에 생성
Args:
analysis_results: 분석 결과
Returns:
Dict[str, str]: 생성된 파일 경로들
"""
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
file_paths = {}
try:
# JSON 보고서
json_path = self.generate_json_report(
analysis_results,
f'analysis_report_{timestamp}.json'
)
file_paths['json'] = json_path
# Excel 보고서
if 'requirements' in analysis_results:
excel_path = self.generate_excel_report(
analysis_results['requirements'],
f'analysis_report_{timestamp}.xlsx'
)
file_paths['excel'] = excel_path
# Word 보고서
word_path = self.generate_word_report(
analysis_results,
f'analysis_report_{timestamp}.docx'
)
file_paths['word'] = word_path
self.logger.info(f"모든 보고서 생성 완료: {len(file_paths)}개 파일")
return file_paths
except Exception as e:
self.logger.error(f"종합 보고서 생성 오류: {e}")
raise