refactor: 데모 브랜치 패키지 통일 com.example.medilightv2android → com.medithings.vesiscan
사용자앱 (feature/tab-navigation) 과 패키지 이름 일치. namespace + applicationId 둘 다 com.medithings.vesiscan 로 변경 (기존 데모 앱은 재설치 필요). ## 변경 범위 - Kotlin 148 파일: package + import 문 (714 occurrences) - 디렉토리 이동: com/example/medilightv2android → com/medithings/vesiscan (main, test, androidTest 각각) - app/build.gradle.kts: namespace, applicationId - docs/FLAVOR_DEMO_STABLE.md: 참조 갱신 - V41DetectorCH4Test: BvDispatchResult.methodChosen → method (dto field name fix) ## 주의 - applicationId 가 바뀌므로 기존 데모 앱 (com.example.medilightv2android.demo) 은 Android 관점에서 다른 앱으로 취급 — 재설치 시 PIN/설정 초기화됨. - Fresh install 권장. 기존 앱 (com.example...) 은 별도로 uninstall 필요. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
@@ -0,0 +1,738 @@
|
||||
FILE: 주간보고서_dwjang_20260604.pptx
|
||||
SLIDE SIZE: W=14630400 H=8229600 EMU | W=16.00in H=9.00in
|
||||
SLIDE COUNT: 7
|
||||
|
||||
LAYOUTS:
|
||||
[0] 0. 제목 슬라이드
|
||||
[1] 0. 제목 반전 슬라이드
|
||||
[2] 1. 빈 화면
|
||||
[3] 1. 빈 반전 화면
|
||||
[4] 2. 목차 슬라이드
|
||||
[5] 2. 목차 반전 슬라이드
|
||||
|
||||
======================================================================
|
||||
SLIDE 1
|
||||
layout: 0. 제목 반전 슬라이드
|
||||
background: type=BACKGROUND (5)
|
||||
shape_count: 2
|
||||
- shape name='TextBox 1' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=6620256 T=3749039 W=2785378 H=584775 EMU | L=7.24in T=4.10in W=3.05in H=0.64in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='주간 진행 보고'
|
||||
p0 lvl=0 align=None - text='주간 진행 보고'
|
||||
r0 font='나눔고딕 ExtraBold' sz=32.0 b=True i=None c=inherit t='주간 '
|
||||
r1 font='나눔고딕 ExtraBold' sz=32.0 b=True i=None c=inherit t='진행'
|
||||
r2 font='나눔고딕 ExtraBold' sz=32.0 b=True i=None c=inherit t=' '
|
||||
r3 font='나눔고딕 ExtraBold' sz=32.0 b=True i=None c=inherit t='보고'
|
||||
- shape name='TextBox 2' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=6620256 T=4572000 W=3346429 H=369332 EMU | L=7.24in T=5.00in W=3.66in H=0.40in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='2026-06-01 (월) ~ 06-05 (금)'
|
||||
p0 lvl=0 align=None - text='2026-06-01 (월) ~ 06-05 (금)'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#55606C t='2026-06-01 (월) ~ 06-0'
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#55606C t='5'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#55606C t=' ('
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#55606C t='금'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#55606C t=')'
|
||||
|
||||
======================================================================
|
||||
SLIDE 2
|
||||
layout: 1. 빈 화면
|
||||
background: type=BACKGROUND (5)
|
||||
shape_count: 4
|
||||
- shape name='TextBox 1' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=402336 T=173736 W=6236208 H=457200 EMU | L=0.44in T=0.19in W=6.82in H=0.50in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=0 mB=45720
|
||||
text(60)='Android App 진행 보고'
|
||||
p0 lvl=0 align=None - text='Android App 진행 보고'
|
||||
r0 font='나눔고딕 ExtraBold' sz=24.0 b=True i=None c=inherit t='Android App 진행 보고'
|
||||
- shape name='TextBox 3' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=603504 T=868680 W=13240512 H=3842077 EMU | L=0.66in T=0.95in W=14.48in H=4.20in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=True mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='테스트 페이지 + labdb 업로드 + BLE/IMU 파싱 준비 | • 모바일 앱 테스트용 페이지 구현 |'
|
||||
p0 lvl=0 align=None - text='테스트 페이지 + labdb 업로드 + BLE/IMU 파싱 준비'
|
||||
r0 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='테스트'
|
||||
r1 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r2 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='페이지'
|
||||
r3 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' + '
|
||||
r4 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='labdb'
|
||||
r5 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r6 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='업로드'
|
||||
r7 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' + BLE/IMU '
|
||||
r8 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='파싱'
|
||||
r9 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r10 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='준비'
|
||||
p1 lvl=0 align=None - text='• 모바일 앱 테스트용 페이지 구현'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='모바일'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 앱 '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='테스트용'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='페이지'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='구현'
|
||||
p2 lvl=1 align=None - text='– Clinical Measurement 모드 — 라벨 입력 + 6채널 라이브 시각화'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– Clinical Measurement '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='모드'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' — '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='라벨'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='입력'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' + 6채널 '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='라이브'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='시각화'
|
||||
p3 lvl=1 align=None - text='– 폴더 단위 저장 (Downloads/VesiScan_Sessions/)'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='폴더'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='단위'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='저장'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' (Downloads/'
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='VesiScan_Sessions'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='/)'
|
||||
p4 lvl=0 align=None - text='• labdb 업로드 기능 (Phase A+B)'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='labdb'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='업로드'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='기능'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' (Phase A+B)'
|
||||
p5 lvl=1 align=None - text='– EncryptedSharedPreferences로 apiKey 안전 보관'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='EncryptedSharedPreferences로'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='apiKey'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='안전'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='보관'
|
||||
p6 lvl=1 align=None - text='– register → admin 승인 → /upload/json'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– register → admin '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='승인'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' → /upload/'
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='json'
|
||||
p7 lvl=1 align=None - text='– End Session 시 자동 업로드 + 폴더 내 .uploaded 마커 + 수동 재시도 버튼'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– End Session 시 '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='자동'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='업로드'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' + '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='폴더'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 내 .uploaded '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='마커'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' + '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='수동'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='재시도'
|
||||
r12 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r13 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='버튼'
|
||||
p8 lvl=0 align=None - text='• BLE 명령어 수정 및 IMU 파싱 추가'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• BLE '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='명령어'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='수정'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 및 IMU '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='파싱'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='추가'
|
||||
p9 lvl=1 align=None - text='– rim: 응답 188B (15 samples × 12B) BE int16 파싱'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– rim: '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='응답'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 188B (15 samples × 12B) BE int16 '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='파싱'
|
||||
p10 lvl=1 align=None - text='– ImuPacketCollector — Accel ±4g (1/8192 LSB), Gyro ±500dps'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='ImuPacketCollector'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' — Accel ±4g (1/8192 LSB), Gyro ±500dps '
|
||||
- shape name='AutoShape 2' type=AUTO_SHAPE (1) autoshape=
|
||||
geom: L=7162800 T=3962400 W=304800 H=304800 EMU | L=7.83in T=4.33in W=0.33in H=0.33in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=TOP (1) wrap=True mL=91440 mR=91440 mT=45720 mB=45720
|
||||
text(60)=''
|
||||
p0 lvl=0 align=None - text=''
|
||||
- shape name='그림 6' type=PICTURE (13) autoshape=
|
||||
geom: L=9247388 T=297454 W=3157605 H=6841479 EMU | L=10.11in T=0.33in W=3.45in H=7.48in
|
||||
line: color=inherit width_pt=None
|
||||
|
||||
======================================================================
|
||||
SLIDE 3
|
||||
layout: 1. 빈 화면
|
||||
background: type=BACKGROUND (5)
|
||||
shape_count: 5
|
||||
- shape name='TextBox 1' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=402336 T=173736 W=6236208 H=457200 EMU | L=0.44in T=0.19in W=6.82in H=0.50in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=0 mB=45720
|
||||
text(60)='Android App 진행 보고'
|
||||
p0 lvl=0 align=None - text='Android App 진행 보고'
|
||||
r0 font='나눔고딕 ExtraBold' sz=24.0 b=True i=None c=inherit t='Android App 진행 보고'
|
||||
- shape name='TextBox 3' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=603504 T=868680 W=13240512 H=4306307 EMU | L=0.66in T=0.95in W=14.48in H=4.71in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=True mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='labdb 통합 정리 | • dataType "001" JSON 저장 및 표시 | – 내부 임상 R&D '
|
||||
p0 lvl=0 align=None - text='labdb 통합 정리'
|
||||
r0 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='labdb'
|
||||
r1 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r2 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='통합'
|
||||
r3 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r4 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='정리'
|
||||
p1 lvl=0 align=None - text='• dataType "001" JSON 저장 및 표시'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='dataType'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' "001" JSON '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='저장'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 및 '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='표시'
|
||||
p2 lvl=1 align=None - text='– 내부 임상 R&D 구분용 — 외부 일반 VesiScan "000"과 분리'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='내부'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='임상'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' R&D '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='구분용'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' — '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='외부'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='일반'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='VesiScan'
|
||||
r12 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' "000"과 '
|
||||
r13 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='분리'
|
||||
p3 lvl=1 align=None - text='– meta.json / measurement.json 양쪽에 data_type 필드 노출'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='meta.json'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' / '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='measurement.json'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='양쪽에'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='data_type'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='필드'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='노출'
|
||||
p4 lvl=0 align=None - text='• labdb 웹에서 raw JSON 다운로드 가능'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='labdb'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='웹에서'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' raw JSON '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='다운로드'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='가능'
|
||||
p5 lvl=1 align=None - text='– (raw 외 별도 처리 영역은 web 담당 — 미수정)'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– (raw 외 '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='별도'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='처리'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='영역은'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' web '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='담당'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' — '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='미수정'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=')'
|
||||
p6 lvl=0 align=None - text='• 웹 프론트엔드 wall detection 알고리즘 V4.1로 변경'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• 웹 '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='프론트엔드'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' wall detection '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='알고리즘'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' V4.1로 '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='변경'
|
||||
p7 lvl=0 align=None - text='• raw JSON 파일명에 session ID 포함 + 메타데이터 저장'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• raw JSON '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='파일명에'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' session ID '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='포함'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' + '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='메타데이터'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='저장'
|
||||
p8 lvl=1 align=None - text='– 파일명만으로 측정 식별, examiner / posture / step / true_volume'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='파일명만으로'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='측정'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='식별'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=', examiner / posture / step / '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='true_volume'
|
||||
p9 lvl=0 align=None - text='• PostgreSQL JSONB NULL byte 500 에러 해결'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• PostgreSQL JSONB NULL byte 500 '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='에러 해결'
|
||||
p10 lvl=1 align=None - text='– 서버 /var/log/labdb.log 직접 확인 → BLE rid: 응답의 trailing NULL이'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='서버'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' /var/log/labdb.log '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='직접'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='확인'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' → BLE rid: '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='응답의'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' trailing '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='NULL이'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='원인'
|
||||
p11 lvl=1 align=None - text='– BLE 파싱 + LabdbClient 양쪽에 재귀 sanitizer 추가'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– BLE '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='파싱'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' + '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='LabdbClient'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='양쪽에'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='재귀'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' sanitizer '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='추가'
|
||||
- shape name='그림 7' type=PICTURE (13) autoshape=
|
||||
geom: L=9135186 T=3057935 W=5076573 H=4302985 EMU | L=9.99in T=3.34in W=5.55in H=4.71in
|
||||
line: color=inherit width_pt=None
|
||||
- shape name='그림 9' type=PICTURE (13) autoshape=
|
||||
geom: L=7075214 T=582514 W=3633182 H=2356549 EMU | L=7.74in T=0.64in W=3.97in H=2.58in
|
||||
line: color=inherit width_pt=None
|
||||
- shape name='그림 12' type=PICTURE (13) autoshape=
|
||||
geom: L=10834869 T=582514 W=3393195 H=2356549 EMU | L=11.85in T=0.64in W=3.71in H=2.58in
|
||||
line: color=inherit width_pt=None
|
||||
|
||||
======================================================================
|
||||
SLIDE 4
|
||||
layout: 1. 빈 화면
|
||||
background: type=BACKGROUND (5)
|
||||
shape_count: 3
|
||||
- shape name='TextBox 1' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=402336 T=173736 W=6236208 H=457200 EMU | L=0.44in T=0.19in W=6.82in H=0.50in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=0 mB=45720
|
||||
text(60)='Android App 진행 보고'
|
||||
p0 lvl=0 align=None - text='Android App 진행 보고'
|
||||
r0 font='나눔고딕 ExtraBold' sz=24.0 b=True i=None c=inherit t='Android App 진행 보고'
|
||||
- shape name='TextBox 3' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=603504 T=868680 W=13240512 H=5781070 EMU | L=0.66in T=0.95in W=14.48in H=6.32in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=True mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='펌웨어 업데이트 대응 — reb 패킷 신구조 (208B → 210B) | • payload 앞에 ch_in'
|
||||
p0 lvl=0 align=None - text='펌웨어 업데이트 대응 — reb 패킷 신구조 (208B → 210B)'
|
||||
r0 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='펌웨어'
|
||||
r1 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r2 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='업데이트'
|
||||
r3 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r4 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='대응'
|
||||
r5 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' — reb '
|
||||
r6 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='패킷'
|
||||
r7 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r8 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='신구조'
|
||||
r9 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' (208B → 210B)'
|
||||
p1 lvl=0 align=None - text='• payload 앞에 ch_info 2B 추가 = [ch_session 1B] + [ch_num 1B]'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• payload '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='앞에'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='ch_info'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 2B '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='추가'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' = ['
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='ch_session'
|
||||
r8 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 1B] + ['
|
||||
r9 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='ch_num'
|
||||
r10 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 1B]'
|
||||
p2 lvl=1 align=None - text='– [tag 4B][ch_info 2B][num_sample 2B][adc 200B][crc 2B]'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– [tag 4B]['
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='ch_info'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 2B]['
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='num_sample'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 2B]['
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='adc'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 200B]['
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='crc'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 2B]'
|
||||
p3 lvl=0 align=None - text='• 채널/세션 정보로 측정 set 식별'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='채널'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='/'
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='세션'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='정보로'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='측정'
|
||||
r8 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' set '
|
||||
r9 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='식별'
|
||||
p4 lvl=1 align=None - text='– 동일 ch_session = 한 측정 set으로 6개 reb 묶음'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='동일'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='ch_session'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' = 한 '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='측정'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='set으로'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 6개 reb '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='묶음'
|
||||
p5 lvl=1 align=None - text='– ch_num으로 채널 직접 indexing (도착 순서 의존 폐기)'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='ch_num으로'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='채널'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='직접'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' indexing ('
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='도착'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='순서'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='의존'
|
||||
r12 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r13 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='폐기'
|
||||
r14 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=')'
|
||||
p6 lvl=0 align=None - text='• 누락/불일치 측정 set 자동 폐기'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='누락'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='/'
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='불일치'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='측정'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' set '
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='자동'
|
||||
r8 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r9 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='폐기'
|
||||
p7 lvl=1 align=None - text='– session 불일치 / 중복 ch_num / 6채널 중 일부 누락 → 해당 set drop'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– session '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='불일치'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' / '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='중복'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='ch_num'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' / 6채널 중 '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='일부'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='누락'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' → '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='해당'
|
||||
r12 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' set drop'
|
||||
p8 lvl=1 align=None - text='– 다음 정상 set만 처리'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='다음'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='정상'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='set만'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='처리'
|
||||
p9 lvl=0 align=None - text='• 한 곳 수정으로 전 화면 적용'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• 한 곳 '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='수정으로'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 전 '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='화면'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='적용'
|
||||
p10 lvl=1 align=None - text='– 도넛차트(maa?) · placement · 임상(mtb?) 모두 동일 collector'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='도넛차트'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='(maa?) · placement · '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='임상'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='('
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='mtb'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='?) '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='모두'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='동일'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' collector'
|
||||
p11 lvl=1 align=None - text='– PiezoPacketCollector 한 군데만 신구조로 재작성'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='PiezoPacketCollector'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 한 '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='군데만'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='신구조로'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='재작성'
|
||||
p12 lvl=0 align=None - text='• Sensor 측정 시 IMU 값 — 가장 오래된 것 → 가장 최근 것으로 수정'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• Sensor '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='측정'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 시 IMU 값 — '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='가장'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='오래된'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' 것 → '
|
||||
r7 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='가장'
|
||||
r8 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r9 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='최근'
|
||||
r10 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r11 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='것으로'
|
||||
r12 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r13 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='수정'
|
||||
p13 lvl=1 align=None - text='– FIFO 첫 샘플 사용 버그 → 측정 순간 자세 반영을 위해 마지막 샘플로'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– FIFO 첫 '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='샘플'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='사용'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='버그'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' → '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='측정'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='순간'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='자세'
|
||||
r12 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r13 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='반영을'
|
||||
r14 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r15 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='위해'
|
||||
r16 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r17 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='마지막'
|
||||
r18 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r19 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='샘플로'
|
||||
p14 lvl=1 align=None - text=''
|
||||
p15 lvl=1 align=None - text='총 15개 받는데 맨 처음 들어온거는 더 적을 수 있음.'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='총 '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='15'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='개 받는데 맨 처음 '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='들어온거는'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='더 적을 수 있음'
|
||||
r6 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='.'
|
||||
p16 lvl=1 align=None - text='마지막으로 받은 imu값(최신) 을 센서 측정 당시의 imu로 이해하면 될것.'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='마지막으로 받은 '
|
||||
r1 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='imu'
|
||||
r2 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='값'
|
||||
r3 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='('
|
||||
r4 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='최신'
|
||||
r5 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t=') '
|
||||
r6 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='을 센서 측정 당시의 '
|
||||
r7 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='imu'
|
||||
r8 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='로 이해하면 '
|
||||
r9 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='될것'
|
||||
r10 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='.'
|
||||
- shape name='그림 5' type=PICTURE (13) autoshape=
|
||||
geom: L=8661917 T=1550078 W=2991267 H=4534533 EMU | L=9.47in T=1.70in W=3.27in H=4.96in
|
||||
line: color=inherit width_pt=None
|
||||
|
||||
======================================================================
|
||||
SLIDE 5
|
||||
layout: 1. 빈 화면
|
||||
background: type=BACKGROUND (5)
|
||||
shape_count: 3
|
||||
- shape name='TextBox 1' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=402336 T=173736 W=6236208 H=457200 EMU | L=0.44in T=0.19in W=6.82in H=0.50in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=0 mB=45720
|
||||
text(60)='Android App 진행 보고'
|
||||
p0 lvl=0 align=None - text='Android App 진행 보고'
|
||||
r0 font='나눔고딕 ExtraBold' sz=24.0 b=True i=None c=inherit t='Android App 진행 보고'
|
||||
- shape name='TextBox 3' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=603504 T=868680 W=13240512 H=6858000 EMU | L=0.66in T=0.95in W=14.48in H=7.50in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=True mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='ClinicalLive — V4.1 Wall Peak 오버레이 (사내 가시화 요청) | • 사내 임상 테스'
|
||||
p0 lvl=0 align=None - text='ClinicalLive — V4.1 Wall Peak 오버레이 (사내 가시화 요청)'
|
||||
r0 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='ClinicalLive — V4.1 Wall Peak 오버레이 (사내 가'
|
||||
p1 lvl=0 align=None - text='• 사내 임상 테스트 진행자 요청 — 실시간 peak 위치 가시화'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• 사내 임상 테스트 진행자 요청 — 실시간 peak 위치 가시화'
|
||||
p2 lvl=0 align=None - text='• V4.1 wall detection (walldetect.V41Detector)을 매 mtb 사이클마다'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• V4.1 wall detection (walldetect.V41De'
|
||||
p3 lvl=1 align=None - text='– 입력: 6채널 raw ADC + ProbeProfileDto (PiezoMonitoring과 동일 설정'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– 입력: 6채널 raw ADC + ProbeProfileDto (Pi'
|
||||
p4 lvl=1 align=None - text='– 출력: 채널별 antIdx(전벽) / postIdx(후벽) Int?'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– 출력: 채널별 antIdx(전벽) / postIdx(후벽) Int?'
|
||||
p5 lvl=1 align=None - text='– runCatching으로 감싸 detection 실패가 측정 자체에 영향 없도록'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– runCatching으로 감싸 detection 실패가 측정 자체에'
|
||||
p6 lvl=0 align=None - text='• 표시'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• 표시'
|
||||
p7 lvl=1 align=None - text='– 그래프 위 세로선 마커 — ant=green, post=orange (alpha 0.75)'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– 그래프 위 세로선 마커 — ant=green, post=orange'
|
||||
p8 lvl=1 align=None - text='– 채널 헤더 우측 "a{antIdx} p{postIdx}" 컬러 텍스트'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– 채널 헤더 우측 "a{antIdx} p{postIdx}" 컬러 텍스'
|
||||
p9 lvl=1 align=None - text='– 기존 raw max peak 숫자도 그대로 유지'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– 기존 raw max peak 숫자도 그대로 유지'
|
||||
p10 lvl=0 align=None - text='• 저장 데이터는 변경 없음'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• 저장 데이터는 변경 없음'
|
||||
p11 lvl=1 align=None - text='– measurement.json / labdb payload는 그대로 raw ADC'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– measurement.json / labdb payload는 그대로'
|
||||
p12 lvl=1 align=None - text='– V4.1 결과는 화면 표시 전용 — 알고리즘 변경 시 같은 데이터로 재분석'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– V4.1 결과는 화면 표시 전용 — 알고리즘 변경 시 같은 데이터로'
|
||||
- shape name='그림 4' type=PICTURE (13) autoshape=
|
||||
geom: L=7315200 T=3161841 W=6946073 H=3101503 EMU | L=8.00in T=3.46in W=7.60in H=3.39in
|
||||
line: color=inherit width_pt=None
|
||||
|
||||
======================================================================
|
||||
SLIDE 6
|
||||
layout: 1. 빈 화면
|
||||
background: type=BACKGROUND (5)
|
||||
shape_count: 4
|
||||
- shape name='TextBox 1' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=402336 T=173736 W=6236208 H=457200 EMU | L=0.44in T=0.19in W=6.82in H=0.50in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=0 mB=45720
|
||||
text(60)='Android App 진행 보고'
|
||||
p0 lvl=0 align=None - text='Android App 진행 보고'
|
||||
r0 font='나눔고딕 ExtraBold' sz=24.0 b=True i=None c=inherit t='Android App 진행 보고'
|
||||
- shape name='TextBox 3' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=603504 T=868680 W=13240512 H=5586145 EMU | L=0.66in T=0.95in W=14.48in H=6.11in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=True mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='사내 테스트 피드백 반영 — UX 정리 3건 및 오류 수정 | • 도넛차트 색깔 일관성 fix | – 증'
|
||||
p0 lvl=0 align=None - text='사내 테스트 피드백 반영 — UX 정리 3건 및 오류 수정'
|
||||
r0 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='사내'
|
||||
r1 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r2 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='테스트'
|
||||
r3 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r4 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='피드백'
|
||||
r5 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r6 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='반영'
|
||||
r7 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' — UX '
|
||||
r8 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='정리'
|
||||
r9 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' 3건'
|
||||
r10 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕 ExtraBold' sz=28.0 b=True i=None c=#222A33 t='및 오류 수정'
|
||||
p1 lvl=0 align=None - text='• 도넛차트 색깔 일관성 fix'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='도넛차트'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='색깔'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='일관성'
|
||||
r6 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' fix'
|
||||
p2 lvl=1 align=None - text='– 증상: Single scan 309ml(노란색) 후 Auto scan 에서 색깔만 초록색으로 바뀌는 오'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='증상'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=': Single scan 309ml('
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='노란색'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=') 후 Auto scan '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='에서'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='색깔만'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='초록색으로'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='바뀌는 오류'
|
||||
p3 lvl=2 align=None - text='· 표시값(maxVolumeMl)과 색깔(lastVolumeMl) source 불일치'
|
||||
r0 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='· '
|
||||
r1 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='표시값'
|
||||
r2 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='('
|
||||
r3 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='maxVolumeMl'
|
||||
r4 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t=')과 '
|
||||
r5 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='색깔'
|
||||
r6 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='('
|
||||
r7 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='lastVolumeMl'
|
||||
r8 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t=') source '
|
||||
r9 font='나눔고딕' sz=13.0 b=False i=None c=#55606C t='불일치'
|
||||
p4 lvl=1 align=None - text='– 수정: bladderLevel 업데이트도 maxVolumeMl 기준으로 통일'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='수정'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=': '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='bladderLevel'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='업데이트도'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='maxVolumeMl'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='기준으로'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='통일'
|
||||
p5 lvl=0 align=None - text='• Setup 화면 Auto Scan Interval 카드 추가'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• Setup '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='화면'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' Auto Scan Interval '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='카드'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' '
|
||||
r5 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='추가'
|
||||
p6 lvl=1 align=None - text='– PiezoPersonalizationView에 신규 카드 — 600~5000ms 슬라이더 + ±200m'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='PiezoPersonalizationView에'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='신규'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='카드'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' — 600~5000ms '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='슬라이더'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' + ±200ms '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='스테퍼'
|
||||
p7 lvl=1 align=None - text='– 기존 MaxVolume / CatheterThreshold 카드와 동일 톤, 3카드 verticalSc'
|
||||
r0 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='기존'
|
||||
r2 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='MaxVolume'
|
||||
r4 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' / '
|
||||
r5 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='CatheterThreshold'
|
||||
r6 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r7 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='카드와'
|
||||
r8 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' '
|
||||
r9 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='동일'
|
||||
r10 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t=' 톤, 3카드 '
|
||||
r11 font='나눔고딕' sz=15.0 b=False i=None c=#222A33 t='verticalScroll'
|
||||
p8 lvl=0 align=None - text='• BLE 끊김 banner 제거 — Silent Reconnect'
|
||||
r0 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='• BLE '
|
||||
r1 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='끊김'
|
||||
r2 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' banner '
|
||||
r3 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t='제거'
|
||||
r4 font='나눔고딕' sz=18.0 b=True i=None c=#1E88E5 t=' — Silent Reconnect'
|
||||
p9 lvl=1 align=None - text='– PiezoMonitoring / VivamyoMonitoring 양쪽 banner 표시 제거'
|
||||
r0 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='PiezoMonitoring'
|
||||
r2 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t=' '
|
||||
r3 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='/ '
|
||||
r4 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='VivamyoMonitoring'
|
||||
r5 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t=' 양쪽 '
|
||||
r6 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='banner '
|
||||
r7 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='표시 제거'
|
||||
p10 lvl=1 align=None - text='– BleManager.scheduleAutoReconnect()가 이미 백그라운드 재연결 시도'
|
||||
r0 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='BleManager.scheduleAutoReconnect'
|
||||
r2 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='()'
|
||||
r3 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='가 이미 백그라운드 '
|
||||
r4 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='재연결'
|
||||
r5 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t=' 시도'
|
||||
p11 lvl=1 align=None - text='– 측정 일시정지 / 배터리 폴링 재시작 등 다른 처리는 그대로 유지'
|
||||
r0 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='– '
|
||||
r1 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='측정 일시정지 '
|
||||
r2 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='/ '
|
||||
r3 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='배터리 '
|
||||
r4 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t='폴링'
|
||||
r5 font='나눔고딕' sz=15.0 b=None i=None c=#222A33 t=' 재시작 등 다른 처리는 그대로 유지'
|
||||
p12 lvl=0 align=None - text='• 첫 연결시 배터리 잔량 표시가 안되는 오류 수정'
|
||||
r0 font='나눔고딕' sz=None b=True i=None c=#1E88E5 t='• '
|
||||
r1 font='나눔고딕' sz=None b=True i=None c=#1E88E5 t='첫 '
|
||||
r2 font='나눔고딕' sz=None b=True i=None c=#1E88E5 t='연결시'
|
||||
r3 font='나눔고딕' sz=None b=True i=None c=#1E88E5 t=' 배터리 잔량 표시가 안되는 오류 수정'
|
||||
p13 lvl=0 align=None - text=''
|
||||
p14 lvl=0 align=None - text=''
|
||||
p15 lvl=0 align=None - text=''
|
||||
- shape name='그림 5' type=PICTURE (13) autoshape=
|
||||
geom: L=2457674 T=5771838 W=6630325 H=1743318 EMU | L=2.69in T=6.31in W=7.25in H=1.91in
|
||||
line: color=inherit width_pt=None
|
||||
- shape name='그림 7' type=PICTURE (13) autoshape=
|
||||
geom: L=10593990 T=1256249 W=2486422 H=5387248 EMU | L=11.59in T=1.37in W=2.72in H=5.89in
|
||||
line: color=inherit width_pt=None
|
||||
|
||||
======================================================================
|
||||
SLIDE 7
|
||||
layout: 1. 빈 화면
|
||||
background: type=BACKGROUND (5)
|
||||
shape_count: 1
|
||||
- shape name='TextBox 1' type=TEXT_BOX (17) autoshape=
|
||||
geom: L=6243111 T=3530025 W=2144177 H=584775 EMU | L=6.83in T=3.86in W=2.34in H=0.64in
|
||||
fill: type=BACKGROUND (5)
|
||||
line: color=inherit width_pt=None
|
||||
textframe: anchor=None wrap=False mL=0 mR=91440 mT=45720 mB=45720
|
||||
text(60)='감사합니다'
|
||||
p0 lvl=0 align=None - text='감사합니다'
|
||||
r0 font='나눔고딕 ExtraBold' sz=32.0 b=True i=None c=inherit t='감사합니다'
|
||||
@@ -0,0 +1,264 @@
|
||||
"""Extract exact visual design info from the reference PPTX into _design_dump.txt."""
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
from pptx import Presentation
|
||||
from pptx.util import Emu
|
||||
from pptx.dml.color import RGBColor
|
||||
from pptx.enum.shapes import MSO_SHAPE_TYPE
|
||||
from pptx.oxml.ns import qn
|
||||
|
||||
PPT_DIR = Path(__file__).parent
|
||||
SRC = PPT_DIR / "주간보고서_dwjang_20260604.pptx"
|
||||
OUT = PPT_DIR / "_design_dump.txt"
|
||||
|
||||
|
||||
def emu_to_in(v):
|
||||
try:
|
||||
return f"{Emu(v).inches:.2f}"
|
||||
except Exception:
|
||||
return "?"
|
||||
|
||||
|
||||
def fmt_xy(left, top, width, height):
|
||||
return (
|
||||
f"L={left} T={top} W={width} H={height} EMU | "
|
||||
f"L={emu_to_in(left)}in T={emu_to_in(top)}in "
|
||||
f"W={emu_to_in(width)}in H={emu_to_in(height)}in"
|
||||
)
|
||||
|
||||
|
||||
def color_from_fill(fill):
|
||||
"""Best-effort extraction of solid fill color as hex."""
|
||||
try:
|
||||
if fill.type is None:
|
||||
return "none/inherit"
|
||||
# 1 = SOLID per MSO_FILL_TYPE
|
||||
if int(fill.type) == 1:
|
||||
fc = fill.fore_color
|
||||
try:
|
||||
rgb = fc.rgb
|
||||
if rgb is not None:
|
||||
return f"#{str(rgb)}"
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return f"theme:{fc.theme_color}"
|
||||
except Exception:
|
||||
pass
|
||||
return f"type={fill.type}"
|
||||
except Exception as e:
|
||||
return f"err:{e.__class__.__name__}"
|
||||
|
||||
|
||||
def color_from_line(line):
|
||||
try:
|
||||
c = line.color
|
||||
try:
|
||||
rgb = c.rgb
|
||||
if rgb is not None:
|
||||
return f"#{str(rgb)}"
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return f"theme:{c.theme_color}"
|
||||
except Exception:
|
||||
return "inherit"
|
||||
except Exception:
|
||||
return "n/a"
|
||||
|
||||
|
||||
def run_color(run):
|
||||
try:
|
||||
c = run.font.color
|
||||
try:
|
||||
rgb = c.rgb
|
||||
if rgb is not None:
|
||||
return f"#{str(rgb)}"
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return f"theme:{c.theme_color}"
|
||||
except Exception:
|
||||
return "inherit"
|
||||
except Exception:
|
||||
return "inherit"
|
||||
|
||||
|
||||
def slide_bg(slide):
|
||||
"""Try to read slide background fill."""
|
||||
try:
|
||||
bg = slide.background
|
||||
return color_from_fill(bg.fill)
|
||||
except Exception as e:
|
||||
return f"err:{e.__class__.__name__}"
|
||||
|
||||
|
||||
def shape_type_name(shape):
|
||||
try:
|
||||
st = shape.shape_type
|
||||
if st is None:
|
||||
return "None"
|
||||
return str(st)
|
||||
except Exception:
|
||||
return "?"
|
||||
|
||||
|
||||
def autoshape_kind(shape):
|
||||
try:
|
||||
return str(shape.auto_shape_type)
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def dump_text_frame(tf, out_lines, indent=" "):
|
||||
for pi, para in enumerate(tf.paragraphs):
|
||||
lvl = para.level
|
||||
align = para.alignment
|
||||
# Detect bullet via pPr/buChar/buAutoNum
|
||||
pPr = para._pPr
|
||||
bullet = "-"
|
||||
if pPr is not None:
|
||||
if pPr.find(qn("a:buNone")) is not None:
|
||||
bullet = "noBul"
|
||||
elif pPr.find(qn("a:buChar")) is not None:
|
||||
bc = pPr.find(qn("a:buChar"))
|
||||
bullet = f"buChar={bc.get('char')!r}"
|
||||
elif pPr.find(qn("a:buAutoNum")) is not None:
|
||||
bullet = "buAutoNum"
|
||||
runs_info = []
|
||||
full_txt = ""
|
||||
for r in para.runs:
|
||||
t = r.text or ""
|
||||
full_txt += t
|
||||
f = r.font
|
||||
runs_info.append({
|
||||
"text": t,
|
||||
"name": f.name,
|
||||
"size": (f.size.pt if f.size else None),
|
||||
"bold": f.bold,
|
||||
"italic": f.italic,
|
||||
"color": run_color(r),
|
||||
})
|
||||
snippet = full_txt[:60].replace("\n", " ")
|
||||
out_lines.append(
|
||||
f"{indent}p{pi} lvl={lvl} align={align} {bullet} text={snippet!r}"
|
||||
)
|
||||
for ri, info in enumerate(runs_info):
|
||||
tt = info["text"][:40].replace("\n", " ")
|
||||
out_lines.append(
|
||||
f"{indent} r{ri} font={info['name']!r} sz={info['size']} "
|
||||
f"b={info['bold']} i={info['italic']} c={info['color']} t={tt!r}"
|
||||
)
|
||||
|
||||
|
||||
def dump_shape(shape, out_lines, indent=" "):
|
||||
name = shape.name
|
||||
st = shape_type_name(shape)
|
||||
kind = autoshape_kind(shape) if st == "MSO_SHAPE_TYPE.AUTO_SHAPE (1)" else ""
|
||||
try:
|
||||
left, top, width, height = shape.left, shape.top, shape.width, shape.height
|
||||
except Exception:
|
||||
left = top = width = height = None
|
||||
out_lines.append(
|
||||
f"{indent}- shape name={name!r} type={st} autoshape={kind}"
|
||||
)
|
||||
out_lines.append(f"{indent} geom: {fmt_xy(left, top, width, height)}")
|
||||
|
||||
# Fill
|
||||
try:
|
||||
if shape.has_text_frame or st.startswith("MSO_SHAPE_TYPE.AUTO_SHAPE") or st == "MSO_SHAPE_TYPE.TEXT_BOX (17)":
|
||||
fill_c = color_from_fill(shape.fill)
|
||||
out_lines.append(f"{indent} fill: {fill_c}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Line
|
||||
try:
|
||||
line = shape.line
|
||||
lc = color_from_line(line)
|
||||
try:
|
||||
lw = line.width
|
||||
lw_pt = (lw / 12700) if lw else None
|
||||
except Exception:
|
||||
lw_pt = None
|
||||
out_lines.append(f"{indent} line: color={lc} width_pt={lw_pt}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Picture
|
||||
if st == "MSO_SHAPE_TYPE.PICTURE (13)":
|
||||
try:
|
||||
img = shape.image
|
||||
out_lines.append(
|
||||
f"{indent} picture: ext={img.ext} sha1={img.sha1[:10]} "
|
||||
f"size_bytes={len(img.blob)} filename={getattr(img, 'filename', None)!r}"
|
||||
)
|
||||
except Exception as e:
|
||||
out_lines.append(f"{indent} picture: err={e}")
|
||||
|
||||
# Text
|
||||
if shape.has_text_frame:
|
||||
tf = shape.text_frame
|
||||
# vertical anchor
|
||||
try:
|
||||
va = tf.vertical_anchor
|
||||
except Exception:
|
||||
va = None
|
||||
try:
|
||||
wrap = tf.word_wrap
|
||||
except Exception:
|
||||
wrap = None
|
||||
out_lines.append(
|
||||
f"{indent} textframe: anchor={va} wrap={wrap} "
|
||||
f"mL={tf.margin_left} mR={tf.margin_right} mT={tf.margin_top} mB={tf.margin_bottom}"
|
||||
)
|
||||
# Full text first 60 chars
|
||||
full = (shape.text_frame.text or "").replace("\n", " | ")
|
||||
out_lines.append(f"{indent} text(60)={full[:60]!r}")
|
||||
dump_text_frame(tf, out_lines, indent=indent + " ")
|
||||
|
||||
# Group
|
||||
if st == "MSO_SHAPE_TYPE.GROUP (6)":
|
||||
out_lines.append(f"{indent} group children:")
|
||||
for child in shape.shapes:
|
||||
dump_shape(child, out_lines, indent=indent + " ")
|
||||
|
||||
|
||||
def main():
|
||||
prs = Presentation(SRC)
|
||||
lines = []
|
||||
lines.append(f"FILE: {SRC.name}")
|
||||
lines.append(
|
||||
f"SLIDE SIZE: W={prs.slide_width} H={prs.slide_height} EMU | "
|
||||
f"W={emu_to_in(prs.slide_width)}in H={emu_to_in(prs.slide_height)}in"
|
||||
)
|
||||
lines.append(f"SLIDE COUNT: {len(prs.slides)}")
|
||||
lines.append("")
|
||||
# Layouts available
|
||||
lines.append("LAYOUTS:")
|
||||
for i, lay in enumerate(prs.slide_layouts):
|
||||
lines.append(f" [{i}] {lay.name}")
|
||||
lines.append("")
|
||||
# Master fonts / theme colors (best effort)
|
||||
try:
|
||||
theme_xml = prs.slide_masters[0].element.getroottree()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for si, slide in enumerate(prs.slides, start=1):
|
||||
lines.append("=" * 70)
|
||||
lines.append(f"SLIDE {si}")
|
||||
lines.append(f" layout: {slide.slide_layout.name}")
|
||||
lines.append(f" background: {slide_bg(slide)}")
|
||||
lines.append(f" shape_count: {len(slide.shapes)}")
|
||||
for shp in slide.shapes:
|
||||
dump_shape(shp, lines, indent=" ")
|
||||
lines.append("")
|
||||
|
||||
OUT.write_text("\n".join(lines), encoding="utf-8")
|
||||
print(f"WROTE: {OUT} lines={len(lines)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,439 @@
|
||||
"""
|
||||
주간보고서 자동 생성 — 2026-06-08(월) ~ 06-12(금) 작업분.
|
||||
|
||||
기존 양식 (주간보고서_dwjang_20260604.pptx) 의 슬라이드 마스터/레이아웃을
|
||||
그대로 가져다 쓰고, 컨텐츠만 교체.
|
||||
|
||||
디자인 규칙 (기존 양식에서 추출):
|
||||
- 16:9 화이트 마스터, 별도 헤더바/배경 데코 없음 (텍스트만)
|
||||
- 컨텐츠 슬라이드 좌상단 "Android App 진행 보고" 24pt ExtraBold 러닝헤더
|
||||
- 본문 textbox: L=0.66" T=0.95" W=14.48"
|
||||
· 제목 28pt ExtraBold #222A33
|
||||
· L1 "• " + 두 칸 · 18pt Bold + accent blue #1E88E5
|
||||
· L2 "– " + 두 칸 · 15pt regular #222A33
|
||||
· L3 "· " + 여섯 칸 · 13pt regular #55606C
|
||||
- 스크린샷은 본문 우측 또는 하단에 카드/테두리 없이 배치
|
||||
"""
|
||||
from pathlib import Path
|
||||
from copy import deepcopy
|
||||
from lxml import etree
|
||||
from pptx import Presentation
|
||||
from pptx.util import Inches, Pt, Emu
|
||||
from pptx.dml.color import RGBColor
|
||||
from pptx.enum.text import PP_ALIGN
|
||||
|
||||
PPT_DIR = Path(__file__).parent
|
||||
TEMPLATE = PPT_DIR / "주간보고서_dwjang_20260604.pptx"
|
||||
OUT_PATH = PPT_DIR / "주간보고서_dwjang_20260611.pptx"
|
||||
|
||||
# 팔레트 (정확한 추출)
|
||||
COLOR_TEXT = RGBColor(0x22, 0x2A, 0x33)
|
||||
COLOR_TEXT_SUB = RGBColor(0x55, 0x60, 0x6C)
|
||||
COLOR_ACCENT = RGBColor(0x1E, 0x88, 0xE5)
|
||||
|
||||
FONT_BODY = "나눔고딕"
|
||||
FONT_HEAD = "나눔고딕 ExtraBold"
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Helper: 기존 slide 다 지우기
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
def clear_slides(prs):
|
||||
"""Presentation 의 모든 슬라이드를 제거 + dangling slide part 도 drop."""
|
||||
sld_id_lst = prs.slides._sldIdLst
|
||||
prs_part = prs.part
|
||||
# rId → slide part 매핑 수집
|
||||
to_drop_rids = []
|
||||
for sld_id in list(sld_id_lst):
|
||||
rid = sld_id.get(
|
||||
'{http://schemas.openxmlformats.org/officeDocument/2006/relationships}id'
|
||||
)
|
||||
if rid:
|
||||
to_drop_rids.append(rid)
|
||||
sld_id_lst.remove(sld_id)
|
||||
# 관련 part 와 rel 제거
|
||||
for rid in to_drop_rids:
|
||||
# part_related_by_id → 슬라이드 part 가져오기
|
||||
try:
|
||||
prs_part.drop_rel(rid)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# 텍스트 설정 유틸
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
def set_run(run, text, *, font=FONT_BODY, size=14, bold=False,
|
||||
color=COLOR_TEXT):
|
||||
run.text = text
|
||||
run.font.name = font
|
||||
# ea/cs 폰트도 같이 — 나눔고딕 깨짐 방지
|
||||
rPr = run._r.get_or_add_rPr()
|
||||
# eastAsia
|
||||
ea = rPr.find('{http://schemas.openxmlformats.org/drawingml/2006/main}ea')
|
||||
if ea is None:
|
||||
ea = etree.SubElement(rPr, '{http://schemas.openxmlformats.org/drawingml/2006/main}ea')
|
||||
ea.set('typeface', font)
|
||||
cs = rPr.find('{http://schemas.openxmlformats.org/drawingml/2006/main}cs')
|
||||
if cs is None:
|
||||
cs = etree.SubElement(rPr, '{http://schemas.openxmlformats.org/drawingml/2006/main}cs')
|
||||
cs.set('typeface', font)
|
||||
run.font.size = Pt(size)
|
||||
run.font.bold = bold
|
||||
if color is not None:
|
||||
run.font.color.rgb = color
|
||||
|
||||
|
||||
def add_textbox(slide, left, top, width, height):
|
||||
tb = slide.shapes.add_textbox(left, top, width, height)
|
||||
tf = tb.text_frame
|
||||
tf.word_wrap = True
|
||||
tf.margin_left = Inches(0.05)
|
||||
tf.margin_right = Inches(0.05)
|
||||
tf.margin_top = Inches(0.0)
|
||||
tf.margin_bottom = Inches(0.0)
|
||||
return tb, tf
|
||||
|
||||
|
||||
def add_running_header(slide):
|
||||
"""좌상단 '주간 진행 보고 — Android App' 러닝헤더."""
|
||||
tb, tf = add_textbox(slide, Inches(0.44), Inches(0.19),
|
||||
Inches(8), Inches(0.5))
|
||||
p = tf.paragraphs[0]
|
||||
p.alignment = PP_ALIGN.LEFT
|
||||
run = p.add_run()
|
||||
set_run(run, "Android App 진행 보고",
|
||||
font=FONT_HEAD, size=24, bold=True, color=COLOR_TEXT)
|
||||
|
||||
|
||||
def add_slide_title(tf, title_text):
|
||||
"""본문 textbox 첫 문단으로 슬라이드 타이틀."""
|
||||
p = tf.paragraphs[0]
|
||||
p.alignment = PP_ALIGN.LEFT
|
||||
run = p.add_run()
|
||||
set_run(run, title_text, font=FONT_HEAD, size=28, bold=True,
|
||||
color=COLOR_TEXT)
|
||||
|
||||
|
||||
def add_bullets(tf, lines):
|
||||
"""lines = [(level, text)] 레벨별 prefix/폰트/컬러 자동."""
|
||||
for level, text in lines:
|
||||
p = tf.add_paragraph()
|
||||
p.alignment = PP_ALIGN.LEFT
|
||||
p.level = 0 # 우리는 모든 indent 를 prefix 로 처리 (양식과 동일)
|
||||
run = p.add_run()
|
||||
if level == 0:
|
||||
prefix = "• "
|
||||
size = 18; bold = True; color = COLOR_ACCENT
|
||||
elif level == 1:
|
||||
prefix = "– "
|
||||
size = 15; bold = False; color = COLOR_TEXT
|
||||
else:
|
||||
prefix = "· "
|
||||
size = 13; bold = False; color = COLOR_TEXT_SUB
|
||||
set_run(run, prefix + text, font=FONT_BODY, size=size, bold=bold,
|
||||
color=color)
|
||||
|
||||
|
||||
def add_spacer(tf, count=1, size=18):
|
||||
for _ in range(count):
|
||||
p = tf.add_paragraph()
|
||||
run = p.add_run()
|
||||
set_run(run, "", font=FONT_BODY, size=size)
|
||||
|
||||
|
||||
def add_caption(slide, text, left, top, width):
|
||||
tb, tf = add_textbox(slide, left, top, width, Inches(0.32))
|
||||
p = tf.paragraphs[0]
|
||||
p.alignment = PP_ALIGN.CENTER
|
||||
run = p.add_run()
|
||||
set_run(run, text, font=FONT_BODY, size=11, color=COLOR_TEXT_SUB)
|
||||
|
||||
|
||||
def fit_picture(slide, path, left, top, max_w, max_h, *, phone=True):
|
||||
"""폰(1080:2340) 또는 태블릿(1200:1920) 비율 유지하며 박스 안에 fit."""
|
||||
if not path.exists():
|
||||
return None
|
||||
aspect = (1080 / 2340) if phone else (1200 / 1920)
|
||||
if max_w / max_h > aspect:
|
||||
h = max_h
|
||||
w = int(h * aspect)
|
||||
else:
|
||||
w = max_w
|
||||
h = int(w / aspect)
|
||||
cx = left + (max_w - w) // 2
|
||||
cy = top + (max_h - h) // 2
|
||||
return slide.shapes.add_picture(str(path), cx, cy, w, h)
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# 슬라이드 빌더
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
def build_title_slide(prs):
|
||||
# Layout 0 = "0. 제목 반전 슬라이드"
|
||||
layout = prs.slide_layouts[0]
|
||||
s = prs.slides.add_slide(layout)
|
||||
|
||||
# 제목 plchldr 위치는 기존 양식에 따라 우측 텍스트 블록
|
||||
# 기존: L=7.24" T=2.95" W=8.32" H=2.05"
|
||||
tb, tf = add_textbox(s, Inches(7.24), Inches(2.95),
|
||||
Inches(8.32), Inches(2.05))
|
||||
p = tf.paragraphs[0]
|
||||
p.alignment = PP_ALIGN.LEFT
|
||||
run = p.add_run()
|
||||
set_run(run, "주간 진행 보고", font=FONT_HEAD, size=32, bold=True,
|
||||
color=COLOR_TEXT)
|
||||
|
||||
# 부제 (날짜) L=7.24" T=5.00"
|
||||
tb2, tf2 = add_textbox(s, Inches(7.24), Inches(5.00),
|
||||
Inches(8.32), Inches(0.6))
|
||||
p2 = tf2.paragraphs[0]
|
||||
p2.alignment = PP_ALIGN.LEFT
|
||||
run2 = p2.add_run()
|
||||
set_run(run2, "2026-06-08 (월) ~ 06-12 (금)",
|
||||
font=FONT_BODY, size=18, bold=True, color=COLOR_TEXT_SUB)
|
||||
return s
|
||||
|
||||
|
||||
def build_content_slide(prs, title, bullets, *, body_h=Inches(7.5),
|
||||
pics=None, captions=None):
|
||||
"""
|
||||
title: slide title (28pt)
|
||||
bullets: [(level, text), ...]
|
||||
pics: optional list of (path, left_in, top_in, w_in, h_in, phone_bool)
|
||||
captions: optional list of (text, left_in, top_in, w_in)
|
||||
"""
|
||||
layout = prs.slide_layouts[1] # 1. 빈 화면
|
||||
s = prs.slides.add_slide(layout)
|
||||
add_running_header(s)
|
||||
# 본문 textbox
|
||||
tb, tf = add_textbox(s, Inches(0.66), Inches(0.95),
|
||||
Inches(14.48), body_h)
|
||||
add_slide_title(tf, title)
|
||||
add_spacer(tf, 1)
|
||||
add_bullets(tf, bullets)
|
||||
# 그림
|
||||
if pics:
|
||||
for (path, left, top, w, h, phone) in pics:
|
||||
fit_picture(s, path, Inches(left), Inches(top),
|
||||
Inches(w), Inches(h), phone=phone)
|
||||
if captions:
|
||||
for (text, left, top, w) in captions:
|
||||
add_caption(s, text, Inches(left), Inches(top), Inches(w))
|
||||
return s
|
||||
|
||||
|
||||
def build_closing_slide(prs):
|
||||
layout = prs.slide_layouts[1]
|
||||
s = prs.slides.add_slide(layout)
|
||||
# 정중앙 "감사합니다"
|
||||
tb, tf = add_textbox(s, Inches(6.83), Inches(3.86),
|
||||
Inches(4.5), Inches(1.0))
|
||||
p = tf.paragraphs[0]
|
||||
p.alignment = PP_ALIGN.CENTER
|
||||
run = p.add_run()
|
||||
set_run(run, "감사합니다", font=FONT_HEAD, size=32, bold=True,
|
||||
color=COLOR_TEXT)
|
||||
return s
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# 메인
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
prs = Presentation(str(TEMPLATE))
|
||||
clear_slides(prs)
|
||||
|
||||
# Slide 1 — Title
|
||||
build_title_slide(prs)
|
||||
|
||||
# Slide 2 — 핵심 요약
|
||||
build_content_slide(prs,
|
||||
title="이번 주 핵심 요약 — 탭 navigation · 설정 통합 · BLE 안정성",
|
||||
bullets=[
|
||||
(0, "4탭 셸 Navigation 도입 (Home / 측정 / 이력 / 설정)"),
|
||||
(1, "기존 시퀀셜 화면 흐름 → 탭 기반 재편, sub-tab 으로 세부 화면 통합"),
|
||||
(1, "탭 셸 노출 화면 / 위저드 풀스크린 분기 정책"),
|
||||
(0, "이력 / 설정 탭 통합"),
|
||||
(1, "이력 — 측정 + 배뇨일지 sub-tab"),
|
||||
(1, "설정 — 개인화 + 알림 + 앱 정보 sub-tab"),
|
||||
(1, "PiezoMonitoring overlay 의 user 설정은 모두 설정 탭으로 이동 (중복 제거)"),
|
||||
(0, "BLE 안정성 — 다중 기기 페어링 (Clinical 한정) + 펌웨어 호환 체크"),
|
||||
(1, "KnownDeviceStore — Clinical 흐름에서만 저장, 일반 사용자는 매 세션 fresh scan"),
|
||||
(1, "Disconnect / Delete Pairing 분리 (회의 피드백 반영)"),
|
||||
(1, "펌웨어 < VBTFW0118 / mid? 미응답 시 경고 배너 · mfv? fallback"),
|
||||
(0, "Polish · Bug fix"),
|
||||
(1, "첫 설치 시 Consent 화면 노출 fix · Dev Tools 영역 dev 모드 전용"),
|
||||
(1, "설정 탭 개인화 카드 컴팩트 모드 (한 화면에 3카드 fit)"),
|
||||
],
|
||||
)
|
||||
|
||||
# Slide 3 — 4탭 셸
|
||||
build_content_slide(prs,
|
||||
title="4탭 셸 Navigation 도입 — MainShell + 자동 라우팅",
|
||||
bullets=[
|
||||
(0, "탭 셸 노출 화면 (showsTabShell)"),
|
||||
(1, "HOME, PIEZO_MONITORING, MEASUREMENT_HISTORY, VOIDING_DIARY, SETTINGS"),
|
||||
(1, "선택 탭은 현재 AppScreen 으로부터 자동 도출 — 별도 state 없음"),
|
||||
(0, "탭 셸 숨김 (풀스크린 가이드형)"),
|
||||
(1, "측정 위저드 — DeviceScan / Personalization / PlacementGuide / URINE_CAMERA"),
|
||||
(1, "사전 화면 — Onboarding / Consent / Registration / PIN / Calibration"),
|
||||
(1, "Clinical R&D 흐름 — ClinicalHome / ClinicalLive (별도 컨텍스트 보존)"),
|
||||
(0, "탭별 진입 동작"),
|
||||
(1, "Home → goHome() · NirsManager stop + demo state cleanup 포함"),
|
||||
(1, "측정 → startFromHome() · 연결되어 있으면 PIEZO_MONITORING, 아니면 DEVICE_SCAN"),
|
||||
(1, "이력 → HistoryTabView · 측정 sub-tab 진입"),
|
||||
(1, "설정 → SettingsTabView · 개인화 sub-tab 진입"),
|
||||
(0, "BackHandler 정정 — 셸 화면 Back 시 PIEZO_MONITORING → HOME 자연 복귀"),
|
||||
],
|
||||
body_h=Inches(7.5),
|
||||
pics=[
|
||||
(PPT_DIR / "Screenshot_20260611_165624_VesiScan Demo.jpg",
|
||||
11.0, 1.1, 4.4, 7.5, True),
|
||||
],
|
||||
captions=[
|
||||
("Home 탭 · 4탭 셸 적용 화면", 11.0, 8.6, 4.4),
|
||||
],
|
||||
)
|
||||
|
||||
# Slide 4 — 이력 탭 통합
|
||||
build_content_slide(prs,
|
||||
title="이력 탭 통합 — MeasurementHistory + VoidingDiary",
|
||||
bullets=[
|
||||
(0, "신규 HistoryTabView · SingleChoiceSegmentedButtonRow 로 sub-tab 전환"),
|
||||
(1, "측정 — piezo 센서 측정 기록 (기존 History / Trends 내부 탭 유지)"),
|
||||
(1, "배뇨일지 — 수동 입력 기록 (24h 의료지표 카드 포함)"),
|
||||
(0, "기존 화면 정리"),
|
||||
(1, "MeasurementHistoryView — 상단 바 (Back + 타이틀) 제거"),
|
||||
(1, "VoidingDiaryView — Scaffold / TopAppBar / onBack 제거"),
|
||||
(1, "탭 셸이 헤더 제공 → 화면 내 중복 헤더 모두 정리"),
|
||||
(0, "라우팅 단순화"),
|
||||
(1, "AppScreen.MEASUREMENT_HISTORY → 측정 sub-tab"),
|
||||
(1, "AppScreen.VOIDING_DIARY → 배뇨일지 sub-tab"),
|
||||
(1, "둘 다 HistoryTabView 진입점, initial sub-tab 만 다름"),
|
||||
],
|
||||
body_h=Inches(7.0),
|
||||
pics=[
|
||||
(PPT_DIR / "Screenshot_20260611_165644_VesiScan Demo.jpg",
|
||||
8.7, 1.1, 3.3, 7.5, True),
|
||||
(PPT_DIR / "Screenshot_20260611_165648_VesiScan Demo.jpg",
|
||||
12.1, 1.1, 3.3, 7.5, True),
|
||||
],
|
||||
captions=[
|
||||
("측정 sub-tab", 8.7, 8.6, 3.3),
|
||||
("배뇨일지 sub-tab", 12.1, 8.6, 3.3),
|
||||
],
|
||||
)
|
||||
|
||||
# Slide 5 — 설정 탭 통합
|
||||
build_content_slide(prs,
|
||||
title="설정 탭 통합 — 개인화 + 알림 + 앱 정보",
|
||||
bullets=[
|
||||
(0, "신규 SettingsTabView · 3 sub-tab"),
|
||||
(1, "개인화 — Max Volume / Catheter Threshold / Auto Scan Interval (+dev: Ant Offset)"),
|
||||
(1, "알림 — ON/OFF · 간격 · 시간대 · 사운드/진동/팝업 (Reminder)"),
|
||||
(1, "앱 정보 — 앱 버전 · 기기 연결 · 펌웨어 · (dev) Serial · Unpair"),
|
||||
(0, "embedded 플래그로 위저드 / 설정 모드 분기"),
|
||||
(1, "위저드 (embedded=false): 헤더 + Bladdy + Continue 버튼"),
|
||||
(1, "설정 탭 (embedded=true): 카드만 노출, 컴팩트 사이즈, LaunchedEffect 로 자동 저장"),
|
||||
(0, "Disconnect / Delete Pairing 분리"),
|
||||
(1, "Disconnect (회색) — bond 유지, 다음 측정 시 PIN 없이 빠른 재연결"),
|
||||
(1, "Delete Pairing (빨강) — 확인 다이얼로그 후 unbond + known list 제거 (destructive)"),
|
||||
],
|
||||
body_h=Inches(7.0),
|
||||
pics=[
|
||||
(PPT_DIR / "Screenshot_20260611_165653_VesiScan Demo.jpg",
|
||||
8.0, 1.1, 2.4, 7.5, True),
|
||||
(PPT_DIR / "Screenshot_20260611_165657_VesiScan Demo.jpg",
|
||||
10.5, 1.1, 2.4, 7.5, True),
|
||||
(PPT_DIR / "Screenshot_20260611_165701_VesiScan Demo.jpg",
|
||||
13.0, 1.1, 2.4, 7.5, True),
|
||||
],
|
||||
captions=[
|
||||
("개인화", 8.0, 8.6, 2.4),
|
||||
("알림", 10.5, 8.6, 2.4),
|
||||
("앱 정보", 13.0, 8.6, 2.4),
|
||||
],
|
||||
)
|
||||
|
||||
# Slide 6 — BLE 안정성
|
||||
build_content_slide(prs,
|
||||
title="BLE 안정성 — Clinical 다중 기기 + 펌웨어 호환 체크",
|
||||
bullets=[
|
||||
(0, "KnownDeviceStore — JSON 리스트로 다중 기기 영속화"),
|
||||
(1, "getAll / add / remove / mostRecent · 구 단일 키 자동 마이그레이션"),
|
||||
(1, "Clinical 흐름 (ClinicalSessionStore.inClinicalFlow) 에서만 저장"),
|
||||
(1, "일반 사용자: 매 세션 fresh scan + pair · 저장 0개"),
|
||||
(0, "DeviceScanView 2섹션 (Clinical 전용)"),
|
||||
(1, "Saved Devices — 카드 탭 = PIN 없이 즉시 재연결 · 휴지통 = Delete Pairing"),
|
||||
(1, "New Devices — 스캔된 기기 중 known 에 없는 것만"),
|
||||
(0, "펌웨어 호환 체크"),
|
||||
(1, "BleManager.MIN_FIRMWARE_BUILD = 118 · parseFirmwareBuild() 끝자리 숫자 비교"),
|
||||
(1, "FirmwareWarningBanner — 구버전 (주황) / 응답 없음 (빨강) / 정상 (숨김)"),
|
||||
(1, "rid: 파서 fixed-width 12B 슬라이스 보정 + mfv? 4초 후 fallback"),
|
||||
],
|
||||
body_h=Inches(6.5),
|
||||
pics=[
|
||||
# 펌웨어 경고 배너 실제 작동 (가로 태블릿)
|
||||
(PPT_DIR / "Screenshot_20260611-154306.png",
|
||||
9.5, 1.1, 6.0, 5.5, False),
|
||||
],
|
||||
captions=[
|
||||
("펌웨어 경고 배너 작동 — VBTFW0116 → VBTFW0118 권장 안내", 9.5, 6.75, 6.0),
|
||||
],
|
||||
)
|
||||
|
||||
# Slide 7 — Bug fix / Polish
|
||||
build_content_slide(prs,
|
||||
title="Bug fix · Polish — Consent 화면 / Dev Tools / 컴팩트",
|
||||
bullets=[
|
||||
(0, "Consent 화면 — 첫 설치 시 정상 노출 fix"),
|
||||
(1, "기존 버그: completeOnboarding() 가 hasConsented=true 자동 마킹 → CONSENT 스킵"),
|
||||
(1, "수정: hasConsented 자동 마킹 제거 · loadState 분기에 !hasConsented 추가"),
|
||||
(1, "정상 흐름: ONBOARDING → CONSENT → REGISTRATION → PIN_SETUP → HOME"),
|
||||
(0, "Dev Tools 영역 gating (PiezoMonitoring)"),
|
||||
(1, "Logs & Charts 토글 + ChannelPanel / BleDebugPanel / Scan Log → isDevMode 한정"),
|
||||
(1, "일반 사용자: Spot / Catheterize 액션 영역까지만 노출 (간결)"),
|
||||
(0, "설정 탭 개인화 카드 — 컴팩트 모드"),
|
||||
(1, "embedded=true 시 카드 padding / 폰트 / Stepper 크기 절반 수준"),
|
||||
(1, "3카드 (dev 면 4카드) 한 화면 내 fit"),
|
||||
],
|
||||
body_h=Inches(6.5),
|
||||
pics=[
|
||||
(PPT_DIR / "Screenshot_20260611_165608_VesiScan Demo.jpg",
|
||||
9.5, 1.1, 3.0, 7.5, True),
|
||||
(PPT_DIR / "Screenshot_20260611_165613_VesiScan Demo.jpg",
|
||||
12.7, 1.1, 3.0, 7.5, True),
|
||||
],
|
||||
captions=[
|
||||
("Consent 상단", 9.5, 8.6, 3.0),
|
||||
("Consent — 의료정보 동의", 12.7, 8.6, 3.0),
|
||||
],
|
||||
)
|
||||
|
||||
# Slide 8 — 결과물 / 다음 주
|
||||
build_content_slide(prs,
|
||||
title="결과물 정리 · 다음 주 계획",
|
||||
bullets=[
|
||||
(0, "feature/tab-navigation · 14 커밋 (master 5100616 → b427fab+)"),
|
||||
(1, "Stage 1 — 4탭 셸 + 라우팅 (MainShell + AppScreen.SETTINGS)"),
|
||||
(1, "Stage 2 — 이력 탭 sub-tab 통합 (HistoryTabView)"),
|
||||
(1, "Stage 3 — 설정 탭 sub-tab 통합 (SettingsTabView + embedded mode)"),
|
||||
(1, "Stage 4 — PiezoMonitoring 상단 바 · overlay 정리"),
|
||||
(1, "BLE — 다중 기기 (Clinical) · Disconnect/Delete 분리 · 펌웨어 호환 체크"),
|
||||
(0, "demo-final cherry-pick (1.1.0-design → 1.1.1-design)"),
|
||||
(1, "BLE 안정성 패치만 backport — 다중 기기 + 펌웨어 호환 + rid 파서 fix"),
|
||||
(0, "신규 문서 — docs/APP_STRUCTURE.md"),
|
||||
(1, "탭 다이어그램 · AppScreen 카탈로그 · 핵심 파일 위치 · Back 분기표"),
|
||||
(0, "다음 주 계획"),
|
||||
(1, "디바이스 검증 — 일반/dev 모드 전체 흐름 풀 테스트 · Clinical 다중 기기 스위치"),
|
||||
(1, "머지 정책 — feature/tab-navigation → master 머지 시점 결정"),
|
||||
(1, "UX 폴리시 — Registration 필드 점검 · 빈 상태 onboarding 안내"),
|
||||
],
|
||||
)
|
||||
|
||||
# Slide 9 — 감사합니다
|
||||
build_closing_slide(prs)
|
||||
|
||||
prs.save(str(OUT_PATH))
|
||||
print(f"Saved: {OUT_PATH}")
|
||||
print(f"Slides: {len(prs.slides)}")
|
||||
Reference in New Issue
Block a user