This commit is contained in:
KIM SU BO committed 2026-10-06 13:24:08 +09:00
1 parent 83278b2998
commit b38ceec784
128 files changed
+51554

No files matched your search

+370
View File
@@ -0,0 +1,370 @@
import os
import re
import json
def parse_missions_md(md_path):
with open(md_path, 'r', encoding='utf-8') as f:
lines = [l.strip() for l in f if l.strip()]
headers = [h.strip() for h in lines[0].split('|')[1:-1]]
projects = {}
for line in lines[2:]:
parts = [p.strip() for p in line.split('|')[1:-1]]
if len(parts) == len(headers):
p_no = int(parts[0]) if parts[0].isdigit() else parts[0]
p_id = parts[1]
if p_no not in projects:
projects[p_no] = {
'p_no': p_no,
'p_id': p_id,
'p_name': parts[2],
'category': parts[3],
'sub_category': parts[4],
'p_difficulty': parts[5],
'learning_type': parts[6],
'war_case': parts[7],
'missions': []
}
mission_dict = dict(zip(headers, parts))
projects[p_no]['missions'].append(mission_dict)
return projects
def extract_file_paths(text):
matches = re.findall(r'`([^`]+)`', text)
paths = []
for m in matches:
sub_items = re.split(r'[,및\s]+', m)
for item in sub_items:
item = item.strip()
if item and ('.' in item or '/' in item or '\\' in item):
paths.append(item)
if not paths:
for token in text.split():
clean = token.strip('`,()[]"\'')
if ('.' in clean and '/' in clean) or clean.endswith('.py') or clean.endswith('.md') or clean.endswith('.json') or clean.endswith('.yaml') or clean.endswith('.pdf') or clean.endswith('.xlsx') or clean.endswith('.csv'):
paths.append(clean)
unique_paths = []
for p in paths:
if p not in unique_paths:
unique_paths.append(p)
return unique_paths
def extract_tech_stack(p_data, m_data):
stack = [p_data['category'], p_data['sub_category']]
title = m_data['미션명']
desc = m_data['미션 설명']
keywords = [
'Python', '드론 영상', '컴퓨터 비전', 'YOLO', '딥러닝', '머신러닝', 'OpenCV',
'EO/IR 센서', '영상 전처리', 'CLAHE', '칼만 필터', '센서 융합', '좌표 변환',
'포화경보', '우선순위 큐', '신뢰도 지수', '전술 대시보드', 'COP', 'HITL',
'스트레스 테스트', 'AAR 사후검토', '위성영상', 'OSINT', '비행로그', '이상 탐지',
'시계열 분석', '자연어 처리', 'NLP', '소셜미디어 분석', '교차검증', '귀속 매트릭스',
'음성 스푸핑', '딥페이크', '전술통신', '대역폭 제약', '상황인계', 'CCTV 탐지',
'침입 경보', '방호 점검', '기만체 차폐', 'TCCC 전투의무', '열/한랭 스트레스',
'수질 분석', '근무부하 예측', '보급 증빙 체인', '재보급 우선순위', '무인 보급',
'단종관리', '공급망 모니터링', 'SaaS', '부품 국산화', '조달계획 검증', '품질예측',
'외주정비 검사', '시효성 품목', '탄약 저장 최적화', '수송 소요예측', '납품물류 추적',
'고장률 분석', 'PBL 품목관리', '정비인력 부하율', '폐기율 산정', '제원검증', '성과지표(KPI)',
'군수데이터 전략', 'RPA 업무자동화'
]
for kw in keywords:
if (kw.lower() in title.lower() or kw.lower() in desc.lower()) and kw not in stack:
stack.append(kw)
if p_data['learning_type'] in ['코딩형', '데이터분석형', '대시보드·시각화형', '업무자동화형', '프로토타입형', 'AI 활용형']:
if 'Python' not in stack:
stack.append('Python')
return stack
def build_prerequisites(p_data):
cat = p_data['category']
sub = p_data['sub_category']
l_type = p_data['learning_type']
if l_type == '코딩형':
return f"Python 프로그래밍 기초, 데이터 처리 및 알고리즘 구현 기본 지식, {cat} 및 {sub} 분야에 대한 기본 이해"
elif l_type == '데이터분석형':
return f"데이터 분석 도구(Python/Pandas/Excel) 활용 기초, 통계 및 시각화 기본 지식, {cat} 실무 프로세스에 대한 이해"
elif l_type == '대시보드·시각화형':
return f"대시보드/데이터 시각화 툴 활용 기초, 핵심 성과지표(KPI) 분석 및 {sub} 업무에 대한 이해"
elif l_type == '문서·분석형':
return f"{cat} 및 {sub} 관련 군사·군수 표준 절차(SOP)에 대한 기본 이해, 정량/정성 데이터 분석 및 보고서 작성 역량"
elif l_type == '실사용·검증형':
return f"{sub} 현장 점검 및 실무 절차(SOP)에 대한 이해, 체크리스트 기반 교차검증 및 피드백 수행 역량"
elif l_type == '업무자동화형':
return f"업무 프로세스 분석 및 자동화(RPA/스크립팅) 기초, {sub} 데이터 처리 및 무결성 검증에 대한 이해"
else:
return f"생성형 AI 및 데이터 분석 기초, {cat}/{sub} 실무 절차에 대한 기본 이해"
def build_project_json(p_data):
p_id = p_data['p_id']
p_name = p_data['p_name']
category = f"{p_data['category']}/{p_data['sub_category']}"
level_map = {'고급': 3, '중급': 2, '초급': 1, '최고급': 3}
p_level = level_map.get(p_data['p_difficulty'], 3)
total_hours = sum(float(m['예상 소요시간(h)']) for m in p_data['missions'])
all_deliverables = []
for m in p_data['missions']:
d_text = m['산출물 및 저장 위치']
paths = extract_file_paths(d_text)
if paths:
for p in paths:
deliv = f"{p} (필수)"
if deliv not in all_deliverables:
all_deliverables.append(deliv)
else:
deliv = f"{d_text} (필수)"
if deliv not in all_deliverables:
all_deliverables.append(deliv)
war_case = p_data['war_case']
case_context = war_case if war_case != '-' else f"{p_data['category']} 및 {p_data['sub_category']}"
summary = (
f"<h4>프로젝트에서 해결해야 하는 문제</h4>"
f"<p>{case_context} 환경을 분석하여 {p_name}을(를) 위한 핵심 데이터와 분석 모델/절차를 구축하고, "
f"실전 운용 시 발생할 수 있는 오류·불확실성 및 실무 병목을 검증·보정하여 효과적인 의사결정 및 업무 효율화를 달성하는 체계를 구현한다.</p>"
f"<h4>학습 목표</h4>"
f"<p>{p_data['missions'][0]['미션명']}부터 데이터 수집/전처리, 핵심 알고리즘 및 분석 모델 구현, 신뢰도 평가 엔진, "
f"전술/업무 대시보드 및 지휘 통제 인터페이스, 인간 개입(HITL) 의사결정 워크플로우, 가상 스트레스/부하 검증 및 AAR 사후검토 피드백까지 "
f"전 과정을 아우르는 실전형 End-to-End 파이프라인을 완성한다.</p>"
)
mission_lis = "".join([f"<li><p>{m['미션명']}</p></li>" for m in p_data['missions']])
objectives = (
f"<h3>소개</h3>"
f"<p>{case_context} 등 실무 환경에서 요구되는 {p_name} 과제를 수행하여, "
f"실시간 데이터 수집부터 분석, 검증, 시각화 및 의사결정 지원에 이르는 전 과정을 체계적으로 학습하고 개발한다.</p>"
f"<h4>학습자가 수행할 핵심 과정</h4>"
f"<ul>{mission_lis}</ul>"
)
constraints = (
"<h4>AI 분석 결과와 인간 의사결정자 판단의 구분</h4>"
"<ul>"
"<li><p>AI 모델의 단독 판단만으로 최종 결심을 내리지 않으며, 반드시 인간 개입(HITL) 승인 및 검토 절차를 거친다.</p></li>"
"<li><p>오탐 및 미탐 가능성을 고려하여 다차원 신뢰도 점수(Confidence Score)와 불확실성 지표를 함께 제공한다.</p></li>"
"</ul>"
"<h4>군사 보안 및 실전 데이터 취급 원칙</h4>"
"<ul>"
"<li><p>실제 작전 기밀 및 아군 부대/장비의 민감 정보는 사용하지 않으며, 가상 시뮬레이션 및 공개 교육용 데이터셋을 활용한다.</p></li>"
f"<li><p>{case_context} 공개 사례를 기반으로 환경을 모의하되 비인가 장비 제원은 사용하지 않는다.</p></li>"
"</ul>"
"<h4>시스템 신뢰성 및 안전 실패(Fail-safe) 보장</h4>"
"<ul>"
"<li><p>통신 장애나 데이터 결손 등 극한 환경에서도 시스템 다운 없이 안전 실패(Fail-safe) 기준을 만족해야 한다.</p></li>"
"<li><p>오경보율(FAR) 및 데이터 왜곡을 통제하여 실무자의 인지 부하를 최소화한다.</p></li>"
"</ul>"
)
eval_summary = (
"<h4>공통 PASS/FAIL 판정 원칙</h4>"
"<ul>"
"<li><p><strong>수행 증거:</strong> 요구된 데이터 스키마, 전처리 파이프라인, 분석/탐지 모델, UI/문서, HITL 워크플로우, 테스트 코드가 정상 동작하는가?</p></li>"
"<li><p><strong>판단 근거:</strong> 오류 필터링 및 신뢰도/우선순위 산출 기준이 전술적/실무적/수학적 근거와 부합하는가?</p></li>"
"<li><p><strong>앞뒤 연결성:</strong> 데이터 스키마부터 전처리, 분석, UI, HITL, AAR 피드백까지 파이프라인이 유기적으로 연동되는가?</p></li>"
"<li><p><strong>완성도:</strong> 정량적 평가 지표와 정성적 평가 기준을 충족하는가?</p></li>"
"</ul>"
"<h4>프로젝트 완료 조건</h4>"
"<p>10개 필수 미션을 순차적으로 완수하여 최종 End-to-End 통합 파이프라인과 브리핑 패키지를 완성하고 회귀/통합 테스트를 통과해야 최종 PASS이다.</p>"
)
prereq = build_prerequisites(p_data)
skills = [
{"skillId": "competency_AI_문제해결역량_1._문제_분석", "level": p_level, "category": "AI 문제해결역량", "subCategory": "1. 문제 분석"},
{"skillId": "competency_AI_문제해결역량_2._대안_도출", "level": p_level, "category": "AI 문제해결역량", "subCategory": "2. 대안 도출"},
{"skillId": "competency_AI_비판적사고역량_1._결과_검증", "level": p_level, "category": "AI 비판적사고역량", "subCategory": "1. 결과 검증"},
{"skillId": "competency_AI활용역량_1._AI_도구_활용", "level": p_level, "category": "AI활용역량", "subCategory": "1. AI 도구 활용"},
{"skillId": "competency_AI활용역량_2._프롬프트_설계", "level": max(1, p_level - 1), "category": "AI활용역량", "subCategory": "2. 프롬프트 설계"}
]
missions_list = []
for m in p_data['missions']:
seq = int(m['미션 번호'])
m_id = m['미션 ID']
m_title = m['미션명']
m_hours = float(m['예상 소요시간(h)'])
m_desc = m['미션 설명']
m_deliv_raw = m['산출물 및 저장 위치']
m_quant = m['정량적 평가']
m_qual = m['정성적 평가']
m_track = m['진행 추적 및 완료 기준']
m_verify = m['검증 방법']
m_improve = m['개선 및 피드백 방안']
m_diff = m['미션 난이도']
m_comp = m['복잡도']
m_prog = m['진행률']
m_paths = extract_file_paths(m_deliv_raw)
m_deliv_items = [f"{p} (필수)" for p in m_paths] if m_paths else [f"{m_deliv_raw} (필수)"]
m_overview = f"<p><strong>{m_title}</strong></p><p>{m_desc}</p>"
m_objectives = (
f"<h3>소개</h3>"
f"<p>{case_context} 환경을 바탕으로 {m_title} 과제를 수행한다.</p>"
f"<h4>학습자가 수행할 핵심 과정</h4>"
f"<ul>"
f"<li><p>{m_desc}</p></li>"
f"<li><p>산출물 작성: {m_deliv_raw}</p></li>"
f"<li><p>검증 및 완료: {m_verify} 및 {m_track}</p></li>"
f"</ul>"
)
m_scenario = (
f"<h4>미션 배경</h4>"
f"<p>{m_desc}</p>"
f"<p><strong>전쟁/사례 구분:</strong> {case_context}</p>"
f"<p><strong>학습 유형 및 복잡도:</strong> {p_data['learning_type']} (난이도: {m_diff}, 복잡도: {m_comp}, 진행률: {m_prog})</p>"
f"<p><strong>산출물 및 저장 위치:</strong> {m_deliv_raw}</p>"
)
m_materials = m_paths if m_paths else [m_deliv_raw]
m_material_text = (
f"<p><strong>미션 산출물 및 저장 위치</strong></p>"
f"<ul><li><p><code>{m_deliv_raw}</code></p></li></ul>"
f"<p><strong>검증 및 개선 방안</strong></p>"
f"<ul>"
f"<li><p>검증 방법: {m_verify}</p></li>"
f"<li><p>개선 및 피드백 방안: {m_improve}</p></li>"
f"</ul>"
)
m_tech = extract_tech_stack(p_data, m)
m_eval_keys = [
(
f"<h4>평가 질문 (PASS/FAIL)</h4>"
f"<p><strong>[정량적 평가] {m_quant}</strong></p>"
f"<h4>PASS 증거</h4>"
f"<p>정량적 지표({m_quant})를 달성하고 단위 테스트 및 실행 결과가 성공적으로 확인되었다.</p>"
f"<h4>보완이 필요한 상태</h4>"
f"<p>정량적 성능 지표가 기준에 미달하거나 실행 중 에러가 발생하는 경우.</p>"
f"<h4>보완 방법</h4>"
f"<p>{m_improve}을(를) 적용하여 성능 및 파라미터를 보정한다.</p>"
),
(
f"<h4>평가 질문 (PASS/FAIL)</h4>"
f"<p><strong>[정성적 평가] {m_qual} 기준을 충족하였는가?</strong></p>"
f"<h4>PASS 증거</h4>"
f"<p>{case_context} 환경 및 작전/군수 실무 요구사항에 부합하는 알고리즘 논리와 타당성이 확보되었다.</p>"
f"<h4>보완이 필요한 상태</h4>"
f"<p>실무 환경에 대한 고려가 부족하거나 판단 기준이 모호한 경우.</p>"
f"<h4>보완 방법</h4>"
f"<p>실무 환경 변수와 판단 기준을 명세서 및 코드에 보강한다.</p>"
),
(
f"<h4>평가 질문 (PASS/FAIL)</h4>"
f"<p><strong>[진행 추적 및 완료 기준] {m_track}을 완수하였는가?</strong></p>"
f"<h4>PASS 증거</h4>"
f"<p>요구된 산출물({m_deliv_raw})이 지정된 경로에 생성되고 {m_verify}를 통과하였다.</p>"
f"<h4>보완이 필요한 상태</h4>"
f"<p>산출물이 미완성이거나 검증 절차를 통과하지 못한 경우.</p>"
f"<h4>보완 방법</h4>"
f"<p>{m_verify} 절차를 재수행하여 발견된 결함을 수정하고 문서를 완성한다.</p>"
)
]
m_eval_text = (
f"<h4>미션 판정</h4>"
f"<p><strong>평가 구분:</strong> 필수</p>"
f"<p><strong>난이도 / 복잡도:</strong> {m_diff} / {m_comp} (진행률: {m_prog})</p>"
f"<h4>미션 PASS 조건</h4>"
f"<ul>"
f"<li><p>정량적 기준: {m_quant}</p></li>"
f"<li><p>정성적 기준: {m_qual}</p></li>"
f"<li><p>진행 추적 및 완료: {m_track}</p></li>"
f"<li><p>검증 방법 통과: {m_verify}</p></li>"
f"</ul>"
)
m_ai_guide = {
"allow": [
"환경 분석 및 데이터 전처리 알고리즘 가이드 요청",
"단위 테스트 및 성능 검증 스크립트 작성 보조",
"오경보 필터링 및 신뢰도 점수 산출 수식 검토"
],
"rules": [
"군사 기밀 및 실제 부대/기관 민감 정보는 절대 입력하지 않는다.",
"AI 분석 결과에 대해 최종 인간 검토(HITL) 원칙을 유지한다.",
"주어진 가상 시뮬레이션 데이터셋과 스키마 규격을 준수한다."
],
"forbid": [
"실제 작전/행정 기밀 데이터 입력",
"인간 검토 없는 무조건적인 자동 결심 로직 구현",
"검증되지 않은 임의의 데이터 조작"
]
}
missions_list.append({
"id": m_id,
"sequence": seq,
"title": m_title,
"durationHours": m_hours,
"overview": m_overview,
"objectives": m_objectives,
"scenario": m_scenario,
"attachments": [],
"materials": m_materials,
"materialText": m_material_text,
"techStack": m_tech,
"deliverables": m_deliv_items,
"evaluationKeys": m_eval_keys,
"evaluationTypes": ["REQUIRED", "REQUIRED", "REQUIRED"],
"evaluationText": m_eval_text,
"aiGuidelines": m_ai_guide,
"guideSteps": []
})
project_json = {
"version": "1.0.0",
"exportedAt": "2026-09-30T14:10:00.000Z",
"id": p_id,
"title": p_name,
"category": category,
"level": p_level,
"durationDays": 5,
"requiredHours": total_hours,
"status": "COMPLETED",
"isRecommended": False,
"summary": summary,
"objectives": objectives,
"deliverables": all_deliverables,
"constraints": constraints,
"evalSummary": eval_summary,
"prerequisites": prereq,
"refFiles": [],
"refText": "",
"projectSkills": skills,
"prerequisiteVods": [],
"missions": missions_list
}
return project_json
def generate_projects(start_no=1, end_no=60):
os.makedirs('import', exist_ok=True)
projects = parse_missions_md('data/missions02.md')
target_nos = list(range(start_no, end_no + 1))
generated_files = []
for p_no in target_nos:
if p_no in projects:
p_data = projects[p_no]
p_json = build_project_json(p_data)
filename = f"import/{p_data['p_id']}.json"
with open(filename, 'w', encoding='utf-8') as f:
json.dump(p_json, f, ensure_ascii=False, indent=2)
print(f"[{p_no:02d}/60] Generated {filename} ({p_data['p_id']}: {p_data['p_name']})")
generated_files.append(filename)
else:
print(f"Project No. {p_no} not found in missions02.md!")
return generated_files
if __name__ == '__main__':
generate_projects(1, 60)