455 lines
28 KiB
JavaScript
455 lines
28 KiB
JavaScript
const path = require('path');
|
|
module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules'));
|
|
const PptxGenJS = require('pptxgenjs');
|
|
|
|
async function main() {
|
|
const pres = new PptxGenJS();
|
|
pres.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 });
|
|
pres.layout = 'CUSTOM_16x9';
|
|
|
|
const C = {
|
|
bgDark: '0D1B2A',
|
|
bgCard: '1B2838',
|
|
bgCardAlt: '152232',
|
|
primary: '00BFA5',
|
|
primaryLight: '1A3D4A',
|
|
accent: 'FF6F61',
|
|
accentYellow: 'FFB74D',
|
|
white: 'FFFFFF',
|
|
gray: '8899AA',
|
|
grayLight: 'B0BEC5',
|
|
line: '2A3E52',
|
|
blue: '42A5F5',
|
|
green: '66BB6A',
|
|
red: 'EF5350',
|
|
};
|
|
const F = 'Arial';
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// SLIDE 1: 표지
|
|
// ═══════════════════════════════════════════════════
|
|
const s1 = pres.addSlide();
|
|
s1.background = { fill: C.bgDark };
|
|
|
|
// 상단 얇은 악센트 라인
|
|
s1.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.04, fill: { color: C.primary } });
|
|
|
|
// 좌측 포인트 바
|
|
s1.addShape(pres.ShapeType.rect, { x: 0.8, y: 1.5, w: 0.06, h: 1.8, fill: { color: C.primary } });
|
|
|
|
// SAM BI 로고
|
|
s1.addImage({ path: '/home/aweso/sam/docs/assets/bi/sam_bi_white.png', x: 0.8, y: 0.5, w: 1.2, h: 0.6 });
|
|
|
|
// 메인 타이틀
|
|
s1.addText('특허 출원 브리핑', {
|
|
x: 1.1, y: 1.55, w: 7, h: 0.7,
|
|
fontSize: 34, bold: true, color: C.white, fontFace: F
|
|
});
|
|
s1.addText('고객사별 맞춤형 ERP/MES 자동 구성 방법', {
|
|
x: 1.1, y: 2.2, w: 7, h: 0.5,
|
|
fontSize: 16, color: C.primary, fontFace: F
|
|
});
|
|
s1.addText('변리사 제출용 기술 자료 (축약본)', {
|
|
x: 1.1, y: 2.75, w: 7, h: 0.4,
|
|
fontSize: 12, color: C.gray, fontFace: F
|
|
});
|
|
|
|
// 하단 정보
|
|
s1.addShape(pres.ShapeType.rect, { x: 0, y: 4.7, w: 10, h: 0.02, fill: { color: C.line } });
|
|
s1.addText('(주)코드브릿지엑스', {
|
|
x: 0.8, y: 4.85, w: 3, h: 0.35,
|
|
fontSize: 12, bold: true, color: C.grayLight, fontFace: F
|
|
});
|
|
s1.addText('2026-03-20', {
|
|
x: 6, y: 4.85, w: 3.2, h: 0.35,
|
|
fontSize: 11, color: C.gray, align: 'right', fontFace: F
|
|
});
|
|
|
|
// 대외비
|
|
addConfidential(s1, pres);
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// SLIDE 2: 특허 전략 — 2축 구조
|
|
// ═══════════════════════════════════════════════════
|
|
const s2 = pres.addSlide();
|
|
s2.background = { fill: C.bgDark };
|
|
addHeader(s2, pres, '특허 전략 — 2축 구조', C);
|
|
addConfidential(s2, pres);
|
|
addFooter(s2, pres, C, '2 / 6');
|
|
|
|
// 축1 카드
|
|
const ax1x = 0.4, ax1y = 1.05, ax1w = 4.5, ax1h = 3.65;
|
|
s2.addShape(pres.ShapeType.roundRect, { x: ax1x, y: ax1y, w: ax1w, h: ax1h, rectRadius: 0.12, fill: { color: '0D2818' }, line: { color: '1B5E20', width: 1.2 } });
|
|
// 축1 헤더
|
|
s2.addShape(pres.ShapeType.roundRect, { x: ax1x, y: ax1y, w: ax1w, h: 0.45, rectRadius: 0.12, fill: { color: '1B5E20' } });
|
|
s2.addShape(pres.ShapeType.rect, { x: ax1x, y: ax1y + 0.3, w: ax1w, h: 0.15, fill: { color: '1B5E20' } });
|
|
s2.addText([
|
|
{ text: ' AXIS 1 ', options: { fontSize: 9, bold: true, color: 'A5D6A7' } },
|
|
{ text: ' 플랫폼 방법특허 (BM 발명)', options: { fontSize: 11, bold: true, color: C.white } },
|
|
], { x: ax1x + 0.1, y: ax1y + 0.02, w: ax1w - 0.2, h: 0.4, fontFace: F });
|
|
|
|
// 축1 설명
|
|
s2.addText('"고객사 업무 데이터를 AI로 분석하여\n맞춤형 ERP/MES를 자동 구성하는 방법"', {
|
|
x: ax1x + 0.2, y: ax1y + 0.55, w: ax1w - 0.4, h: 0.55,
|
|
fontSize: 9.5, italic: true, color: C.primary, fontFace: F, lineSpacingMultiple: 1.3
|
|
});
|
|
|
|
const axis1Items = [
|
|
['비대면 3채널 수집', '파일 + 설문 + 음성 인터뷰'],
|
|
['AI 패턴 분석', 'LLM + 20만줄 도메인 지식'],
|
|
['레시피 기반 자동 초기화', 'TenantBootstrapper 4단계'],
|
|
['동적 필드 3계층', 'page → section → field'],
|
|
['Zero-Config 수식 라우팅', '파일 존재만으로 자동 발견'],
|
|
];
|
|
axis1Items.forEach((item, i) => {
|
|
const iy = ax1y + 1.2 + i * 0.48;
|
|
s2.addShape(pres.ShapeType.roundRect, { x: ax1x + 0.15, y: iy, w: ax1w - 0.3, h: 0.4, rectRadius: 0.06, fill: { color: '0F2D1A' } });
|
|
s2.addShape(pres.ShapeType.ellipse, { x: ax1x + 0.25, y: iy + 0.08, w: 0.24, h: 0.24, fill: { color: '2E7D32' } });
|
|
s2.addText(String(i + 1), { x: ax1x + 0.25, y: iy + 0.08, w: 0.24, h: 0.24, fontSize: 8, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: F });
|
|
s2.addText(item[0], { x: ax1x + 0.6, y: iy + 0.02, w: 2, h: 0.18, fontSize: 9, bold: true, color: C.white, fontFace: F });
|
|
s2.addText(item[1], { x: ax1x + 0.6, y: iy + 0.2, w: 3.6, h: 0.16, fontSize: 7.5, color: C.gray, fontFace: F });
|
|
});
|
|
|
|
// 최우선 배지
|
|
s2.addShape(pres.ShapeType.roundRect, { x: ax1x + ax1w - 1.2, y: ax1y + 0.55, w: 1, h: 0.28, rectRadius: 0.04, fill: { color: C.accent } });
|
|
s2.addText('최우선', { x: ax1x + ax1w - 1.2, y: ax1y + 0.55, w: 1, h: 0.28, fontSize: 9, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
// 축2 카드
|
|
const ax2x = 5.1, ax2y = 1.05, ax2w = 4.5, ax2h = 2.5;
|
|
s2.addShape(pres.ShapeType.roundRect, { x: ax2x, y: ax2y, w: ax2w, h: ax2h, rectRadius: 0.12, fill: { color: '1A1A2E' }, line: { color: '37474F', width: 1 } });
|
|
s2.addShape(pres.ShapeType.roundRect, { x: ax2x, y: ax2y, w: ax2w, h: 0.45, rectRadius: 0.12, fill: { color: '37474F' } });
|
|
s2.addShape(pres.ShapeType.rect, { x: ax2x, y: ax2y + 0.3, w: ax2w, h: 0.15, fill: { color: '37474F' } });
|
|
s2.addText([
|
|
{ text: ' AXIS 2 ', options: { fontSize: 9, bold: true, color: C.grayLight } },
|
|
{ text: ' 개별 알고리즘 특허', options: { fontSize: 11, bold: true, color: C.white } },
|
|
], { x: ax2x + 0.1, y: ax2y + 0.02, w: ax2w - 0.2, h: 0.4, fontFace: F });
|
|
|
|
const axis2Items = [
|
|
['BOM 수식 엔진', '1,948줄 · 10단계 견적 자동화'],
|
|
['절곡 공정 최적 배분', '1,171줄 · 낭비 15%→5%'],
|
|
['건기원 실적신고', '품질검사→엑셀 자동 생성'],
|
|
['신용도 이중 평가', '외부(쿠콘)+내부(거래이력)'],
|
|
];
|
|
axis2Items.forEach((item, i) => {
|
|
const iy = ax2y + 0.55 + i * 0.45;
|
|
s2.addText('•', { x: ax2x + 0.25, y: iy, w: 0.2, h: 0.35, fontSize: 10, color: C.blue, fontFace: F });
|
|
s2.addText(item[0], { x: ax2x + 0.45, y: iy + 0.02, w: 2, h: 0.16, fontSize: 9, bold: true, color: C.grayLight, fontFace: F });
|
|
s2.addText(item[1], { x: ax2x + 0.45, y: iy + 0.18, w: 3.8, h: 0.14, fontSize: 7.5, color: C.gray, fontFace: F });
|
|
});
|
|
|
|
// 선행기술 리스크 박스
|
|
const riskY = 3.7;
|
|
s2.addShape(pres.ShapeType.roundRect, { x: ax2x, y: riskY, w: ax2w, h: 1, rectRadius: 0.1, fill: { color: '2D1515' }, line: { color: '5D3030', width: 0.8 } });
|
|
s2.addText('선행기술 리스크', { x: ax2x + 0.2, y: riskY + 0.06, w: 2.5, h: 0.28, fontSize: 9, bold: true, color: C.accent, fontFace: F });
|
|
s2.addText('젠소프트 "AI 기반 하이퍼 오토메이션" 특허가 유사', {
|
|
x: ax2x + 0.2, y: riskY + 0.35, w: ax2w - 0.4, h: 0.2, fontSize: 8, color: C.grayLight, fontFace: F
|
|
});
|
|
s2.addText('대응: 컨셉이 아닌 구체적 처리 흐름 + 산업 특화로 차별화', {
|
|
x: ax2x + 0.2, y: riskY + 0.6, w: ax2w - 0.4, h: 0.2, fontSize: 8, bold: true, color: C.accentYellow, fontFace: F
|
|
});
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// SLIDE 3: 5단계 자동화 파이프라인
|
|
// ═══════════════════════════════════════════════════
|
|
const s3 = pres.addSlide();
|
|
s3.background = { fill: C.bgDark };
|
|
addHeader(s3, pres, '5단계 자동화 파이프라인 — 청구항 핵심', C);
|
|
addConfidential(s3, pres);
|
|
addFooter(s3, pres, C, '3 / 6');
|
|
|
|
const steps = [
|
|
{ num: '1', title: '로우데이터\n수집', sub: '비대면 3채널', detail: '견적서 파일\n설문 응답\n음성 인터뷰', time: '1~2일', color: '1565C0' },
|
|
{ num: '2', title: '전처리\n정규화', sub: '데이터 변환', detail: '파일 파싱\n응답 정규화\nSTT 키워드', time: '자동', color: '00838F' },
|
|
{ num: '3', title: 'AI 분석\n패턴 도출', sub: 'LLM 엔진', detail: '업종 분류\n규모 판별\nBOM 추론', time: '수분', color: '2E7D32' },
|
|
{ num: '4', title: '테넌트 생성\n자동 초기화', sub: 'Bootstrapper', detail: '코드 생성\n메뉴 복제\n레시피 4Step', time: '수초', color: 'E65100' },
|
|
{ num: '5', title: '동적\n커스터마이징', sub: '맞춤 적용', detail: '필드 3계층\n수식 라우팅\n데이터 격리', time: '즉시', color: '6A1B9A' },
|
|
];
|
|
|
|
const stepW = 1.65, stepGap = 0.18, startX = 0.42;
|
|
steps.forEach((st, i) => {
|
|
const sx = startX + i * (stepW + stepGap);
|
|
const sy = 1.1;
|
|
|
|
// 카드 배경
|
|
s3.addShape(pres.ShapeType.roundRect, { x: sx, y: sy, w: stepW, h: 3.35, rectRadius: 0.1, fill: { color: C.bgCard }, line: { color: C.line, width: 0.5 } });
|
|
|
|
// 넘버 서클
|
|
s3.addShape(pres.ShapeType.ellipse, { x: sx + stepW / 2 - 0.22, y: sy + 0.12, w: 0.44, h: 0.44, fill: { color: st.color } });
|
|
s3.addText(st.num, { x: sx + stepW / 2 - 0.22, y: sy + 0.12, w: 0.44, h: 0.44, fontSize: 16, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
// 제목
|
|
s3.addText(st.title, { x: sx + 0.05, y: sy + 0.65, w: stepW - 0.1, h: 0.55, fontSize: 10, bold: true, color: C.white, align: 'center', valign: 'middle', lineSpacingMultiple: 1.1, fontFace: F });
|
|
|
|
// 서브 태그
|
|
s3.addShape(pres.ShapeType.roundRect, { x: sx + 0.2, y: sy + 1.28, w: stepW - 0.4, h: 0.25, rectRadius: 0.04, fill: { color: C.bgCardAlt } });
|
|
s3.addText(st.sub, { x: sx + 0.2, y: sy + 1.28, w: stepW - 0.4, h: 0.25, fontSize: 7.5, color: C.grayLight, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
// 구분선
|
|
s3.addShape(pres.ShapeType.rect, { x: sx + 0.15, y: sy + 1.65, w: stepW - 0.3, h: 0.01, fill: { color: C.line } });
|
|
|
|
// 상세 항목
|
|
s3.addText(st.detail, { x: sx + 0.15, y: sy + 1.75, w: stepW - 0.3, h: 1.0, fontSize: 8, color: C.grayLight, lineSpacingMultiple: 1.5, fontFace: F });
|
|
|
|
// 소요 시간 배지
|
|
s3.addShape(pres.ShapeType.roundRect, { x: sx + 0.25, y: sy + 2.9, w: stepW - 0.5, h: 0.3, rectRadius: 0.04, fill: { color: st.color } });
|
|
s3.addText(st.time, { x: sx + 0.25, y: sy + 2.9, w: stepW - 0.5, h: 0.3, fontSize: 9, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
// 화살표 (마지막 제외)
|
|
if (i < 4) {
|
|
s3.addText('>', { x: sx + stepW, y: sy + 0.85, w: stepGap, h: 0.5, fontSize: 16, bold: true, color: C.primary, align: 'center', valign: 'middle', fontFace: F });
|
|
}
|
|
});
|
|
|
|
// 하단 청구항 요약
|
|
s3.addShape(pres.ShapeType.roundRect, { x: 0.42, y: 4.55, w: 9.16, h: 0.45, rectRadius: 0.06, fill: { color: C.primaryLight }, line: { color: C.primary, width: 0.5 } });
|
|
s3.addText([
|
|
{ text: '청구항 핵심: ', options: { fontSize: 8, bold: true, color: C.primary } },
|
|
{ text: '(a) 3채널 수집 → (b) 정규화 → (c) AI 패턴 도출 → (d) 레시피 기반 초기화 → (e) 동적 조정 + 행 수준 격리', options: { fontSize: 8, color: C.grayLight } },
|
|
], { x: 0.6, y: 4.55, w: 8.8, h: 0.45, valign: 'middle', fontFace: F });
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// SLIDE 4: As-Is / To-Be 핵심 비교
|
|
// ═══════════════════════════════════════════════════
|
|
const s4 = pres.addSlide();
|
|
s4.background = { fill: C.bgDark };
|
|
addHeader(s4, pres, 'As-Is / To-Be 핵심 비교', C);
|
|
addConfidential(s4, pres);
|
|
addFooter(s4, pres, C, '4 / 6');
|
|
|
|
// 왼쪽: 지표 대조표
|
|
const tblX = 0.35, tblY = 1.05, tblW = 5.9;
|
|
|
|
// 테이블 헤더
|
|
s4.addShape(pres.ShapeType.roundRect, { x: tblX, y: tblY, w: tblW, h: 0.38, rectRadius: 0.08, fill: { color: '1B3A5C' } });
|
|
s4.addText('항목', { x: tblX + 0.1, y: tblY, w: 1.6, h: 0.38, fontSize: 8, bold: true, color: C.grayLight, valign: 'middle', fontFace: F });
|
|
s4.addText('기존 방식', { x: tblX + 1.7, y: tblY, w: 1.6, h: 0.38, fontSize: 8, bold: true, color: C.accent, align: 'center', valign: 'middle', fontFace: F });
|
|
s4.addText('SAM', { x: tblX + 3.3, y: tblY, w: 1.4, h: 0.38, fontSize: 8, bold: true, color: C.primary, align: 'center', valign: 'middle', fontFace: F });
|
|
s4.addText('개선률', { x: tblX + 4.7, y: tblY, w: 1.1, h: 0.38, fontSize: 8, bold: true, color: C.accentYellow, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
const rows = [
|
|
['ERP 초기 구축', '6개월~1년', '1주일', '31배'],
|
|
['견적 1건 작성', '3~5시간', '10초', '1,300배'],
|
|
['신규 업체 온보딩', '2주 (현장방문)', '1일 (비대면)', '14배'],
|
|
['업종 커스터마이징', '코드포크 (수개월)', '설정 변경', '∞'],
|
|
['도입 비용', '5,800만~1.5억', '월 과금', '10배+'],
|
|
['도입 실패율', '40~60%', '0% (2사 실증)', '∞'],
|
|
];
|
|
|
|
rows.forEach((row, i) => {
|
|
const ry = tblY + 0.42 + i * 0.42;
|
|
const bgColor = i % 2 === 0 ? C.bgCard : C.bgCardAlt;
|
|
s4.addShape(pres.ShapeType.rect, { x: tblX, y: ry, w: tblW, h: 0.4, fill: { color: bgColor } });
|
|
s4.addText(row[0], { x: tblX + 0.1, y: ry, w: 1.6, h: 0.4, fontSize: 8.5, color: C.white, valign: 'middle', fontFace: F });
|
|
s4.addText(row[1], { x: tblX + 1.7, y: ry, w: 1.6, h: 0.4, fontSize: 8.5, color: C.grayLight, align: 'center', valign: 'middle', fontFace: F });
|
|
s4.addText(row[2], { x: tblX + 3.3, y: ry, w: 1.4, h: 0.4, fontSize: 8.5, bold: true, color: C.primary, align: 'center', valign: 'middle', fontFace: F });
|
|
s4.addText(row[3], { x: tblX + 4.7, y: ry, w: 1.1, h: 0.4, fontSize: 9, bold: true, color: C.accentYellow, align: 'center', valign: 'middle', fontFace: F });
|
|
});
|
|
|
|
// 오른쪽: 비용 절감 카드
|
|
const costX = 6.5, costY = 1.05, costW = 3.2, costH = 3.7;
|
|
s4.addShape(pres.ShapeType.roundRect, { x: costX, y: costY, w: costW, h: costH, rectRadius: 0.12, fill: { color: C.bgCard }, line: { color: C.primary, width: 1 } });
|
|
|
|
// 비용 카드 헤더
|
|
s4.addText('연간 비용 절감 (1개사)', { x: costX + 0.15, y: costY + 0.1, w: costW - 0.3, h: 0.3, fontSize: 9, bold: true, color: C.primary, fontFace: F });
|
|
s4.addShape(pres.ShapeType.rect, { x: costX + 0.15, y: costY + 0.42, w: costW - 0.3, h: 0.01, fill: { color: C.line } });
|
|
|
|
const costItems = [
|
|
['견적 인건비', '3,750만'],
|
|
['절곡 오류 재작업', '600만'],
|
|
['원자재 낭비', '1,800만'],
|
|
['단가/품질 관리', '1,680만'],
|
|
];
|
|
costItems.forEach((ci, i) => {
|
|
const cy = costY + 0.5 + i * 0.45;
|
|
s4.addShape(pres.ShapeType.roundRect, { x: costX + 0.15, y: cy, w: costW - 0.3, h: 0.38, rectRadius: 0.05, fill: { color: C.bgCardAlt } });
|
|
s4.addText(ci[0], { x: costX + 0.25, y: cy, w: 1.5, h: 0.38, fontSize: 8, color: C.grayLight, valign: 'middle', fontFace: F });
|
|
s4.addText(ci[1], { x: costX + 1.8, y: cy, w: 1.2, h: 0.38, fontSize: 9, bold: true, color: C.green, align: 'right', valign: 'middle', fontFace: F });
|
|
});
|
|
|
|
// 합계
|
|
s4.addShape(pres.ShapeType.rect, { x: costX + 0.15, y: costY + 2.35, w: costW - 0.3, h: 0.01, fill: { color: C.primary } });
|
|
s4.addShape(pres.ShapeType.roundRect, { x: costX + 0.15, y: costY + 2.45, w: costW - 0.3, h: 0.55, rectRadius: 0.08, fill: { color: C.primaryLight } });
|
|
s4.addText('연간 절감 합계', { x: costX + 0.25, y: costY + 2.48, w: 1.5, h: 0.22, fontSize: 8, color: C.grayLight, fontFace: F });
|
|
s4.addText('7,830만원/년', { x: costX + 0.25, y: costY + 2.68, w: costW - 0.5, h: 0.28, fontSize: 16, bold: true, color: C.primary, fontFace: F });
|
|
|
|
// 실증 사례 배지
|
|
s4.addShape(pres.ShapeType.roundRect, { x: costX + 0.15, y: costY + 3.15, w: costW - 0.3, h: 0.4, rectRadius: 0.06, fill: { color: '1A2E1A' }, line: { color: '2E7D32', width: 0.5 } });
|
|
s4.addText([
|
|
{ text: '실증: ', options: { fontSize: 8, bold: true, color: C.green } },
|
|
{ text: '경동기업(2025-12~)\n주일기업(2025-09~) 운영 중', options: { fontSize: 7.5, color: C.grayLight } },
|
|
], { x: costX + 0.25, y: costY + 3.15, w: costW - 0.5, h: 0.4, valign: 'middle', fontFace: F });
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// SLIDE 5: 선행기술 대비 독창성
|
|
// ═══════════════════════════════════════════════════
|
|
const s5 = pres.addSlide();
|
|
s5.background = { fill: C.bgDark };
|
|
addHeader(s5, pres, '선행기술 대비 독창성', C);
|
|
addConfidential(s5, pres);
|
|
addFooter(s5, pres, C, '5 / 6');
|
|
|
|
// 좌측: 비교표
|
|
const cmpX = 0.35, cmpY = 1.05, cmpW = 5.3;
|
|
|
|
// 비교표 헤더
|
|
s5.addShape(pres.ShapeType.roundRect, { x: cmpX, y: cmpY, w: cmpW, h: 0.38, rectRadius: 0.08, fill: { color: '1B3A5C' } });
|
|
s5.addText('기술 요소', { x: cmpX + 0.1, y: cmpY, w: 2, h: 0.38, fontSize: 8, bold: true, color: C.grayLight, valign: 'middle', fontFace: F });
|
|
s5.addText('젠소프트', { x: cmpX + 2.2, y: cmpY, w: 0.9, h: 0.38, fontSize: 7.5, bold: true, color: C.grayLight, align: 'center', valign: 'middle', fontFace: F });
|
|
s5.addText('이카운트', { x: cmpX + 3.1, y: cmpY, w: 0.9, h: 0.38, fontSize: 7.5, bold: true, color: C.grayLight, align: 'center', valign: 'middle', fontFace: F });
|
|
s5.addText('SAM', { x: cmpX + 4.05, y: cmpY, w: 1.1, h: 0.38, fontSize: 8, bold: true, color: C.primary, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
const compRows = [
|
|
['비대면 3채널 수집', 'X', 'X', 'O'],
|
|
['한글 초성 코드 생성', 'X', 'X', 'O'],
|
|
['레시피 멱등적 초기화', 'X', 'X', 'O'],
|
|
['동적 필드 3계층', '△', '△', 'O'],
|
|
['DB 수준 조건부 렌더링', 'X', 'X', 'O'],
|
|
['Zero-Config 수식 라우팅', 'X', 'X', 'O'],
|
|
['행 수준 자동 격리 (267모델)', '△', 'X', 'O'],
|
|
['4계층 AI 프롬프트 엔진', 'X', 'X', 'O'],
|
|
['자연어 트리거 배포 자동화', 'X', 'X', 'O'],
|
|
];
|
|
|
|
compRows.forEach((row, i) => {
|
|
const ry = cmpY + 0.42 + i * 0.36;
|
|
const bgColor = i % 2 === 0 ? C.bgCard : C.bgCardAlt;
|
|
s5.addShape(pres.ShapeType.rect, { x: cmpX, y: ry, w: cmpW, h: 0.34, fill: { color: bgColor } });
|
|
s5.addText(row[0], { x: cmpX + 0.1, y: ry, w: 2.1, h: 0.34, fontSize: 7.5, color: C.white, valign: 'middle', fontFace: F });
|
|
|
|
[1, 2, 3].forEach((col) => {
|
|
const cx = cmpX + 2.2 + (col - 1) * 0.9 + (col === 3 ? 0.15 : 0);
|
|
const cw = col === 3 ? 1.1 : 0.9;
|
|
const val = row[col];
|
|
let tc, tf;
|
|
if (val === 'O') { tc = C.primary; tf = true; }
|
|
else if (val === '△') { tc = C.accentYellow; tf = false; }
|
|
else { tc = C.gray; tf = false; }
|
|
s5.addText(val === 'O' ? '✓' : val === 'X' ? '—' : '△', { x: cx, y: ry, w: cw, h: 0.34, fontSize: 9, bold: tf, color: tc, align: 'center', valign: 'middle', fontFace: F });
|
|
});
|
|
});
|
|
|
|
// 우측: 프롬프트 엔진 차별점
|
|
const peX = 5.85, peY = 1.05, peW = 3.85;
|
|
s5.addShape(pres.ShapeType.roundRect, { x: peX, y: peY, w: peW, h: 3.9, rectRadius: 0.12, fill: { color: C.bgCard }, line: { color: C.blue, width: 1 } });
|
|
s5.addText('프롬프트 엔지니어링 핵심', { x: peX + 0.15, y: peY + 0.1, w: peW - 0.3, h: 0.3, fontSize: 9.5, bold: true, color: C.blue, fontFace: F });
|
|
s5.addShape(pres.ShapeType.rect, { x: peX + 0.15, y: peY + 0.42, w: peW - 0.3, h: 0.01, fill: { color: C.line } });
|
|
|
|
const peItems = [
|
|
{ icon: '4', label: '계층 규칙 상속', desc: '전역→SAM→서비스→문서\n합산 3,000줄+ 규칙', color: '1565C0' },
|
|
{ icon: '20만', label: '도메인 지식 베이스', desc: '산업 특화 규칙을\nAI가 자동 참조', color: '00838F' },
|
|
{ icon: '57', label: '스킬+에이전트', desc: '45 스킬 + 12 에이전트\n코드 품질·보안·배포 자율 관리', color: '6A1B9A' },
|
|
{ icon: 'L3', label: '서버 안전 제어', desc: 'L1(읽기)·L2(승인)·L3(금지)\n실제 502 사고에서 도출', color: 'C62828' },
|
|
];
|
|
|
|
peItems.forEach((pe, i) => {
|
|
const py = peY + 0.5 + i * 0.85;
|
|
// 아이콘 서클
|
|
s5.addShape(pres.ShapeType.ellipse, { x: peX + 0.2, y: py + 0.1, w: 0.5, h: 0.5, fill: { color: pe.color } });
|
|
s5.addText(pe.icon, { x: peX + 0.2, y: py + 0.1, w: 0.5, h: 0.5, fontSize: pe.icon.length > 2 ? 7 : 12, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: F });
|
|
// 라벨
|
|
s5.addText(pe.label, { x: peX + 0.8, y: py + 0.05, w: 2.8, h: 0.22, fontSize: 9, bold: true, color: C.white, fontFace: F });
|
|
// 설명
|
|
s5.addText(pe.desc, { x: peX + 0.8, y: py + 0.3, w: 2.8, h: 0.4, fontSize: 7.5, color: C.gray, lineSpacingMultiple: 1.3, fontFace: F });
|
|
});
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// SLIDE 6: 실행 로드맵
|
|
// ═══════════════════════════════════════════════════
|
|
const s6 = pres.addSlide();
|
|
s6.background = { fill: C.bgDark };
|
|
addHeader(s6, pres, '실행 로드맵', C);
|
|
addConfidential(s6, pres);
|
|
addFooter(s6, pres, C, '6 / 6');
|
|
|
|
// 타임라인 바
|
|
s6.addShape(pres.ShapeType.rect, { x: 0.7, y: 1.45, w: 8.6, h: 0.04, fill: { color: C.line } });
|
|
|
|
const phases = [
|
|
{ x: 0.7, w: 3.0, num: '1', period: '3~4월', title: '변리사 제출 자료 완성', color: '1565C0',
|
|
items: ['온보딩 자동화 흐름도', 'As-Is/To-Be 비교표', '청구항 초안 공동 작성', '선행기술 벤치마킹'] },
|
|
{ x: 3.9, w: 2.6, num: '2', period: '4월', title: '보완 개발', color: '00838F',
|
|
items: ['신용도 내부 평가 구현', 'AI 동적 설문 프로토타입', '업종 확장 사례 3건+'] },
|
|
{ x: 6.7, w: 2.6, num: '3', period: '5월~', title: '특허 출원', color: '2E7D32',
|
|
items: ['축1 플랫폼 방법특허 출원', '축2 알고리즘 특허 재검토', '명세서 보강 (실사용 데이터)'] },
|
|
];
|
|
|
|
phases.forEach((ph) => {
|
|
// 타임라인 위 노드
|
|
s6.addShape(pres.ShapeType.ellipse, { x: ph.x + ph.w / 2 - 0.15, y: 1.32, w: 0.3, h: 0.3, fill: { color: ph.color } });
|
|
s6.addText(ph.num, { x: ph.x + ph.w / 2 - 0.15, y: 1.32, w: 0.3, h: 0.3, fontSize: 11, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
// 카드
|
|
const cardY = 1.75;
|
|
s6.addShape(pres.ShapeType.roundRect, { x: ph.x, y: cardY, w: ph.w, h: 2.6, rectRadius: 0.1, fill: { color: C.bgCard }, line: { color: ph.color, width: 1 } });
|
|
|
|
// 기간 배지
|
|
s6.addShape(pres.ShapeType.roundRect, { x: ph.x + 0.12, y: cardY + 0.1, w: 0.9, h: 0.28, rectRadius: 0.04, fill: { color: ph.color } });
|
|
s6.addText(ph.period, { x: ph.x + 0.12, y: cardY + 0.1, w: 0.9, h: 0.28, fontSize: 8, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: F });
|
|
|
|
// 제목
|
|
s6.addText(ph.title, { x: ph.x + 1.1, y: cardY + 0.08, w: ph.w - 1.3, h: 0.3, fontSize: 10, bold: true, color: C.white, fontFace: F });
|
|
|
|
// 구분선
|
|
s6.addShape(pres.ShapeType.rect, { x: ph.x + 0.12, y: cardY + 0.48, w: ph.w - 0.24, h: 0.01, fill: { color: C.line } });
|
|
|
|
// 액션 아이템
|
|
ph.items.forEach((item, j) => {
|
|
const iy = cardY + 0.58 + j * 0.45;
|
|
s6.addShape(pres.ShapeType.roundRect, { x: ph.x + 0.12, y: iy, w: ph.w - 0.24, h: 0.38, rectRadius: 0.05, fill: { color: C.bgCardAlt } });
|
|
s6.addShape(pres.ShapeType.rect, { x: ph.x + 0.12, y: iy, w: 0.04, h: 0.38, fill: { color: ph.color } });
|
|
s6.addText(item, { x: ph.x + 0.28, y: iy, w: ph.w - 0.52, h: 0.38, fontSize: 8, color: C.grayLight, valign: 'middle', fontFace: F });
|
|
});
|
|
});
|
|
|
|
// 하단: 시스템 규모 + 업종 확장
|
|
const btmY = 4.55;
|
|
s6.addShape(pres.ShapeType.roundRect, { x: 0.4, y: btmY, w: 9.2, h: 0.6, rectRadius: 0.08, fill: { color: C.primaryLight }, line: { color: C.primary, width: 0.5 } });
|
|
|
|
const stats = [
|
|
['모델 267개', '라우트 1,327개', '서비스 332개', '마이그레이션 551개', '운영 2사'],
|
|
];
|
|
s6.addText([
|
|
{ text: '시스템 규모 ', options: { fontSize: 8, bold: true, color: C.primary } },
|
|
{ text: '모델 267개 | 라우트 1,327개 | 서비스 332개 | 마이그레이션 551개 | 운영 테넌트 2사', options: { fontSize: 8, color: C.grayLight } },
|
|
], { x: 0.55, y: btmY, w: 5.5, h: 0.6, valign: 'middle', fontFace: F });
|
|
|
|
s6.addText([
|
|
{ text: '확장 가능: ', options: { fontSize: 8, bold: true, color: C.accentYellow } },
|
|
{ text: '가구·철강·시공·유통·식품 (파일/설정 추가만으로)', options: { fontSize: 8, color: C.grayLight } },
|
|
], { x: 6.1, y: btmY, w: 3.4, h: 0.6, valign: 'middle', align: 'right', fontFace: F });
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// 저장
|
|
// ═══════════════════════════════════════════════════
|
|
const outPath = '/home/aweso/sam/docs/patent-attorney-briefing-compact.pptx';
|
|
await pres.writeFile({ fileName: outPath });
|
|
console.log('PPTX created: ' + outPath);
|
|
}
|
|
|
|
// ─── Helper Functions ──────────────────────────────────
|
|
function addHeader(slide, pres, title, C) {
|
|
slide.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.04, fill: { color: C.primary } });
|
|
slide.addShape(pres.ShapeType.rect, { x: 0.35, y: 0.35, w: 0.06, h: 0.38, fill: { color: C.primary } });
|
|
slide.addText(title, { x: 0.55, y: 0.28, w: 6, h: 0.5, fontSize: 18, bold: true, color: C.white, fontFace: 'Arial' });
|
|
}
|
|
|
|
function addFooter(slide, pres, C, pageNum) {
|
|
slide.addShape(pres.ShapeType.rect, { x: 0, y: 5.33, w: 10, h: 0.01, fill: { color: C.line } });
|
|
slide.addText('(주)코드브릿지엑스 | SAM 특허 출원 브리핑', {
|
|
x: 0.35, y: 5.35, w: 5, h: 0.25,
|
|
fontSize: 7, color: C.gray, fontFace: 'Arial'
|
|
});
|
|
slide.addText(pageNum, {
|
|
x: 7, y: 5.35, w: 2.7, h: 0.25,
|
|
fontSize: 7, color: C.gray, align: 'right', fontFace: 'Arial'
|
|
});
|
|
}
|
|
|
|
function addConfidential(slide, pres) {
|
|
slide.addShape(pres.ShapeType.roundRect, { x: 8.3, y: 0.15, w: 1.4, h: 0.35, rectRadius: 0.04, fill: { color: 'D32F2F' } });
|
|
slide.addText('CONFIDENTIAL', { x: 8.3, y: 0.12, w: 1.4, h: 0.22, fontSize: 7, bold: true, color: 'FFFFFF', align: 'center', fontFace: 'Arial' });
|
|
slide.addText('대 외 비', { x: 8.3, y: 0.28, w: 1.4, h: 0.22, fontSize: 8, bold: true, color: 'FFCDD2', align: 'center', fontFace: 'Arial' });
|
|
}
|
|
|
|
main().catch(console.error);
|