devorah-ai-2016 commited on
Commit
b2e4919
ยท
verified ยท
1 Parent(s): fca8aa3

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +1211 -0
app.py ADDED
@@ -0,0 +1,1211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import openpyxl
3
+ from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
4
+ from openpyxl.utils import get_column_letter
5
+ from datetime import datetime, date
6
+ import io
7
+
8
+ # ---------------------------------------------------------
9
+ # Page Configurations and Premium Styling (CSS)
10
+ # ---------------------------------------------------------
11
+ st.set_page_config(
12
+ page_title="์žฌ๋‚œยท์†Œ๋ฐฉยท์•ˆ์ „ ๊ต์œก ๋ฌธ์„œ ์ž๋™์ƒ์„ฑ๊ธฐ",
13
+ page_icon="๐Ÿš’",
14
+ layout="wide",
15
+ initial_sidebar_state="expanded"
16
+ )
17
+
18
+ # Custom Glassmorphism & Modern Soft Palettes UI styling
19
+ st.markdown("""
20
+ <style>
21
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+KR:wght@300;400;500;700;900&display=swap');
22
+
23
+ html, body, [class*="css"] {
24
+ font-family: 'Noto Sans KR', 'Inter', sans-serif;
25
+ }
26
+
27
+ /* Premium Title Card styling */
28
+ .title-card {
29
+ background: linear-gradient(135deg, #1A365D 0%, #2A4365 100%);
30
+ padding: 2.5rem;
31
+ border-radius: 16px;
32
+ color: white;
33
+ margin-bottom: 2rem;
34
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
35
+ position: relative;
36
+ overflow: hidden;
37
+ }
38
+ .title-card::after {
39
+ content: "";
40
+ position: absolute;
41
+ top: -50%;
42
+ right: -30%;
43
+ width: 300px;
44
+ height: 300px;
45
+ background: rgba(255, 255, 255, 0.05);
46
+ border-radius: 50%;
47
+ }
48
+ .title-card h1 {
49
+ font-size: 2.2rem;
50
+ font-weight: 900;
51
+ margin: 0 0 0.5rem 0;
52
+ color: #FFFFFF !important;
53
+ letter-spacing: -0.025em;
54
+ }
55
+ .title-card p {
56
+ font-size: 1.1rem;
57
+ margin: 0;
58
+ opacity: 0.9;
59
+ font-weight: 300;
60
+ }
61
+
62
+ /* Section Headers */
63
+ .section-header {
64
+ font-size: 1.3rem;
65
+ font-weight: 700;
66
+ color: #1E3A8A;
67
+ border-left: 5px solid #3B82F6;
68
+ padding-left: 10px;
69
+ margin-top: 1.5rem;
70
+ margin-bottom: 1rem;
71
+ }
72
+
73
+ /* Custom button styling */
74
+ div.stButton > button {
75
+ background: linear-gradient(90deg, #2563EB 0%, #1D4ED8 100%) !important;
76
+ color: white !important;
77
+ font-weight: 600 !important;
78
+ padding: 0.75rem 2rem !important;
79
+ border-radius: 10px !important;
80
+ border: none !important;
81
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2) !important;
82
+ transition: all 0.2s ease-in-out !important;
83
+ width: 100% !important;
84
+ font-size: 1.1rem !important;
85
+ }
86
+ div.stButton > button:hover {
87
+ transform: translateY(-2px) !important;
88
+ box-shadow: 0 6px 20px rgba(37, 99, 235, 0.35) !important;
89
+ }
90
+ </style>
91
+ """, unsafe_allow_html=True)
92
+
93
+ # ---------------------------------------------------------
94
+ # Dynamic Narrative Sentence Generation Engine
95
+ # ---------------------------------------------------------
96
+ def generate_narrative_text(info, section, training_type):
97
+ facility_name = info.get('facility_name', 'ํ–‰๋ณต์š”์–‘์›')
98
+ total_participants = info.get('total_participants', 18)
99
+ staff_count = info.get('staff_participants', 8)
100
+ recipient_count = info.get('recipient_participants', 12)
101
+ evac_time = info.get('evac_time', '4๋ถ„ 30์ดˆ')
102
+ vulnerable_count = info.get('vulnerable_count', 5)
103
+ wheelchair_count = info.get('wheelchair_count', 3)
104
+ walk_aid_count = info.get('walk_aid_count', 4)
105
+
106
+ emergency_mock = info.get('emergency_mock', '์‹ค์‹œ ๋ฐ ์–‘ํ˜ธ')
107
+ fire_ext_demo = info.get('fire_ext_demo', '์‹ค์‹œ ๋ฐ ์–‘ํ˜ธ')
108
+ route_checked = info.get('route_checked', 'ํ™•์ธ์™„๋ฃŒ')
109
+ contact_checked = info.get('contact_checked', '์ž‘๋™ํ™•์ธ')
110
+ guardian_call_date = info.get('guardian_call_date', str(datetime.today().strftime('%Y-%m-%d')))
111
+ guardian_reflected = info.get('guardian_reflected', '๋ฐ˜์˜์™„๋ฃŒ')
112
+
113
+ if training_type == "์†Œ๋ฐฉํ›ˆ๋ จ":
114
+ # Multi-occupational Opinions
115
+ if section == "opinion_์‹œ์„ค์žฅ_1":
116
+ return "์†Œ๋ฐฉ ํ›ˆ๋ จ ์‹œ ์ „ ์ธต์˜ ์†Œํ™” ๋ฐ ๊ฒฝ๋ณด์„ค๋น„ ๊ฐ€๋™์„ ์ผ์ผ ์ ๊ฒ€ํ•˜๊ณ , ์ธ๋ ฅ ๊ต๋Œ€ ๊ทผ๋ฌด ์‹œ ์ธ์ˆ˜์ธ๊ณ„์„œ์— '์˜ค๋Š˜์˜ ๋น„์ƒ ๋Œ€์ฑ… ์—ญํ• ' ํ‘œ๊ธฐ๋ฅผ ์˜๋ฌดํ™”ํ•˜๋Š” ํ–‰์ • ์ง€์นจ์„ ์‹œ๋‹ฌํ•จ."
117
+ elif section == "opinion_์‹œ์„ค์žฅ_2":
118
+ return "์›ํ™œํ•œ ํ”ผ๋‚œ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋…ธํ›„ ํœ ์ฒด์–ด ์ •๋น„ ์˜ˆ์‚ฐ์„ ํŽธ์„ฑํ•˜๊ณ , ์‹œ๋„๋Ÿฌ์šด ๊ฒฝ๋ณด ์† ํ†ต์ œ๋ฅผ ์œ„ํ•œ ํœด๋Œ€์‹ ๋ฉ”๊ฐ€ํฐ 2๋Œ€ ๋ฐ ๋ฐ˜์‚ฌ ์œ ๋„์กฐ๋ผ ์ถ”๊ฐ€ ๊ณต๊ธ‰์„ ์ง€์›ํ•จ."
119
+ elif section == "opinion_์‹œ์„ค์žฅ_role":
120
+ return "ํ›ˆ๋ จ ์ด๊ด„ ์ง€ํœ˜, ์†Œ๋ฐฉ ์•ˆ์ „ ๋Œ€์ฑ… ์œ„์›ํšŒ ์ฃผ๊ด€ ๋ฐ ์˜ˆ์‚ฐ ๊ฒฐ์žฌ"
121
+
122
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_1":
123
+ return f"์ˆ˜๊ธ‰์ž {recipient_count}๋ช… ์ค‘ {vulnerable_count}๋ช…์˜ ๋Œ€ํ”ผ์ทจ์•ฝ์ž์— ๋Œ€ํ•˜์—ฌ ์š”์–‘๋ณดํ˜ธ์‚ฌ ๋ฐ ๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ์™€ 1:1 ๋งค์นญ ์กฐ๋ฅผ ํŽธ์„ฑํ•˜๊ณ , ๋Œ€ํ”ผ ๊ฒฝ๋กœ ๋™์„ ์—์„œ ์žฅ์•  ์š”์†Œ๏ฟฝ๏ฟฝ ์‚ฌ์ „์— ์Šคํฌ๋ฆฌ๋‹ํ•จ."
124
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_2":
125
+ return "๋ณดํ˜ธ์ž ๋น„์ƒ์—ฐ๋ฝ๋ง ์ตœ์‹ ํ™” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์•ˆ์ „ ๊ณ„ํš์„ ๊ฐฑ์‹ ํ•˜์˜€์œผ๋ฉฐ, ์ˆ˜๊ธ‰์ž๋ณ„ ์š•๊ตฌ์‚ฌ์ • ๊ธฐ๋ก์ง€์— ๊ฐœ์ธ๋ณ„ ๋Œ€ํ”ผ ์‹œ ํŠน์ด์‚ฌํ•ญ์„ ๋ช…์‹œํ•˜์—ฌ ๋ฐ˜์˜ํ•จ."
126
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_role":
127
+ return "๋Œ€ํ”ผ์ทจ์•ฝ์ž ๋ถ„๋ฅ˜, ๋น„์ƒ์—ฐ๋ฝ ๋™์„  ์ ๊ฒ€, ํ›ˆ๋ จ์ผ์ง€ ๊ธฐ๋ก ๋ฐ ๋Œ€์™ธ ๋ณดํ˜ธ์ž ์•ˆ๋‚ด"
128
+
129
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_1":
130
+ return f"ํœ ์ฒด์–ด ๋Œ€์ƒ์ž {wheelchair_count}๋ช…๊ณผ ๋ณดํ–‰๋ณด์กฐ ํ•„์š”์ž {walk_aid_count}๋ช…์€ ์Šค์Šค๋กœ ๊ฒฝ๋ณด์Œ์„ ์ธ์ง€ํ•˜๋”๋ผ๋„ ๊ด€์ ˆ ๊ฒฝ์ง ๋ฐ ์ธ์ง€ ์ €ํ•˜๋กœ ์ž๋ ฅ ๋Œ€ํ”ผ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜์—ฌ ๋Œ€ํ”ผ ์‹œ ๋‚™์ƒ ์œ„ํ—˜์ด ๋งค์šฐ ๋†’์€ ์ƒํƒœ๋กœ ๊ด€์ฐฐ๋จ."
131
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_2":
132
+ return "ํ™”์žฌ ์‹œ ์—ฐ๊ธฐ ํก์ž…์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์ –์€ ์ˆ˜๊ฑด์œผ๋กœ ์ฝ”์™€ ์ž…์„ ๋ณดํ˜ธํ•˜๋ฉฐ, ํœ ์ฒด์–ด ์ด๋™ ์‹œ์—๋Š” ๊ฒฝ์‚ฌ๋กœ ๋ธŒ๋ ˆ์ดํฌ๊ฐ€ ๋ฐ€๋ฆฌ์ง€ ์•Š๋„๋ก ๊ณ ์ •ํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ์ถœ๋ฐœ ์ „ ํ•„ํžˆ ์ˆ™์ง€ํ•˜๊ณ  ์ดํ–‰ํ•ด์•ผ ํ•จ."
133
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_role":
134
+ return "์ˆ˜๊ธ‰์ž 1:1 ๋Œ€ํ”ผ ๋™๋ฐ˜ ์ด๋™, ๋Œ€ํ”ผ ์ค‘ ๋‚™์ƒ ์œ„ํ—˜ ํ†ต์ œ, ํ”ผ๋‚œ ๋ฌผํ’ˆ ์ ์‹œ ๋ฐฐ๋ถ€"
135
+
136
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_1":
137
+ return f"๋Œ€ํ”ผ ์™„๋ฃŒ ํ›„ ์‹ ์†ํ•˜๊ฒŒ ์ž„์‹œ ์ง‘๊ฒฐ์ง€์—์„œ ์ˆ˜๊ธ‰์ž {recipient_count}๋ช…์˜ ํ˜ˆ์••, ๋งฅ๋ฐ• ๋“ฑ ํ™œ๋ ฅ์ง•ํ›„๋ฅผ ๊ธฐ๋กํ•˜์—ฌ ๋น„์ƒ ์ง„๋ฃŒ ์นด๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‡ผํฌ ์ฆ์ƒ ๋ฐ ํ˜ธํก๊ธฐ ์งˆํ™˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜์˜€์Œ."
138
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_2":
139
+ return "ํœด๋Œ€์šฉ ๊ตฌ๊ธ‰ ์•ฝํ’ˆ ๊ฐ€๋ฐฉ ๋ฐ ์‚ฐ์†Œ์บ” ์ค€๋น„ ์ƒํƒœ๋ฅผ ์‚ฌ์ „์— ํ™•์ธํ•˜์˜€๊ณ , ๋Œ€ํ”ผ ๊ณผ์ •์—์„œ ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•œ ์ˆ˜๊ธ‰์ž์˜ ๊ฐ€๋ฒผ์šด ์ฐฐ๊ณผ์ƒ์— ๋Œ€ํ•œ ์†Œ๋… ๋ฐ ์‘๊ธ‰ ์ฒ˜์น˜ ์š”๋ น์„ ํ›ˆ๋ จํ•˜์˜€์Œ."
140
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_role":
141
+ return "๋น„์ƒ ์•ฝํ’ˆ ํœด๋Œ€, ํ™œ๋ ฅ์ง•ํ›„ ์ธก์ • ๋ฐ ์‘๊ธ‰๊ตฌํ˜ธ ์กฐ์น˜ ๊ฐ€๋™"
142
+
143
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_1":
144
+ return "๋ณดํ–‰์ด ๋ถˆ์•ˆ์ •ํ•œ ์ˆ˜๊ธ‰์ž๋“ค์€ ๋น„์ƒ์ƒํ™ฉ ์‹œ ํ‰์†Œ๋ณด๋‹ค ๋ณดํ–‰ ๋ณด์กฐ๊ธฐ ์กฐ์ž‘ ์„œ๋‘๋ฆ„์œผ๋กœ ์ธํ•ด ๋ฌด๊ฒŒ์ค‘์‹ฌ์ด ๋ฌด๋„ˆ์ ธ ๋„˜์–ด์ง€๊ธฐ ์‰ฌ์šด ์‹ ์ฒด ํŠน์„ฑ์„ ์ง€๋‹˜."
145
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_2":
146
+ return "๋Œ€ํ”ผ ์‹œ ๊ฒฝ์‚ฌ๋กœ ๋ถ€๊ทผ์—์„œ ๋‚™์ƒ ๋ฐฉ์ง€ ํŒŒ์ง€๋ฒ•์„ ์‹ค์‹œํ•˜๊ณ , ํœ ์ฒด์–ด ์Šน๊ฐ•๊ธฐ ์ง„์ž… ์‹œ ๋ฐฉํ–ฅ ์ „ํ™˜์— ๋”ฐ๋ฅธ ์ถฉ๋Œ ๋ฐฉ์ง€ ์š”๋ น์„ ๋ฌผ๋ฆฌ์น˜๋ฃŒ ๊ด€์  ๋ฐ ์žฌํ™œ ๋ณด์กฐ ๊ธฐ๊ตฌ๋ฅผ ์ ์šฉํ•ด ์ง‘์ค‘ ์ง€์›ํ•จ."
147
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_role":
148
+ return "๋ณดํ–‰ ๋ฐ ํœ ์ฒด์–ด ์•ˆ์ „ ์ด๋™ ๊ธฐ๋ฒ• ๊ต์œก, ๋ฏธ๋„๋Ÿผ ๋ฐฉ์ง€ ์ œ๋™ ๋ณด์กฐ"
149
+
150
+ # 2์ฐจ ๊ฒฐ๊ณผ ๋ฐ˜์˜
151
+ elif section == "result_problem":
152
+ return f"์ž๋ ฅ ๋Œ€ํ”ผ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋Œ€ํ”ผ์ทจ์•ฝ์ž {vulnerable_count}๋ช…์˜ ์ธ์†” ์ธ๋ ฅ ๋ถ„๋‹ด์ด ๋ถˆ๋ช…ํ™•ํ•˜์˜€๊ณ , ์ผ๋ถ€ ํœ ์ฒด์–ด({wheelchair_count}๋Œ€)์˜ ๋ธŒ๋ ˆ์ดํฌ ์ž‘๋™ ๊ฒฐํ•จ ๋ฐ ๊ฒฝ๋ณด ์ž‘๋™ ์‹œ ์†Œ์Œ์œผ๋กœ ์ธํ•œ ๋ฌด์„  ์ง€์‹œ ์ „๋‹ฌ ๋ถˆ๋Ÿ‰ ํ˜„์ƒ์ด ์กด์žฌํ–ˆ์Œ."
153
+ elif section == "result_action":
154
+ return f"ํ™”์žฌ ๋น„์ƒ๊ฒฝ๋ณด ์ „ํŒŒ ํ›„ 119 ์‹ ๊ณ ๋ฅผ ์ง„ํ–‰ํ•˜๊ณ  ์ง€์ • ๋Œ€ํ”ผ๊ฒฝ๋กœ({route_checked})์— ๋”ฐ๋ผ ์ „์› ๋Œ€ํ”ผ๋ฅผ ๋งˆ์ณค์œผ๋ฉฐ, ๋‹ค์ง์ข…์ด ๋ฐ€์ฐฉ ํ˜‘์—…ํ•˜์—ฌ 1:1 ๋Œ€ํ”ผ ๋ฐ ์†Œํ™”๊ธฐ ์ž‘๋™ ์‹ค๋ฌด ์‹œ์—ฐ({fire_ext_demo})์„ ์™„์ˆ˜ํ•จ."
155
+ elif section == "result_role_actions":
156
+ return "์‹œ์„ค์žฅ์€ ์ „์ฒด ํ›ˆ๋ จ ์ง€ํœ˜ ๋ฐ ์—ฐ๋ฝ๋ง ์ž‘๋™์„ ์ ๊ฒ€ํ–ˆ๊ณ , ๋ณต์ง€์‚ฌ๋Š” ์ทจ์•ฝ์ž ์กฐ ๋ถ„๋‹ด๊ณผ ๊ธฐ๋ก์„, ์š”์–‘๋ณดํ˜ธ์‚ฌ๋Š” ์ –์€ ์ˆ˜๊ฑด์„ ํ™œ์šฉํ•ด 1:1 ๋Œ€ํ”ผ๋ฅผ, ๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ๋Š” ํ™œ๋ ฅ์ง•ํ›„ ์ ๊ฒ€์„, ๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ๋Š” ์ด๋™ ์ž์„ธ ๋ณด์กฐ๋ฅผ ์ „๋‹ดํ•จ."
157
+ elif section == "result_outcome":
158
+ return f"์ „ ์ง์›์ด ๋น„์ƒ ์‹œ ํ–‰๋™ ์ง€์นจ์„ ์ˆ™์ง€ํ•˜์˜€๊ณ , ์š”์–‘๋ณดํ˜ธ์‚ฌ์˜ 1:1 ๋งค์นญ ์ง€์›์„ ํ†ตํ•ด ์ตœ์ข… ๋Œ€ํ”ผ์™„๋ฃŒ ์‹œ๊ฐ„์ด {evac_time}๋กœ ํฌ๊ฒŒ ๋‹จ์ถ•๋˜์–ด ์‹ค์ „ ๋Œ€์‘ ๋Šฅ๋ ฅ์ด ์ž…์ฆ๋จ."
159
+ elif section == "result_data":
160
+ return f"์ด ์ฐธ์—ฌ์ž {total_participants}๋ช… (์ข…์‚ฌ์ž {staff_count}๋ช…, ์ˆ˜๊ธ‰์ž {recipient_count}๋ช…), ๋Œ€ํ”ผ์ทจ์•ฝ์ž {vulnerable_count}๋ช…, ํœ ์ฒด์–ด {wheelchair_count}๋Œ€, ๋ณดํ–‰๋ณด์กฐ {walk_aid_count}๋ช…, ๋Œ€ํ”ผ์™„๋ฃŒ {evac_time}, ์†Œํ™”๊ธฐ ์‹ค์Šต {fire_ext_demo}, ์‘๊ธ‰๋Œ€์‘ {emergency_mock}."
161
+ elif section == "result_risks":
162
+ return f"์ผ๋ถ€ ๋ณต๋„ ๊ฒฝ์‚ฌ๋กœ ๊ตฌ๊ฐ„์—์„œ ํœ ์ฒด์–ด {wheelchair_count}๋Œ€๊ฐ€ ๊ตํ–‰ํ•  ๋•Œ ๋ฌธํ„ฑ ์žฅ์• ๋ฌผ๋กœ ์ธํ•ด ์†๋„๊ฐ€ ์ง€์ฒด๋˜๋Š” ๋ณ‘๋ชฉ ํ˜„์ƒ์ด ๋‚จ์•„์žˆ๊ณ , ์‹œ๋„๋Ÿฌ์šด ์‚ฌ์ด๋ Œ ์ƒํ™ฉ์—์„œ ์œ ๋„์ž์˜ ์Œ์„ฑ ์ „๋‹ฌ์ด ๋ถ€๋ถ„์ ์œผ๋กœ ๋ฐฉํ•ด๋ฐ›๋Š” ๋ฌด์„  ์ˆ˜์‹  ์Œ์˜์ด ๊ด€์ฐฐ๋จ."
163
+ elif section == "result_next":
164
+ return "๊ฒฝ์‚ฌ๋กœ ์ฃผ๋ณ€ ๋ฏธ๋„๋Ÿผ ๋ฐฉ์ง€ ๋งคํŠธ๋ฅผ ์‹œ๊ณตํ•˜๊ณ  ๋ฌธํ„ฑ์„ ์™„๋งŒํ•˜๊ฒŒ ๊ฐœ์กฐํ•  ๊ฒƒ์ด๋ฉฐ, ๋น„์ƒ ๋Œ€ํ”ผ์šฉ ํœด๋Œ€์‹ ๋ฉ”๊ฐ€ํฐ์„ ์ถ”๊ฐ€ ๋ฐฐ์น˜ํ•  ์˜ˆ์ •์ž„. ๋‹ค๏ฟฝ๏ฟฝ ํ›ˆ๋ จ ์‹œ์—๋Š” ์•ผ๊ฐ„ ํ™”์žฌ ๋Œ€๋น„ ์ตœ์†Œ ๊ทผ๋ฌด์ž ์ค‘์‹ฌ ๋Œ€ํ”ผ ํ›ˆ๋ จ์„ ์ถ”์ง„ํ•˜๊ฒ ์Œ."
165
+ elif section == "result_guardian":
166
+ return f"๋ณดํ˜ธ์ž ์œ ์„  ์ƒ๋‹ด({guardian_call_date}) ๊ฒฐ๊ณผ ๊ฑฐ๋™๋ถˆํŽธ ์ˆ˜๊ธ‰์ž์˜ ๋Œ€ํ”ผ ์•ˆ์ „ ์šฐ๋ ค๊ฐ€ ์žˆ์–ด 1:1 ์ „๋‹ด ์ธ๋ ฅ ๋งค์นญ ๊ณ„ํš์„ ์„ค๋ช…ํ•˜์˜€์œผ๋ฉฐ, ๋ณดํ˜ธ์ž ๋น„์ƒ ์—ฐ๋ฝ์ฒ˜ ์ตœ์‹ ํ™”๋ฅผ ํ†ตํ•ด {guardian_reflected} ์ƒํƒœ๋ฅผ ์™„๋ฃŒํ•จ."
167
+
168
+ elif training_type == "์žฌ๋‚œํ›ˆ๋ จ":
169
+ # Multi-occupational Opinions
170
+ if section == "opinion_์‹œ์„ค์žฅ_1":
171
+ return "์ง€์ง„ ์ƒํ™ฉ ๋ฐœ์ƒ ์‹œ ๊ฑด๋ฌผ ๋ถ•๊ดด ์œ„ํ—˜์— ๋Œ€๋น„ํ•œ ์‹ค๋‚ด ๊ธด๊ธ‰ ๋Œ€ํ”ผ์ฒ˜์™€ ์‹ค์™ธ ์ง‘๊ฒฐ์ง€์˜ ์•ˆ์ „ ์ƒํƒœ๋ฅผ ์žฌ์ •๋น„ํ•˜๊ณ , ์žฌ๋‚œ ํ†ต์ œ ๋งค๋‰ด์–ผ์„ ์ „ ์ง์›์—๊ฒŒ ์ƒ์‹œ ๊ณต๋žŒ ์ง€์‹œํ•จ."
172
+ elif section == "opinion_์‹œ์„ค์žฅ_2":
173
+ return "์ •์ „์— ๋Œ€๋น„ํ•ด ๋น„์ƒ ๋ฐœ์ „๊ธฐ ๊ฐ€๋™ ์ƒํƒœ๋ฅผ ์ด๊ด„ ํ™•์ธํ•˜๊ณ  ๋น„์ƒ์šฉ ์†์ „๋“ฑ, ์žฌ๋‚œ ์•ˆ์ „๋ชจ ๋“ฑ ๊ตฌํ˜ธ ๋ฌผํ’ˆ์˜ ์˜ˆ์‚ฐ ๋ฐ ์ „ ์ง์› ์ง€๊ธ‰์„ ์Šน์ธํ•จ."
174
+ elif section == "opinion_์‹œ์„ค์žฅ_role":
175
+ return "์žฌ๋‚œ ๋Œ€์ฑ… ๋ณธ๋ถ€ ์ด๊ด„ ์ง€ํœ˜, ๊ฑด๋ฌผ ์•ˆ์ „์„ฑ ๊ด€๋ฆฌ ๋ฐ ๋น„์ƒ ์šฉํ’ˆ ๊ฒฐ์žฌ"
176
+
177
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_1":
178
+ return f"์ง€์ง„ ๊ฒฝ๋ณด ์‹œ ํŒจ๋‹‰ ์ƒํƒœ์— ๋น ์งˆ ์ˆ˜ ์žˆ๋Š” ์ˆ˜๊ธ‰์ž {recipient_count}๋ช…์˜ ์ธ์ง€ ์ƒํƒœ๋ฅผ ๊ฐ์•ˆํ•ด ํŠน๋ณ„ ์‹ฌ๋ฆฌ ์ง€์› ๋ฐ 1:1 ๋Œ€ํ”ผ ๋งค์นญ ํ‘œ๋ฅผ ์ž‘์„ฑํ•จ."
179
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_2":
180
+ return "์žฌ๋‚œ ๋Œ€๋น„ ์ˆ˜๊ธ‰์ž ํ†ต๋ณด์ฒด๊ณ„๋ฅผ ๊ฒ€ํ† ํ•˜๊ณ , ์œ ์„  ์ƒ๋‹ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณดํ˜ธ์ž๋“ค์—๊ฒŒ ์žฌ๋‚œ ๋Œ€ํ”ผ ํ›ˆ๋ จ ๊ณ„ํš๊ณผ ๋Œ€ํ”ผ์†Œ ์œ„์น˜๋ฅผ ์„œ๋น„์Šค ๋™์˜์„œ์— ๋ช…์‹œํ•จ."
181
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_role":
182
+ return "์‹ฌ๋ฆฌ ๋ถˆ์•ˆ ์œ„ํ—˜์ž ์„ ๋ณ„, ๋น„์ƒ ๋Œ€ํ”ผ ๊ณ„ํš ์„œ๋น„์Šค ๊ณ„ํš ๋ฐ˜์˜, ํ›ˆ๋ จ ์‹œ๋‚˜๋ฆฌ์˜ค ์ž‘์„ฑ"
183
+
184
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_1":
185
+ return f"์ง€์ง„ ์ง„๋™ ๋ฐœ์ƒ ์‹œ ํœ ์ฒด์–ด {wheelchair_count}๋Œ€ ๋ฐ ๋ณดํ–‰๋ณด์กฐ ์žฅ๋น„์˜ ๋ฏธ๋„๋Ÿฌ์ง์œผ๋กœ ์ธํ•œ ์ถฉ๋Œ ๋ฐ ๊ฐ€๊ตฌ ๋‚™ํ•˜๋กœ ๋‚™์ƒ๊ณผ ์‹ ์ฒด ๊ณจ์ ˆ ์œ„ํ—˜์ด ํฌ๊ฒŒ ๊ด€์ฐฐ๋จ."
186
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_2":
187
+ return "์ง„๋™ ์‹œ ์ˆ˜๊ธ‰์ž๋ฅผ ํ…Œ์ด๋ธ” ๋ฐ‘์œผ๋กœ ๋Œ€ํ”ผ์‹œํ‚ค๊ฑฐ๋‚˜ ๋ฒ ๊ฐœ ๋“ฑ์œผ๋กœ ๋จธ๋ฆฌ๋ฅผ ์ตœ์šฐ์„ ์ ์œผ๋กœ ๋ณดํ˜ธํ•˜๋ฉฐ, ํœ ์ฒด์–ด์˜ ๋ฐ”ํ€ด ๊ณ ์ • ๋ ˆ๋ฒ„๋ฅผ ๋ฐ˜๋“œ์‹œ ์ œ๋™ ์œ„์น˜๋กœ ์žก๊ณ  ๋ฐ€์ฐฉ ๋Œ€๊ธฐํ•ด์•ผ ํ•จ."
188
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_role":
189
+ return "์‹ ์ฒด ๋‚™ํ•˜ ์œ„ํ—˜ ์ฐจ๋‹จ, ๋งค์นญ ์ˆ˜๊ธ‰์ž ๊ธด๊ธ‰ ๋ณดํ˜ธ ๋ฐ ์•ˆ์ „ ์œ ๋„"
190
+
191
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_1":
192
+ return f"์ง€์ง„์œผ๋กœ ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•œ ํƒ€๋ฐ•์ƒ, ์—ด์ƒ ๋“ฑ ๊ณจ์ ˆ ์˜์‹ฌ ํ™˜์ž์— ๋Œ€๋น„ํ•˜์—ฌ ์‹ ์† ์ง„๋‹จ ๊ฐ€์ด๋“œ๋ฅผ ํ™•์ธํ•˜๊ณ  ๋Œ€ํ”ผ ์™„๋ฃŒ ํ›„ ํ™œ๋ ฅ์ง•ํ›„ ๋ฐ ์‹ฌ๋ฆฌ ์ถฉ๊ฒฉ ์ƒํƒœ๋ฅผ ๊ด€์ฐฐํ•˜์˜€์Œ."
193
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_2":
194
+ return "๋น„์ƒ ๊ตฌ๊ธ‰ ํ‚คํŠธ ๋‚ด ๊น์Šค ๋ถ•๋Œ€ ๋ฐ ์™ธ์ƒ ์•ฝํ’ˆ ์žฌ๊ณ ๋ฅผ ํŒŒ์•…ํ•˜๊ณ , ๋‹น๋‡จ ํ™˜์ž ๋“ฑ ํˆฌ์•ฝ ์‹œ๊ฐ„์ด ์ค‘์š”ํ•œ ์ˆ˜๊ธ‰์ž์˜ ์•ฝํ’ˆ ํœด๋Œ€ ๋ณด์กด ์ƒํƒœ๋ฅผ ์ ๊ฒ€ํ•จ."
195
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_role":
196
+ return "์™ธ์ƒ ์‘๊ธ‰์ฒ˜์น˜, ๋น„์ƒ ๊ตฌ๊ธ‰ํ’ˆ ๊ด€๋ฆฌ, ๋Œ€ํ”ผ ์™„๋ฃŒ์ž ๊ฑด๊ฐ• ๊ฒ€์ง„"
197
+
198
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_1":
199
+ return "์ง€์ง„ ๋Œ€ํ”ผ ์‹œ ์•ผ์™ธ๋กœ ๋‚˜๊ฐ€๋Š” ์šธํ‰๋ถˆํ‰ํ•œ ๋ณด๋„๋ธ”๋ก์ด๋‚˜ ์ž๊ฐˆ๊ธธ ์œ„์—์„œ ๋ณดํ–‰ ๋ถˆ์•ˆ์ • ์ˆ˜๊ธ‰์ž๋“ค์˜ ๊ท ํ˜• ์ €ํ•˜๋กœ ๋ฐœ๋ชฉ ๋ถ€์ƒ ๋ฐ ์ „๋„ ์œ„ํ—˜์ด ๋†’์€ ๊ฒƒ์œผ๋กœ ํ™•์ธ๋จ."
200
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_2":
201
+ return "๋Œ€ํ”ผ๊ฒฝ๋กœ ์ƒ์˜ ๊ฒฝ์‚ฌ๋ฉด์„ ์ง€๋‚  ๋•Œ ๋’ค์—์„œ ๋ฐ›์ณ์ฃผ๋Š” ์‹ ์ฒด ์ง€์ง€ ์šด๋™๋ฒ•์„ ํ™œ์šฉํ•˜๊ณ  ํ›ˆ๋ จ ์ข…๋ฃŒ ํ›„ ํ”ผ๋กœ๊ฐ€ ์Œ“์ธ ๊ด€์ ˆ๊ณผ ๊ทผ์œก์„ ํ’€์–ด์ฃผ๊ธฐ ์œ„ํ•œ ์ด์™„ ์น˜๋ฃŒ๋ฅผ ์ง€๋„ํ•จ."
202
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_role":
203
+ return "์ด๋™ ๊ฒฝ๋กœ ๋…ธ๋ฉด ์ƒํƒœ ์•ˆ๋‚ด, ์ด๋™ ๋ณด์กฐ ๊ธฐ๊ตฌ ์ œ๋™ ์ž์„ธ ๊ต์ •"
204
+
205
+ # 2์ฐจ ๊ฒฐ๊ณผ ๋ฐ˜์˜
206
+ elif section == "result_problem":
207
+ return f"์ง„๋™ ์ƒํ™ฉ ์‹œ ํœ ์ฒด์–ด ๊ณ ์ • ์กฐ์น˜ ๋ฏธํก์œผ๋กœ 2์ฐจ ์ถฉ๋Œ ์œ„ํ—˜์ด ๊ฐ์ง€๋˜์—ˆ๊ณ , ๋Œ€ํ”ผ ๊ฒฝ๋กœ ๋‚ด ๋ณต๋„ ์ฝ”๋„ˆ ๋ถ€๋ถ„์˜ ๊ตํ–‰ ์ •์ฒด์™€ ํ•จ๊ป˜ ์ค‘์ฆ ์น˜๋งค ์ˆ˜๊ธ‰์ž 1๋ช…์˜ ๋Œ€ํ”ผ ๊ฑฐ๋ถ€ ๋Œ๋ฐœ ํ–‰๋™์ด ๋ฐœ์ƒํ•จ."
208
+ elif section == "result_action":
209
+ return f"์ง€์ง„ ๋ฐœ์ƒ์— ๋”ฐ๋ฅธ ๋จธ๋ฆฌ ๋ณดํ˜ธ(๋ฒ ๊ฐœ ๋ฐ ๋ฐฉ์„ ํ™œ์šฉ) ํ›„, ์ง„๋™์ด ๋ฉˆ์ถ˜ ์ƒํƒœ๋ฅผ ๊ฐ€์ •ํ•˜๊ณ  ๋Œ€ํ”ผ๊ฒฝ๋กœ({route_checked})๋ฅผ ๋”ฐ๋ผ ์•ผ์™ธ ๋Œ€ํ”ผํ•˜์˜€์œผ๋ฉฐ, ์ •์ „ ๋Œ€๋น„ ํ”Œ๋ž˜์‹œ ํ™œ์šฉ ๋ฐ ์—ฐ๋ฝ์ฒด๊ณ„({contact_checked})๋ฅผ ๊ฒ€ํ† ํ•จ."
210
+ elif section == "result_role_actions":
211
+ return "์‹œ์„ค์žฅ์€ ๋น„์ƒ ๋ฐœ์ „ ์ƒํƒœ๋ฅผ ์ฒดํฌํ•˜๊ณ , ๋ณต์ง€์‚ฌ๋Š” ์น˜๋งค ์ˆ˜๊ธ‰์ž์—๊ฒŒ ์•ˆ์‹ฌ ์ง€์ง€ ์š”๋ น์„ ์ œ๊ณตํ–ˆ์œผ๋ฉฐ, ์š”์–‘๋ณดํ˜ธ์‚ฌ๋Š” 1:1 ๋Œ€ํ”ผ ์ด์†ก์„, ๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ๋Š” ํ™œ๋ ฅ์ง•ํ›„ ๋ฐ ๊ตฌํ˜ธ ์•ฝํ’ˆ์„ ์ง€์ฐธํ•˜์˜€๊ณ , ๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ๋Š” ์ง€์ง„ ์‹œ ์ด๋™ ์ง€์ง€๏ฟฝ๏ฟฝ๏ฟฝ ๋‹ด๋‹นํ•จ."
212
+ elif section == "result_outcome":
213
+ return f"์ดˆ๊ธฐ ๋จธ๋ฆฌ ๋ณดํ˜ธ ์š”๋ น ๋ฐ ์งˆ์„œ ์ •์—ฐํ•œ ์ด๋™์„ ํ†ตํ•ด ๋Œ€ํ”ผ์™„๋ฃŒ ์‹œ๊ฐ„์ด {evac_time}๋กœ ์ธก์ •๋˜์—ˆ๊ณ , ์žฌ๋‚œ ์ƒํ™ฉ์— ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋Š” ์š”๋ น์ด ์„ฑ๊ณต์ ์œผ๋กœ ์Šต๋“๋˜์—ˆ์Œ."
214
+ elif section == "result_data":
215
+ return f"์ด ์ฐธ์—ฌ์ž {total_participants}๋ช… (์ข…์‚ฌ์ž {staff_count}๋ช…, ์ˆ˜๊ธ‰์ž {recipient_count}๋ช…), ๋Œ€ํ”ผ์ทจ์•ฝ์ž {vulnerable_count}๋ช…, ํœ ์ฒด์–ด {wheelchair_count}๋Œ€, ๋ณดํ–‰๋ณด์กฐ {walk_aid_count}๋ช…, ๋Œ€ํ”ผ์™„๋ฃŒ {evac_time}, ์†Œํ™”๊ธฐ ์‹ค์Šต {fire_ext_demo}, ์‘๊ธ‰๋Œ€์‘ {emergency_mock}."
216
+ elif section == "result_risks":
217
+ return "์•ผ์™ธ ์ง‘๊ฒฐ์ง€์ธ ์ฃผ์ฐจ์žฅ ๋…ธ๋ฉด์— ๋Œ์ถœ๋œ ๊ฒฝ๊ณ„์„์ด ๋ณดํ–‰์ž ์ด๋™ ์‹œ ๋ฐœ ๊ฑธ๋ฆผ ๋‚™์ƒ ์š”์†Œ๋กœ ์‹๋ณ„๋˜์—ˆ๊ณ , ์žฌ๋‚œ ์ƒํ™ฉ ๊ธด์žฅ๊ฐ์œผ๋กœ ์ผ๋ถ€ ๊ณ ๋ น ์ˆ˜๊ธ‰์ž์˜ ๋‹จ๊ธฐ ํ˜ˆ์•• ์ƒ์Šน์„ธ๊ฐ€ ์œ ์ง€๋จ."
218
+ elif section == "result_next":
219
+ return "์ง‘๊ฒฐ์ง€ ๋ฐ”๋‹ฅ์˜ ๋Œ์ถœ๋ฌผ์— ํ™ฉ์ƒ‰ ์•ˆ์ „ ํ…Œ์ดํ”„๋ฅผ ๋ถ€์ฐฉํ•˜๊ณ  ๋ฏธ๋„๋Ÿผ ๋ฐฉ์ง€ ์ฒ˜๋ฆฌ๋ฅผ ์ถ”๊ฐ€ ์ˆ˜๋ฆฝํ•˜๋ฉฐ, ๋‹ค์Œ ํ›ˆ๋ จ ์‹œ์—๋Š” ์ธ๊ทผ ์‹ค๋‚ด ์ง€์ • ๋Œ€ํ”ผ์†Œ(๋Œ€๊ฐ•๋‹น)๋กœ์˜ ์‹ค์งˆ ์—ฐ๊ณ„ ๋™์„  ํ›ˆ๋ จ์„ ์‹ค์‹œํ•˜๊ฒ ์Œ."
220
+ elif section == "result_guardian":
221
+ return f"๋ณดํ˜ธ์ž ์œ ์„  ์ƒ๋‹ด({guardian_call_date}) ๊ฒฐ๊ณผ ๊ฑฐ๋™๋ถˆํŽธ ์ˆ˜๊ธ‰์ž์˜ ๋Œ€ํ”ผ ์•ˆ์ „ ์šฐ๋ ค๊ฐ€ ์žˆ์–ด 1:1 ์ „๋‹ด ์ธ๋ ฅ ๋งค์นญ ๊ณ„ํš์„ ์„ค๋ช…ํ•˜์˜€์œผ๋ฉฐ, ๋ณดํ˜ธ์ž ๋น„์ƒ ์—ฐ๋ฝ์ฒ˜ ์ตœ์‹ ํ™”๋ฅผ ํ†ตํ•ด {guardian_reflected} ์ƒํƒœ๋ฅผ ์™„๋ฃŒํ•จ."
222
+
223
+ else: # ์•ˆ์ „๊ต์œก
224
+ # Multi-occupational Opinions
225
+ if section == "opinion_์‹œ์„ค์žฅ_1":
226
+ return "๊ธฐ๊ด€ ๋‚ด ๋‚™์ƒ, ์งˆ์‹, ์†Œ๋ฐฉ ๋“ฑ ์•ˆ์ „ ๊ด€๋ จ ๋งค๋‰ด์–ผ์„ ์ˆ˜๊ธ‰์ž ์ž…์†Œ ๊ทœ์ •์— ์˜๋ฌด ์ฒจ๋ถ€ํ•˜๊ณ , ์ง์ข… ๊ฐ„์˜ ๋งค๋‰ด์–ผ ์ˆ™์ง€ ํŽธ์ฐจ๊ฐ€ ์—†๋„๋ก ์—ฐ๊ฐ„ ์•ˆ์ „๊ต์œก ์ด์ˆ˜์ œ๋ฅผ ์šด์˜ ์ง€์‹œํ•จ."
227
+ elif section == "opinion_์‹œ์„ค์žฅ_2":
228
+ return "์‘๊ธ‰์ƒํ™ฉ ๋ชจ์˜๋Œ€์‘ ๋Šฅ๋ ฅ ํ–ฅ์ƒ์„ ์œ„ํ•œ ๊ณ ์„ฑ๋Šฅ CPR ๋งˆ๋„คํ‚น ๋ฐ ์†Œ๋ฐฉ ์‚ด์ˆ˜ ์žฅ๋น„ ๊ตฌ์ž…์„ ์ง€์›ํ•˜๊ณ  ์›๋‚ด ๋Œ€ํ”ผ ์œ ๋„ ์œ ๊ด‘ ์กฐ๋ผ ๊ตฌ์ž… ์˜ˆ์‚ฐ์„ ์ „์•ก ๋ฐฐ์ •ํ•จ."
229
+ elif section == "opinion_์‹œ์„ค์žฅ_role":
230
+ return "์•ˆ์ „ ๊ต์œก ์ฒด๊ณ„ ๊ตฌ์ถ•, ์‹œ์„ค ๋‚ด ์•ˆ์ „ ๊ทœ์ • ์ค€์ˆ˜ ๊ฐ๋… ๋ฐ ๊ต์œก ๊ต๊ตฌ ์Šน์ธ"
231
+
232
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_1":
233
+ return f"๋‚™์ƒ ๋ฐ ์งˆ์‹ ๊ณ ์œ„ํ—˜ ์ˆ˜๊ธ‰์ž {vulnerable_count}๋ช…์˜ ์‚ฌ๋ก€ ํšŒ์˜๋ฅผ ํ†ตํ•ด ๊ฐœ๋ณ„ ๋งž์ถคํ˜• ๊ธ‰์—ฌ์ œ๊ณต๊ณ„ํš์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์•ˆ์ „๊ต์œก์— ๋”ฐ๋ฅธ ์˜ˆ๋ฐฉ ์ˆ˜์น™์„ ์ •๋น„ํ•จ."
234
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_2":
235
+ return "๋ณดํ˜ธ์ž์™€์˜ ์ƒ๋‹ด ๊ธฐ๋ก์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ธฐ๊ด€ ๋‚ด ์‘๊ธ‰์ƒํ™ฉ ๋Œ€์‘ ์ ˆ์ฐจ๋ฅผ ๊ณต์œ ํ•˜๊ณ  ๋™์˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜์—ฌ, ์•ˆ์ „ ๊ต์œก ๊ณ„ํš ๋ฐ CPR ๋™์˜์„œ๋ฅผ ์ˆ˜์ง‘ยท๋ณด๊ด€ํ•จ."
236
+ elif section == "opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_role":
237
+ return "์•ˆ์ „ ๋™์˜์„œ ๊ด€๋ฆฌ, ์ˆ˜๊ธ‰์ž ๋‚™์ƒ์œ„ํ—˜๋„ ์žฌํ‰๊ฐ€ ๋ฐ ๊ต์œก ์‹ค์Šต ํ–‰์ • ๊ธฐ๋ก"
238
+
239
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_1":
240
+ return f"์ธ์ง€ ์žฅ์• ๊ฐ€ ์žˆ๋Š” ์ˆ˜๊ธ‰์ž๋“ค์€ ๊ธฐ์นจ ๋ฐ˜์‚ฌ๊ฐ€ ์ €ํ•˜๋˜์–ด ์‹์‚ฌ ์‹œ ๋ชฉ ๋„˜๊น€์ด ๋ถˆ์™„์ „ํ•ด ์งˆ์‹ ์œ„ํ—˜์ด ์žˆ์œผ๋ฉฐ, ํœ ์ฒด์–ด ์ œ๋™ ์žฅ์น˜๋ฅผ ์ˆ˜์‹œ๋กœ ์žŠ์–ด ์นจ๋Œ€ ํƒ‘์Šน ์‹œ ๋‚™์ƒ ์œ„ํ—˜์ด ๋†’์Œ."
241
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_2":
242
+ return f"์‹์‚ฌ ์ง€์› ์‹œ ์ƒ์ฒด๋ฅผ ๋ฐ”๋ฅด๊ฒŒ ์„ธ์šฐ๋Š” ์‹์‚ฌ ์ž์„ธ๋ฅผ ๊ต์ •ํ•˜๊ณ , ํœ ์ฒด์–ด ์Šนํ•˜์ฐจ ์‹œ์—๋Š” ๋ธŒ๋ ˆ์ดํฌ ์ƒํƒœ๋ฅผ ๋ณดํ˜ธ์ž๊ฐ€ ์ „ํ™” ์ƒ๋‹ด์—์„œ ์–ธ๊ธ‰ํ•œ ๋‚™์ƒ ๋ฐฉ์ง€ ์ˆ˜์น™์— ๋งž์ถฐ ํ•„ํžˆ ์ด์ค‘ ์ž ๊ธˆํ•˜์—ฌ ์ œ๊ณตํ•จ."
243
+ elif section == "opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_role":
244
+ return "์•ˆ์ „ ์‹์‚ฌ ๋™ํ–‰ ๋ณด์กฐ, ํœ ์ฒด์–ด ์•ˆ์ „ ์กฐ์ž‘ ๋ฐ ๋‚™์ƒ ์˜ˆ๋ฐฉ ๊ทœ์น™ ์ ์šฉ"
245
+
246
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_1":
247
+ return "์งˆ์‹ ์ƒํ™ฉ ๋ชจ์˜ ์‹œ ํ•˜์ž„๋ฆฌํžˆ๋ฒ•์„ ์ •ํ™•ํ•˜๊ฒŒ ์‹œ์—ฐํ•˜๊ณ , ์‹ฌ์ •์ง€ ์ˆ˜๊ธ‰์ž ๋ฐœ์ƒ์— ๋”ฐ๋ฅธ ์‹ ์†ํ•œ ์ธ๊ณตํ˜ธํก ๋ฐ ์ž๋™์‹ฌ์žฅ์ถฉ๊ฒฉ๊ธฐ(AED) ํŒจ๋“œ ๋ถ€์ฐฉ ์œ„์น˜์™€ ์ƒํ™ฉ๋ณ„ ์‹ฌ์ „๋„ ๋ถ„์„ ์ ˆ์ฐจ๋ฅผ ๊ต์œกํ•จ."
248
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_2":
249
+ return "๊ฐ์—ผ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์† ์†Œ๋… ์ ˆ์ฐจ ๋ฐ ์ „์—ผ๋ณ‘ ์œ ํ–‰ ์‹œ ๊ฒฉ๋ฆฌ ์ง€์นจ์„ ์‚ฌ์ „์— ์ˆ˜๋ฆฝํ•˜๊ณ  ๋น„์ƒ ์•ฝํ’ˆ ์บ๋น„๋‹›์˜ ์—ด์‡  ๋ฐ ๋ฐฐ์น˜ ์ƒํƒœ๋ฅผ ์ „ ์ง์›์— ์ „ํŒŒํ•จ."
250
+ elif section == "opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_role":
251
+ return "ํ•˜์ž„๋ฆฌํžˆ๋ฒ• ๋ฐ CPR ์‹œ์—ฐ ๊ต์œก ์ฃผ๋„, ๊ฐ์—ผ๋ณ‘ ์˜ˆ๋ฐฉ ๊ทœ์น™ ์ง€๋„"
252
+
253
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_1":
254
+ return "๋ณดํ–‰๋ณด์กฐ๊ธฐ(์›Œ์ปค) ์‚ฌ์šฉ ์–ด๋ฅด์‹ ๋“ค์ด ๋ฐฉํ–ฅ ์ „ํ™˜ ์‹œ ๋‹ค๋ฆฌ ์—‰ํ‚ด์œผ๋กœ ์ธํ•œ ๋‚™์ƒ ์œ„ํ—˜์ด ํผ์„ ํ™•์ธํ•˜๊ณ  ํ•˜์ง€ ๊ทผ๋ ฅ ๊ฐ•ํ™”๋ฅผ ์œ„ํ•œ ์žฌํ™œ ์šด๋™์ด ์ค‘์š”ํ•จ์„ ์ธ์ง€ํ•จ."
255
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_2":
256
+ return "ํœ ์ฒด์–ด์™€ ์›Œ์ปค ์‚ฌ์ด์˜ ์˜ฌ๋ฐ”๋ฅธ ์ฒด์ค‘ ์ด๋™ ์ค‘์‹ฌ ํ›ˆ๋ จ์„ ์ฃผ 3ํšŒ ์ •๊ธฐ ์ง„ํ–‰ํ•˜๊ณ , ๋‚™์ƒ ์˜ˆ๋ฐฉ 3๋Œ€ ์‹ ์ฒด ๋ณด์กฐ ๊ธฐ๋ฒ•์„ ์š”์–‘๋ณดํ˜ธ์‚ฌ์—๊ฒŒ ์ง๋ฌด ๊ต์œก์œผ๋กœ ์—ฐ๊ณ„ํ•จ."
257
+ elif section == "opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_role":
258
+ return "๋‚™์ƒ ์˜ˆ๋ฐฉ ์ŠคํŠธ๋ ˆ์นญ ๊ต์œก, ๋ณด์กฐ ๋ณดํ–‰ ๊ธฐ๊ตฌ ๊ต์ • ๋ฐ ๋ณดํ–‰ ์žฌํ™œ ์šด๋™ ์ œ๊ณต"
259
+
260
+ # 2์ฐจ ๊ฒฐ๊ณผ ๋ฐ˜์˜
261
+ elif section == "result_problem":
262
+ return "์ˆ˜๊ธ‰์ž๋“ค์˜ ๊ทผ๋ ฅ ์•ฝํ™”๋กœ ๋‚™์ƒ ์œ„ํ—˜๋„๊ฐ€ ๋†’์€ ์ƒํƒœ์—์„œ ์‘๊ธ‰ ๋„๊ตฌ(AED) ๋ฐ ์•ฝํ’ˆํ•จ ๋ณด๊ด€ ์œ„์น˜ ์ธ์ง€ ๋ถ€์กฑ์ด ํ™•์ธ๋˜์—ˆ๊ณ , ์—ญํ•  ๋ถ„๋‹ด์— ๋”ฐ๋ฅธ ์‹ ์†ํ•œ ์‘๊ธ‰ ์กฐ์น˜ ์—ฐ๊ณ„๊ฐ€ ์ผ๋ถ€ ๋ฏธํกํ•˜์˜€์Œ."
263
+ elif section == "result_action":
264
+ return f"๋‹ค์ง์ข… ํ•ฉ๋™ ์•ˆ์ „๊ต์œก์„ ์‹ค์‹œํ•˜๊ณ  ๋Œ€ํ”ผ์ทจ์•ฝ์ž {vulnerable_count}๋ช…์— ๋Œ€ํ•œ 1:1 ๋ณดํ–‰ ์ง€์›๋ฒ•์„ ์‹ค์Šตํ•˜์˜€์œผ๋ฉฐ, ํ•˜์ž„๋ฆฌํžˆ๋ฒ• ๋ฐ AED๋ฅผ ํ™œ์šฉํ•œ ์‹ฌํ์†Œ์ƒ์ˆ  ๋ชจ์˜์‹ค์Šต({emergency_mock})์„ ์ง„ํ–‰ํ•จ."
265
+ elif section == "result_role_actions":
266
+ return "์‹œ์„ค์žฅ์€ ์•ˆ์ „ ๊ฐ๋…์„, ๋ณต์ง€์‚ฌ๋Š” ์•ˆ์ „ ๋™์˜์„œ ์ˆ˜์ง‘ ๋ฐ ๊ธฐ๋ก์„, ์š”์–‘๋ณดํ˜ธ์‚ฌ๋Š” ํœ ์ฒด์–ด ์ด์ค‘ ์ œ๋™ ์‹ค์Šต์„, ๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ๋Š” ํ•˜์ž„๋ฆฌํžˆ๋ฒ•๊ณผ CPR ๊ต์œก์„, ๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ๋Š” ๋‚™์ƒ ๋ฐฉ์ง€ ๋ณดํ–‰ ์ค‘์‹ฌ ์ง€๋„๋ฅผ ๋‹ด๋‹นํ•จ."
267
+ elif section == "result_outcome":
268
+ return "์ „ ์ง์›์ด ์‘๊ธ‰์ƒํ™ฉ ๋ฐœ์ƒ ์‹œ ๋ณธ์ธ์˜ ๋‹ด๋‹น ์—ญํ• ์„ ์ˆ™์ง€ํ•˜๊ณ  AED ์กฐ์ž‘ ๋ฐ ํ•˜์ž„๋ฆฌํžˆ๋ฒ• ๋“ฑ ์œ„๊ธ‰ ์ƒํ™ฉ์—์„œ์˜ ์ดˆ๊ธฐ ๋Œ€์‘ ์ฒ˜์น˜ ๋Šฅ๋ ฅ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋˜์—ˆ์Œ."
269
+ elif section == "result_data":
270
+ return f"์ด ์ฐธ์—ฌ์ž {total_participants}๋ช… (์ข…์‚ฌ์ž {staff_count}๋ช…, ์ˆ˜๊ธ‰์ž {recipient_count}๋ช…), ๋Œ€ํ”ผ์ทจ์•ฝ์ž {vulnerable_count}๋ช…, ํœ ์ฒด์–ด {wheelchair_count}๋Œ€, ๋ณดํ–‰๋ณด์กฐ {walk_aid_count}๋ช…, ๋Œ€ํ”ผ์™„๋ฃŒ {evac_time}, ์†Œํ™”๊ธฐ ์‹ค์Šต {fire_ext_demo}, ์‘๊ธ‰๋Œ€์‘ {emergency_mock}."
271
+ elif section == "result_risks":
272
+ return "์ข…์‚ฌ์ž๋“ค์˜ ๊ทผ๋ฌด ๊ต๋Œ€ ์‹œ ๋น„์ƒ ์—ญํ•  ์ธ์ˆ˜์ธ๊ณ„ ๋งค๋‰ด์–ผ ์ˆ™์ง€ ํŽธ์ฐจ๊ฐ€ ๋ฏธ์„ธํ•˜๊ฒŒ ๊ด€์กดํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์›๋‚ด ์ผ๋ถ€ ๋ณต๋„ ์กฐ๋ช…์ด ๋‹ค์†Œ ์–ด๋‘์›Œ ์•ผ๊ฐ„ ๋‚™์ƒ ์œ ๋ฐœ ์š”์ธ์œผ๋กœ ์ž‘์šฉํ•  ์šฐ๋ ค๊ฐ€ ๋ณด์ž„."
273
+ elif section == "result_next":
274
+ return "๊ต๋Œ€ ๋Œ€์žฅ ์–‘์‹์— '๋น„์ƒ๋Œ€๋น„๋ฐ˜ ์—ญํ• '์„ ํ‘œ๊ธฐํ•˜๋Š” ์กฐ์น˜๋ฅผ ๊ทœ์ • ๊ฐœ์ •ํ•˜๊ณ , ์–ด๋‘์šด ๋ณต๋„์— ๋™์ž‘ ๊ฐ์ง€์‹ ์•ผ๊ฐ„ ์•ˆ์ „ ์œ ๋„๋“ฑ์„ ์ถ”๊ฐ€ ์‹œ๊ณตํ•˜๋ฉฐ, ๋ถ„๊ธฐ๋ณ„ 1ํšŒ CPR ๋ชจ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹ค์‹œํ•˜๊ฒ ์Œ."
275
+ elif section == "result_guardian":
276
+ return f"๋ณดํ˜ธ์ž ์œ ์„  ์ƒ๋‹ด({guardian_call_date}) ๊ฒฐ๊ณผ ๊ฑฐ๋™๋ถˆํŽธ ์ˆ˜๊ธ‰์ž์˜ ๋Œ€ํ”ผ ์•ˆ์ „ ์šฐ๋ ค๊ฐ€ ์žˆ์–ด 1:1 ์ „๋‹ด ์ธ๋ ฅ ๋งค์นญ ๊ณ„ํš์„ ์„ค๋ช…ํ•˜์˜€์œผ๋ฉฐ, ๋ณดํ˜ธ์ž ๋น„์ƒ ์—ฐ๋ฝ์ฒ˜ ์ตœ์‹ ํ™”๋ฅผ ํ†ตํ•ด {guardian_reflected} ์ƒํƒœ๋ฅผ ์™„๋ฃŒํ•จ."
277
+
278
+ return ""
279
+
280
+ # ---------------------------------------------------------
281
+ # Compile Data Structures for Excel Workbook
282
+ # ---------------------------------------------------------
283
+ def compile_document_data(info, training_type):
284
+ data = {
285
+ 'facility_name': info['facility_name'],
286
+ 'facility_head': info['facility_head'],
287
+ 'writer': info['writer'],
288
+ 'training_date': info['training_date'].strftime('%Y-%m-%d') if isinstance(info['training_date'], (date, datetime)) else str(info['training_date']),
289
+ 'training_time': info['training_time'],
290
+ 'training_location': info['training_location'],
291
+ 'training_type': training_type,
292
+ 'host': info['host'],
293
+ 'total_participants': info['total_participants'],
294
+ 'staff_participants': info['staff_participants'],
295
+ 'recipient_participants': info['recipient_participants'],
296
+ 'evac_time': info['evac_time'],
297
+ 'vulnerable_count': info['vulnerable_count'],
298
+ 'wheelchair_count': info['wheelchair_count'],
299
+ 'walk_aid_count': info['walk_aid_count'],
300
+ 'emergency_mock': info['emergency_mock'],
301
+ 'fire_ext_demo': info['fire_ext_demo'],
302
+ 'route_checked': info['route_checked'],
303
+ 'contact_checked': info['contact_checked'],
304
+ 'guardian_call_date': info['guardian_call_date'].strftime('%Y-%m-%d') if isinstance(info['guardian_call_date'], (date, datetime)) else str(info['guardian_call_date']),
305
+ 'guardian_opinion': info['guardian_opinion'],
306
+ 'guardian_response': info['guardian_response'],
307
+ 'guardian_reflected': info['guardian_reflected'],
308
+ }
309
+
310
+ # 5 Job Roles Opinions
311
+ roles_list = ['์‹œ์„ค์žฅ', '์‚ฌํšŒ๋ณต์ง€์‚ฌ', '์š”์–‘๋ณดํ˜ธ์‚ฌ', '๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ', '๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ']
312
+ for r in roles_list:
313
+ data[f'opinion_{r}_1'] = generate_narrative_text(data, f'opinion_{r}_1', training_type)
314
+ data[f'opinion_{r}_2'] = generate_narrative_text(data, f'opinion_{r}_2', training_type)
315
+ data[f'opinion_{r}_role'] = generate_narrative_text(data, f'opinion_{r}_role', training_type)
316
+
317
+ # 2์ฐจ ๊ฒฐ๊ณผ ๋ฐ˜์˜
318
+ data['result_problem'] = generate_narrative_text(data, 'result_problem', training_type)
319
+ data['result_action'] = generate_narrative_text(data, 'result_action', training_type)
320
+ data['result_role_actions'] = generate_narrative_text(data, 'result_role_actions', training_type)
321
+ data['result_outcome'] = generate_narrative_text(data, 'result_outcome', training_type)
322
+ data['result_data'] = generate_narrative_text(data, 'result_data', training_type)
323
+ data['result_risks'] = generate_narrative_text(data, 'result_risks', training_type)
324
+ data['result_next'] = generate_narrative_text(data, 'result_next', training_type)
325
+ data['result_guardian'] = generate_narrative_text(data, 'result_guardian', training_type)
326
+
327
+ return data
328
+
329
+ # ---------------------------------------------------------
330
+ # openpyxl Styling Helpers
331
+ # ---------------------------------------------------------
332
+ header_fill = PatternFill(start_color="F2F4F7", end_color="F2F4F7", fill_type="solid") # soft gray
333
+ section_fill = PatternFill(start_color="E8EFF9", end_color="E8EFF9", fill_type="solid") # professional light blue
334
+
335
+ label_font = Font(name="๋ง‘์€ ๊ณ ๋”•", size=9.5, bold=True, color="374151")
336
+ value_font = Font(name="๋ง‘์€ ๊ณ ๋”•", size=9.5, color="111827")
337
+ section_font = Font(name="๋ง‘์€ ๊ณ ๋”•", size=10.5, bold=True, color="1A365D")
338
+
339
+ align_center = Alignment(vertical="center", horizontal="center")
340
+ align_left = Alignment(vertical="center", horizontal="left", indent=1)
341
+ align_left_wrap = Alignment(vertical="center", horizontal="left", wrap_text=True)
342
+
343
+ thin_border = Border(
344
+ left=Side(style='thin', color='D0D5DD'),
345
+ right=Side(style='thin', color='D0D5DD'),
346
+ top=Side(style='thin', color='D0D5DD'),
347
+ bottom=Side(style='thin', color='D0D5DD')
348
+ )
349
+
350
+ def style_range(ws, cell_range, border=None, fill=None, font=None, alignment=None):
351
+ for row in ws[cell_range]:
352
+ for cell in row:
353
+ if border is not None:
354
+ cell.border = border
355
+ if fill is not None:
356
+ cell.fill = fill
357
+ if font is not None:
358
+ cell.font = font
359
+ if alignment is not None:
360
+ cell.alignment = alignment
361
+
362
+ def write_spacer(ws, r_num):
363
+ ws.row_dimensions[r_num].height = 10
364
+
365
+ def write_section_header(ws, r_num, title):
366
+ ws.row_dimensions[r_num].height = 25
367
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=9)
368
+ ws.cell(row=r_num, column=1, value=title)
369
+ style_range(ws, f"A{r_num}:I{r_num}", fill=section_fill, font=section_font, alignment=align_left, border=thin_border)
370
+
371
+ def setup_page_print(ws):
372
+ ws.page_setup.orientation = ws.ORIENTATION_PORTRAIT
373
+ ws.page_setup.paperSize = ws.PAPERSIZE_A4
374
+ ws.sheet_properties.pageSetUpPr.fitToPage = True
375
+ ws.page_setup.fitToWidth = 1
376
+ ws.page_setup.fitToHeight = 1
377
+
378
+ ws.page_margins.left = 0.5
379
+ ws.page_margins.right = 0.5
380
+ ws.page_margins.top = 0.5
381
+ ws.page_margins.bottom = 0.5
382
+
383
+ ws.views.sheetView[0].showGridLines = True
384
+
385
+ def write_general_info_row(ws, r_num, key1, val1, key2, val2):
386
+ ws.row_dimensions[r_num].height = 24
387
+
388
+ # Left key-val
389
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
390
+ ws.cell(row=r_num, column=1, value=key1)
391
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=4)
392
+ ws.cell(row=r_num, column=3, value=val1)
393
+
394
+ # Right key-val
395
+ ws.merge_cells(start_row=r_num, start_column=5, end_row=r_num, end_column=6)
396
+ ws.cell(row=r_num, column=5, value=key2)
397
+ ws.merge_cells(start_row=r_num, start_column=7, end_row=r_num, end_column=9)
398
+ ws.cell(row=r_num, column=7, value=val2)
399
+
400
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
401
+ style_range(ws, f"C{r_num}:D{r_num}", font=value_font, alignment=align_center, border=thin_border)
402
+ style_range(ws, f"E{r_num}:F{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
403
+ style_range(ws, f"G{r_num}:I{r_num}", font=value_font, alignment=align_center, border=thin_border)
404
+
405
+ # ---------------------------------------------------------
406
+ # Excel Creator: Header and Content Helpers
407
+ # ---------------------------------------------------------
408
+ def write_title_and_approval(ws, title_text, info):
409
+ ws.row_dimensions[1].height = 22
410
+ ws.row_dimensions[2].height = 43
411
+
412
+ ws.merge_cells(start_row=1, start_column=1, end_row=2, end_column=7)
413
+ title_cell = ws.cell(row=1, column=1)
414
+ title_cell.value = title_text
415
+ style_range(ws, "A1:G2",
416
+ font=Font(name="๋ง‘์€ ๊ณ ๋”•", size=15, bold=True, color="111827"),
417
+ alignment=align_center,
418
+ border=thin_border)
419
+
420
+ ws.cell(row=1, column=8, value="๋‹ด๋‹น์ž")
421
+ ws.cell(row=1, column=9, value="์‹œ์„ค์žฅ")
422
+ style_range(ws, "H1:I1",
423
+ fill=header_fill,
424
+ font=Font(name="๋ง‘์€ ๊ณ ๋”•", size=9.5, bold=True, color="374151"),
425
+ alignment=align_center,
426
+ border=thin_border)
427
+
428
+ ws.cell(row=2, column=8, value="")
429
+ ws.cell(row=2, column=9, value="")
430
+ style_range(ws, "H2:I2", border=thin_border)
431
+
432
+ def write_plan_participants(ws, r_num, info):
433
+ ws.row_dimensions[r_num].height = 24
434
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
435
+ ws.cell(row=r_num, column=1, value="์ด ์ฐธ์—ฌ์ธ์›")
436
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=4)
437
+ ws.cell(row=r_num, column=3, value=f"{info['total_participants']} ๋ช…")
438
+
439
+ ws.merge_cells(start_row=r_num, start_column=5, end_row=r_num, end_column=6)
440
+ ws.cell(row=r_num, column=5, value="์ข…์‚ฌ์ž ์ˆ˜")
441
+ ws.cell(row=r_num, column=7, value=f"{info['staff_participants']} ๋ช…")
442
+
443
+ ws.cell(row=r_num, column=8, value="์ˆ˜๊ธ‰์ž ์ˆ˜")
444
+ ws.cell(row=r_num, column=9, value=f"{info['recipient_participants']} ๋ช…")
445
+
446
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
447
+ style_range(ws, f"C{r_num}:D{r_num}", font=value_font, alignment=align_center, border=thin_border)
448
+ style_range(ws, f"E{r_num}:F{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
449
+
450
+ ws.cell(row=r_num, column=7).font = value_font
451
+ ws.cell(row=r_num, column=7).alignment = align_center
452
+ ws.cell(row=r_num, column=7).border = thin_border
453
+
454
+ ws.cell(row=r_num, column=8).fill = header_fill
455
+ ws.cell(row=r_num, column=8).font = label_font
456
+ ws.cell(row=r_num, column=8).alignment = align_center
457
+ ws.cell(row=r_num, column=8).border = thin_border
458
+
459
+ ws.cell(row=r_num, column=9).font = value_font
460
+ ws.cell(row=r_num, column=9).alignment = align_center
461
+ ws.cell(row=r_num, column=9).border = thin_border
462
+
463
+ r_num += 1
464
+
465
+ ws.row_dimensions[r_num].height = 24
466
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
467
+ ws.cell(row=r_num, column=1, value="๋Œ€ํ”ผ์ทจ์•ฝ์ž ์ˆ˜")
468
+ ws.cell(row=r_num, column=3, value=f"{info['vulnerable_count']} ๋ช…")
469
+
470
+ ws.merge_cells(start_row=r_num, start_column=4, end_row=r_num, end_column=5)
471
+ ws.cell(row=r_num, column=4, value="ํœ ์ฒด์–ด ์‚ฌ์šฉ ๋Œ€์ƒ์ž")
472
+ ws.cell(row=r_num, column=6, value=f"{info['wheelchair_count']} ๋ช…")
473
+
474
+ ws.merge_cells(start_row=r_num, start_column=7, end_row=r_num, end_column=8)
475
+ ws.cell(row=r_num, column=7, value="๋ณดํ–‰๋ณด์กฐ ํ•„์š”์ž")
476
+ ws.cell(row=r_num, column=9, value=f"{info['walk_aid_count']} ๋ช…")
477
+
478
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
479
+ ws.cell(row=r_num, column=3).font = value_font
480
+ ws.cell(row=r_num, column=3).alignment = align_center
481
+ ws.cell(row=r_num, column=3).border = thin_border
482
+
483
+ style_range(ws, f"D{r_num}:E{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
484
+ ws.cell(row=r_num, column=6).font = value_font
485
+ ws.cell(row=r_num, column=6).alignment = align_center
486
+ ws.cell(row=r_num, column=6).border = thin_border
487
+
488
+ style_range(ws, f"G{r_num}:H{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
489
+ ws.cell(row=r_num, column=9).font = value_font
490
+ ws.cell(row=r_num, column=9).alignment = align_center
491
+ ws.cell(row=r_num, column=9).border = thin_border
492
+
493
+ return r_num
494
+
495
+ def write_plan_details(ws, r_num, info):
496
+ write_section_header(ws, r_num, "2. ํ›ˆ๋ จ ๋ชฉ์  ๋ฐ ๊ณ„ํš")
497
+ r_num += 1
498
+
499
+ ws.row_dimensions[r_num].height = 24
500
+ ws.row_dimensions[r_num+1].height = 24
501
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num+1, end_column=2)
502
+ ws.cell(row=r_num, column=1, value="ํ›ˆ๋ จ ๋ชฉ์ ")
503
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num+1, end_column=9)
504
+
505
+ purpose_text = (
506
+ f"{info['training_type']} ์ƒํ™ฉ ๋ฐœ์ƒ ์‹œ ์‹ ์†ํ•˜๊ณ  ์ฒด๊ณ„์ ์ธ ๋Œ€ํ”ผ ๋ฐ ์ดˆ๊ธฐ ๋Œ€์‘ ๋Šฅ๋ ฅ์„ ๋ฐฐ์–‘ํ•˜์—ฌ ์ˆ˜๊ธ‰์ž์˜ ์ƒ๋ช…๊ณผ ์‹ ์ฒด๋ฅผ ๋ณดํ˜ธํ•˜๊ณ , "
507
+ "๋‹ค์ง์ข… ๊ฐ„์˜ ์œ ๊ธฐ์ ์ธ ํ˜‘๋ ฅ์„ ํ†ตํ•ด ์žฅ๊ธฐ์š”์–‘๊ธฐ๊ด€ ํ‰๊ฐ€ ๊ธฐ์ค€์— ์ ํ•ฉํ•œ ์•ˆ์ „ ๊ด€๋ฆฌ ์ฒด๊ณ„๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ ์ž ํ•จ."
508
+ )
509
+ ws.cell(row=r_num, column=3, value=purpose_text)
510
+ style_range(ws, f"A{r_num}:B{r_num+1}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
511
+ style_range(ws, f"C{r_num}:I{r_num+1}", font=value_font, alignment=align_left_wrap, border=thin_border)
512
+ r_num += 2
513
+
514
+ ws.row_dimensions[r_num].height = 24
515
+ ws.row_dimensions[r_num+1].height = 24
516
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num+1, end_column=2)
517
+ ws.cell(row=r_num, column=1, value="๋Œ€ํ”ผ ๊ฒฝ๋กœ")
518
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num+1, end_column=9)
519
+
520
+ route_text = (
521
+ "ํ”ผ๋‚œ๊ณ„๋‹จ ๋ฐ ์ง€์ • ๋Œ€ํ”ผ๊ฒฝ๋กœ ์‚ฌ์ „ ํ™•์ธ: ์‹ค๋‚ด ๋น„์ƒ๊ตฌ ํ‘œ์‹œ๋“ฑ ๋ฐ ๋Œ€ํ”ผ ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ ์ง€์ •๋œ ์™ธ๋ถ€ ์ง‘๊ฒฐ์ง€๊นŒ์ง€์˜ ์ด๋™ ๋™์„ ์„ ํŒŒ์•…ํ•˜๊ณ  ์žฅ์• ๋ฌผ์„ ์™„์ „ํžˆ ์ œ๊ฑฐํ•จ.\n"
522
+ f"(๋Œ€ํ”ผ๊ฒฝ๋กœ ํ™•์ธ ์ƒํƒœ: {info['route_checked']})"
523
+ )
524
+ ws.cell(row=r_num, column=3, value=route_text)
525
+ style_range(ws, f"A{r_num}:B{r_num+1}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
526
+ style_range(ws, f"C{r_num}:I{r_num+1}", font=value_font, alignment=align_left_wrap, border=thin_border)
527
+ r_num += 2
528
+
529
+ write_spacer(ws, r_num)
530
+ r_num += 1
531
+
532
+ write_section_header(ws, r_num, "3. ๋‹ค์ง์ข…๋ณ„ ์—ญํ•  ๋ถ„๋‹ด ๊ณ„ํš")
533
+ r_num += 1
534
+
535
+ ws.row_dimensions[r_num].height = 24
536
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
537
+ ws.cell(row=r_num, column=1, value="์ง์ข…")
538
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=9)
539
+ ws.cell(row=r_num, column=3, value="์—ญํ•  ๋ฐ ์ฃผ์š” ์—…๋ฌด ๋ถ„๋‹ด ๋‚ด์šฉ")
540
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
541
+ style_range(ws, f"C{r_num}:I{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
542
+ r_num += 1
543
+
544
+ roles = [
545
+ ("์‹œ์„ค์žฅ", "ํ›ˆ๋ จ ์ด๊ด„, ์ง€ํœ˜, ํ‰๊ฐ€ ๋Œ€์‘, ์œ ๊ด€๊ธฐ๊ด€ ์—ฐ๋ฝ์ฒด๊ณ„ ํ™•์ธ"),
546
+ ("์‚ฌํšŒ๋ณต์ง€์‚ฌ", "์ˆ˜๊ธ‰์ž ๋ช…๋‹จ ํ™•์ธ, ๋Œ€ํ”ผ์ทจ์•ฝ์ž ๋ถ„๋ฅ˜, ๋ณดํ˜ธ์ž ์—ฐ๋ฝ, ํ›ˆ๋ จ๊ธฐ๋ก ์ž‘์„ฑ"),
547
+ ("์š”์–‘๋ณดํ˜ธ์‚ฌ", "์ˆ˜๊ธ‰์ž ๋Œ€ํ”ผ ๋ณด์กฐ, ์ด๋™ ์ง€์›, ๋‚™์ƒ์œ„ํ—˜์ž ๋ณดํ˜ธ, ์‹ค์ œ ํ˜„์žฅ ๋Œ€์‘"),
548
+ ("๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ", "์‘๊ธ‰์ƒํ™ฉ ํ™•์ธ, ํ™œ๋ ฅ์ง•ํ›„ ํ™•์ธ, ํˆฌ์•ฝยท๊ฑด๊ฐ•์ƒํƒœ ํ™•์ธ, ๋ถ€์ƒ์ž ์‘๊ธ‰์กฐ์น˜"),
549
+ ("๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ", "๋ณดํ–‰๋ถˆ์•ˆ์ • ์ˆ˜๊ธ‰์ž ์ด๋™์ง€์›, ํœ ์ฒด์–ดยท์›Œ์ปค ์‚ฌ์šฉ ๋Œ€์ƒ์ž ๋Œ€ํ”ผ ์ง€์›, ๋‚™์ƒ์˜ˆ๋ฐฉ ํ™•์ธ")
550
+ ]
551
+ for role, desc in roles:
552
+ ws.row_dimensions[r_num].height = 24
553
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
554
+ ws.cell(row=r_num, column=1, value=role)
555
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=9)
556
+ ws.cell(row=r_num, column=3, value=desc)
557
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
558
+ style_range(ws, f"C{r_num}:I{r_num}", font=value_font, alignment=align_left, border=thin_border)
559
+ r_num += 1
560
+
561
+ write_spacer(ws, r_num)
562
+ r_num += 1
563
+
564
+ write_section_header(ws, r_num, "4. ๋น„์ƒ ์—ฐ๋ฝ ๋ฐ ์œ ๊ด€๊ธฐ๊ด€ ํ˜‘์กฐ ์ฒด๊ณ„")
565
+ r_num += 1
566
+
567
+ ws.row_dimensions[r_num].height = 24
568
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
569
+ ws.cell(row=r_num, column=1, value="์œ ๊ด€๊ธฐ๊ด€")
570
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=4)
571
+ ws.cell(row=r_num, column=3, value="๋น„์ƒ์—ฐ๋ฝ์ฒ˜")
572
+ ws.merge_cells(start_row=r_num, start_column=5, end_row=r_num, end_column=9)
573
+ ws.cell(row=r_num, column=5, value="์ฃผ์š” ํ˜‘์กฐ ๋ฐ ๋Œ€์‘ ๋‚ด์šฉ")
574
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
575
+ style_range(ws, f"C{r_num}:D{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
576
+ style_range(ws, f"E{r_num}:I{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
577
+ r_num += 1
578
+
579
+ contacts = [
580
+ ("์†Œ๋ฐฉ์„œ (119)", "119 / ๊ด€ํ• ์†Œ๋ฐฉ์„œ", f"ํ™”์žฌ ๋ฐœ์ƒ ์‹ ๊ณ , ์ธ๋ช… ๊ตฌ์กฐ ๋ฐ ํ™”์žฌ ์ง„์•• ์ง€์› (์†Œํ™”๊ธฐ ์‹œ์—ฐ: {info['fire_ext_demo']})"),
581
+ ("๊ฒฝ์ฐฐ์„œ (112)", "112 / ๊ด€ํ• ์ง€๊ตฌ๋Œ€", "ํ›ˆ๋ จ ์‹œ ์ฃผ๋ณ€ ๊ตํ†ต ํ†ต์ œ ๋ฐ ์•ˆ์ „ ์œ ์ง€ ํ˜‘์กฐ"),
582
+ ("ํ˜‘๋ ฅ ์˜๋ฃŒ๊ธฐ๊ด€", "์ธ๊ทผ ์ข…ํ•ฉ๋ณ‘์›", f"์‘๊ธ‰ ํ™˜์ž ๋ฐœ์ƒ ์‹œ ๊ธด๊ธ‰ ์ด์†ก ๋ฐ ๊ธด๊ธ‰ ์˜๋ฃŒ ์ง€์›์ฒด๊ณ„ ๊ฐ€๋™ (๋ชจ์˜๋Œ€์‘: {info['emergency_mock']})")
583
+ ]
584
+ for org, phone, task in contacts:
585
+ ws.row_dimensions[r_num].height = 24
586
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
587
+ ws.cell(row=r_num, column=1, value=org)
588
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=4)
589
+ ws.cell(row=r_num, column=3, value=phone)
590
+ ws.merge_cells(start_row=r_num, start_column=5, end_row=r_num, end_column=9)
591
+ ws.cell(row=r_num, column=5, value=task)
592
+
593
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
594
+ style_range(ws, f"C{r_num}:D{r_num}", font=value_font, alignment=align_center, border=thin_border)
595
+ style_range(ws, f"E{r_num}:I{r_num}", font=value_font, alignment=align_left, border=thin_border)
596
+ r_num += 1
597
+
598
+ return r_num
599
+
600
+ def write_report_participants(ws, r_num, info):
601
+ ws.row_dimensions[r_num].height = 24
602
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
603
+ ws.cell(row=r_num, column=1, value="์ด ์ฐธ์—ฌ์ธ์›")
604
+ ws.cell(row=r_num, column=3, value=f"{info['total_participants']} ๋ช…")
605
+
606
+ ws.merge_cells(start_row=r_num, start_column=4, end_row=r_num, end_column=5)
607
+ ws.cell(row=r_num, column=4, value="์ข…์‚ฌ์ž ์ฐธ์—ฌ์ž ์ˆ˜")
608
+ ws.cell(row=r_num, column=6, value=f"{info['staff_participants']} ๋ช…")
609
+
610
+ ws.merge_cells(start_row=r_num, start_column=7, end_row=r_num, end_column=8)
611
+ ws.cell(row=r_num, column=7, value="์ˆ˜๊ธ‰์ž ์ฐธ์—ฌ์ž ์ˆ˜")
612
+ ws.cell(row=r_num, column=9, value=f"{info['recipient_participants']} ๋ช…")
613
+
614
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
615
+ ws.cell(row=r_num, column=3).font = value_font
616
+ ws.cell(row=r_num, column=3).alignment = align_center
617
+ ws.cell(row=r_num, column=3).border = thin_border
618
+
619
+ style_range(ws, f"D{r_num}:E{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
620
+ ws.cell(row=r_num, column=6).font = value_font
621
+ ws.cell(row=r_num, column=6).alignment = align_center
622
+ ws.cell(row=r_num, column=6).border = thin_border
623
+
624
+ style_range(ws, f"G{r_num}:H{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
625
+ ws.cell(row=r_num, column=9).font = value_font
626
+ ws.cell(row=r_num, column=9).alignment = align_center
627
+ ws.cell(row=r_num, column=9).border = thin_border
628
+
629
+ r_num += 1
630
+
631
+ ws.row_dimensions[r_num].height = 24
632
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
633
+ ws.cell(row=r_num, column=1, value="๋Œ€ํ”ผ์™„๋ฃŒ ์‹œ๊ฐ„")
634
+ ws.cell(row=r_num, column=3, value=f"{info['evac_time']}")
635
+
636
+ ws.merge_cells(start_row=r_num, start_column=4, end_row=r_num, end_column=5)
637
+ ws.cell(row=r_num, column=4, value="๋Œ€ํ”ผ์ทจ์•ฝ์ž ์ˆ˜")
638
+ ws.cell(row=r_num, column=6, value=f"{info['vulnerable_count']} ๋ช…")
639
+
640
+ ws.merge_cells(start_row=r_num, start_column=7, end_row=r_num, end_column=8)
641
+ ws.cell(row=r_num, column=7, value="ํœ ์ฒด์–ด ์‚ฌ์šฉ ๋Œ€์ƒ์ž")
642
+ ws.cell(row=r_num, column=9, value=f"{info['wheelchair_count']} ๋ช…")
643
+
644
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
645
+ ws.cell(row=r_num, column=3).font = value_font
646
+ ws.cell(row=r_num, column=3).alignment = align_center
647
+ ws.cell(row=r_num, column=3).border = thin_border
648
+
649
+ style_range(ws, f"D{r_num}:E{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
650
+ ws.cell(row=r_num, column=6).font = value_font
651
+ ws.cell(row=r_num, column=6).alignment = align_center
652
+ ws.cell(row=r_num, column=6).border = thin_border
653
+
654
+ style_range(ws, f"G{r_num}:H{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
655
+ ws.cell(row=r_num, column=9).font = value_font
656
+ ws.cell(row=r_num, column=9).alignment = align_center
657
+ ws.cell(row=r_num, column=9).border = thin_border
658
+
659
+ r_num += 1
660
+
661
+ ws.row_dimensions[r_num].height = 24
662
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
663
+ ws.cell(row=r_num, column=1, value="๋ณดํ–‰๋ณด์กฐ ํ•„์š”์ž")
664
+ ws.cell(row=r_num, column=3, value=f"{info['walk_aid_count']} ๋ช…")
665
+
666
+ ws.merge_cells(start_row=r_num, start_column=4, end_row=r_num, end_column=5)
667
+ ws.cell(row=r_num, column=4, value="์‘๊ธ‰์ƒํ™ฉ ๋ชจ์˜๋Œ€์‘")
668
+ ws.cell(row=r_num, column=6, value=f"{info['emergency_mock']}")
669
+
670
+ ws.merge_cells(start_row=r_num, start_column=7, end_row=r_num, end_column=8)
671
+ ws.cell(row=r_num, column=7, value="์†Œํ™”๊ธฐ ์‚ฌ์šฉ ์‹œ์—ฐ")
672
+ ws.cell(row=r_num, column=9, value=f"{info['fire_ext_demo']}")
673
+
674
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
675
+ ws.cell(row=r_num, column=3).font = value_font
676
+ ws.cell(row=r_num, column=3).alignment = align_center
677
+ ws.cell(row=r_num, column=3).border = thin_border
678
+
679
+ style_range(ws, f"D{r_num}:E{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
680
+ ws.cell(row=r_num, column=6).font = value_font
681
+ ws.cell(row=r_num, column=6).alignment = align_center
682
+ ws.cell(row=r_num, column=6).border = thin_border
683
+
684
+ style_range(ws, f"G{r_num}:H{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
685
+ ws.cell(row=r_num, column=9).font = value_font
686
+ ws.cell(row=r_num, column=9).alignment = align_center
687
+ ws.cell(row=r_num, column=9).border = thin_border
688
+
689
+ r_num += 1
690
+
691
+ ws.row_dimensions[r_num].height = 24
692
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
693
+ ws.cell(row=r_num, column=1, value="๋Œ€ํ”ผ๊ฒฝ๋กœ ํ™•์ธ")
694
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=4)
695
+ ws.cell(row=r_num, column=3, value=f"{info['route_checked']}")
696
+
697
+ ws.merge_cells(start_row=r_num, start_column=5, end_row=r_num, end_column=6)
698
+ ws.cell(row=r_num, column=5, value="๋น„์ƒ์—ฐ๋ฝ๋ง ํ™•์ธ")
699
+ ws.merge_cells(start_row=r_num, start_column=7, end_row=r_num, end_column=9)
700
+ ws.cell(row=r_num, column=7, value=f"{info['contact_checked']}")
701
+
702
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
703
+ style_range(ws, f"C{r_num}:D{r_num}", font=value_font, alignment=align_center, border=thin_border)
704
+ style_range(ws, f"E{r_num}:F{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
705
+ style_range(ws, f"G{r_num}:I{r_num}", font=value_font, alignment=align_center, border=thin_border)
706
+
707
+ return r_num
708
+
709
+ # ---------------------------------------------------------
710
+ # Audit Style Meeting Opinion & 2nd Result Writers
711
+ # ---------------------------------------------------------
712
+ def write_role_meeting_opinion(ws, r_num, role, detail1, detail2, role_desc):
713
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num+2, end_column=2)
714
+ ws.cell(row=r_num, column=1, value=role)
715
+
716
+ # Row 1 (Detail 1)
717
+ ws.row_dimensions[r_num].height = 28
718
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=9)
719
+ ws.cell(row=r_num, column=3, value=detail1)
720
+
721
+ # Row 2 (Detail 2)
722
+ ws.row_dimensions[r_num+1].height = 28
723
+ ws.merge_cells(start_row=r_num+1, start_column=3, end_row=r_num+1, end_column=9)
724
+ ws.cell(row=r_num+1, column=3, value=detail2)
725
+
726
+ # Row 3 (Role Desc)
727
+ ws.row_dimensions[r_num+2].height = 28
728
+ ws.merge_cells(start_row=r_num+2, start_column=3, end_row=r_num+2, end_column=9)
729
+ ws.cell(row=r_num+2, column=3, value=role_desc)
730
+
731
+ style_range(ws, f"A{r_num}:B{r_num+2}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
732
+ style_range(ws, f"C{r_num}:I{r_num}", font=value_font, alignment=align_left_wrap, border=thin_border)
733
+ style_range(ws, f"C{r_num+1}:I{r_num+1}", font=value_font, alignment=align_left_wrap, border=thin_border)
734
+ style_range(ws, f"C{r_num+2}:I{r_num+2}", font=value_font, alignment=align_left_wrap, border=thin_border)
735
+
736
+ return r_num + 2
737
+
738
+ def write_secondary_result_row(ws, r_num, label, content):
739
+ ws.row_dimensions[r_num].height = 28
740
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
741
+ ws.cell(row=r_num, column=1, value=label)
742
+
743
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=9)
744
+ ws.cell(row=r_num, column=3, value=content)
745
+
746
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
747
+ style_range(ws, f"C{r_num}:I{r_num}", font=value_font, alignment=align_left_wrap, border=thin_border)
748
+
749
+ return r_num
750
+
751
+ def write_guardian_feedback(ws, r_num, info):
752
+ # Row 1: meta (Date, Reflected)
753
+ ws.row_dimensions[r_num].height = 24
754
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
755
+ ws.cell(row=r_num, column=1, value="ํ†ตํ™”์ผ์ž")
756
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=4)
757
+ ws.cell(row=r_num, column=3, value=f"{info['guardian_call_date']}")
758
+
759
+ ws.merge_cells(start_row=r_num, start_column=5, end_row=r_num, end_column=6)
760
+ ws.cell(row=r_num, column=5, value="๋ฐ˜์˜ ์—ฌ๋ถ€")
761
+ ws.merge_cells(start_row=r_num, start_column=7, end_row=r_num, end_column=9)
762
+ ws.cell(row=r_num, column=7, value=f"{info['guardian_reflected']}")
763
+
764
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
765
+ style_range(ws, f"C{r_num}:D{r_num}", font=value_font, alignment=align_center, border=thin_border)
766
+ style_range(ws, f"E{r_num}:F{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
767
+ style_range(ws, f"G{r_num}:I{r_num}", font=value_font, alignment=align_center, border=thin_border)
768
+
769
+ r_num += 1
770
+
771
+ # Row 2 & 3: Guardian Opinion
772
+ ws.row_dimensions[r_num].height = 28
773
+ ws.row_dimensions[r_num+1].height = 28
774
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num+1, end_column=2)
775
+ ws.cell(row=r_num, column=1, value="๋ณดํ˜ธ์ž ์˜๊ฒฌ")
776
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num+1, end_column=9)
777
+ ws.cell(row=r_num, column=3, value=f"{info['guardian_opinion']}")
778
+
779
+ style_range(ws, f"A{r_num}:B{r_num+1}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
780
+ style_range(ws, f"C{r_num}:I{r_num+1}", font=value_font, alignment=align_left_wrap, border=thin_border)
781
+
782
+ r_num += 2
783
+
784
+ # Row 4 & 5: Facility Explanation
785
+ ws.row_dimensions[r_num].height = 28
786
+ ws.row_dimensions[r_num+1].height = 28
787
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num+1, end_column=2)
788
+ ws.cell(row=r_num, column=1, value="๊ธฐ๊ด€ ์„ค๋ช…๋‚ด์šฉ")
789
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num+1, end_column=9)
790
+ ws.cell(row=r_num, column=3, value=f"{info['guardian_response']}")
791
+
792
+ style_range(ws, f"A{r_num}:B{r_num+1}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
793
+ style_range(ws, f"C{r_num}:I{r_num+1}", font=value_font, alignment=align_left_wrap, border=thin_border)
794
+
795
+ return r_num + 1
796
+
797
+ def write_photo_section(ws, r_num):
798
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num+5, end_column=9)
799
+ for i in range(6):
800
+ ws.row_dimensions[r_num+i].height = 25
801
+
802
+ photo_cell = ws.cell(row=r_num, column=1)
803
+ photo_cell.value = (
804
+ "[ํ›ˆ๋ จ ์‚ฌ์ง„ ์ฒจ๋ถ€๋ž€]\n\n"
805
+ "โ€ป ์—ฌ๊ธฐ์— ์‹ค์ œ ๋Œ€ํ”ผํ›ˆ๋ จ, ์†Œํ™”๊ธฐ ์‹œ์—ฐ, ์‘๊ธ‰๋ชจ์˜๋Œ€์‘ ๋“ฑ ํ›ˆ๋ จ ์‚ฌ์ง„์„ ๋ถ€์ฐฉํ•˜์‹ญ์‹œ์˜ค.\n"
806
+ "(์žฅ๊ธฐ์š”์–‘๊ธฐ๊ด€ ํ‰๊ฐ€ ๋Œ€์‘์„ ์œ„ํ•ด 2์žฅ ์ด์ƒ์˜ ์‚ฌ์ง„ ๋ถ€์ฐฉ์ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.)"
807
+ )
808
+ style_range(ws, f"A{r_num}:I{r_num+5}",
809
+ font=Font(name="๋ง‘์€ ๊ณ ๋”•", size=9.5, italic=True, color="667085"),
810
+ alignment=Alignment(vertical="center", horizontal="center", wrap_text=True),
811
+ border=thin_border)
812
+
813
+ return r_num + 5
814
+
815
+ # ---------------------------------------------------------
816
+ # Excel Creator: Write Checklist Sheet
817
+ # ---------------------------------------------------------
818
+ def write_checklist_tab(ws, info):
819
+ col_widths = {
820
+ 'A': 10, 'B': 10, 'C': 12, 'D': 12, 'E': 12, 'F': 12, 'G': 12, 'H': 14, 'I': 14
821
+ }
822
+ for col, width in col_widths.items():
823
+ ws.column_dimensions[col].width = width
824
+
825
+ setup_page_print(ws)
826
+
827
+ # Title
828
+ ws.row_dimensions[1].height = 22
829
+ ws.row_dimensions[2].height = 22
830
+ ws.merge_cells("A1:I2")
831
+ title_cell = ws.cell(row=1, column=1)
832
+ title_cell.value = "์žฅ๊ธฐ์š”์–‘๊ธฐ๊ด€ ํ‰๊ฐ€ ๋Œ€์‘ - ํ›ˆ๋ จ ๋ฐ ๊ต์œก ๋ˆ„๋ฝ ์ฒดํฌ๋ฆฌ์ŠคํŠธ"
833
+ style_range(ws, "A1:I2",
834
+ font=Font(name="๋ง‘์€ ๊ณ ๋”•", size=14, bold=True, color="111827"),
835
+ alignment=align_center,
836
+ border=thin_border)
837
+
838
+ # Info Banner
839
+ ws.row_dimensions[4].height = 30
840
+ ws.merge_cells("A4:I4")
841
+ banner_cell = ws.cell(row=4, column=1)
842
+ banner_cell.value = "โ€ป ๋ณธ ์ฒดํฌ๋ฆฌ์ŠคํŠธ๋Š” ๊ตญ๋ฏผ๊ฑด๊ฐ•๋ณดํ—˜๊ณต๋‹จ ์žฅ๊ธฐ์š”์–‘๊ธฐ๊ด€ ํ‰๊ฐ€ ๊ณ ์‹œ ๊ธฐ์ค€ ๋ฐ ๋งค๋‰ด์–ผ์— ์˜๊ฑฐํ•˜์—ฌ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ํ•ญ๋ชฉ์˜ ๋ฐ˜์˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค."
843
+ style_range(ws, "A4:I4",
844
+ fill=PatternFill(start_color="F9FAFB", end_color="F9FAFB", fill_type="solid"),
845
+ font=Font(name="๋ง‘์€ ๊ณ ๋”•", size=9, italic=True, color="475467"),
846
+ alignment=align_center,
847
+ border=thin_border)
848
+
849
+ # Headers
850
+ ws.row_dimensions[6].height = 26
851
+ ws.merge_cells("A6:B6")
852
+ ws.cell(row=6, column=1, value="ํ‰๊ฐ€ ํ•ญ๋ชฉ")
853
+ ws.merge_cells("C6:E6")
854
+ ws.cell(row=6, column=3, value="์„ธ๋ถ€ ํ™•์ธ์‚ฌํ•ญ ๋ฐ ๊ธฐ์ค€")
855
+ ws.merge_cells("F6:G6")
856
+ ws.cell(row=6, column=6, value="๋ฐ˜์˜ ์ƒํƒœ")
857
+ ws.merge_cells("H6:I6")
858
+ ws.cell(row=6, column=8, value="ํ‰๊ฐ€ ๊ธฐ์ค€ ์ถฉ์กฑ ์—ฌ๋ถ€")
859
+
860
+ style_range(ws, "A6:I6", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
861
+
862
+ checklist_items = [
863
+ ("ํ›ˆ๋ จ๊ณ„ํš์„œ ์ž‘์„ฑ ์—ฌ๋ถ€", "ํ›ˆ๋ จ์„ ์‹ค์‹œํ•˜๊ธฐ ์ „ ๊ตฌ์ฒด์ ์ธ ๊ณ„ํš์„œ๊ฐ€ ์ˆ˜๋ฆฝ๋˜์–ด ์žˆ๋Š”๊ฐ€?", "์ž‘์„ฑ ์™„๋ฃŒ", "์ถฉ์กฑ (Pass)"),
864
+ ("๊ฒฐ๊ณผ๋ณด๊ณ ์„œ ์ž‘์„ฑ ์—ฌ๋ถ€", "ํ›ˆ๋ จ ์‹ค์‹œ ํ›„ ๊ฒฐ๊ณผ๋ณด๊ณ ์„œ๊ฐ€ ์ž‘์„ฑ ๋ฐ ๋ณด๊ด€๋˜์–ด ์žˆ๋Š”๊ฐ€?", "์ž‘์„ฑ ์™„๋ฃŒ", "์ถฉ์กฑ (Pass)"),
865
+ ("ํ›ˆ๋ จ์ผ์ž ๊ธฐ๋ก", "๊ณ„ํš์„œ ๋ฐ ๊ฒฐ๊ณผ๋ณด๊ณ ์„œ์— ์‹ค์ œ ํ›ˆ๋ จ์ผ์ž๊ฐ€ ์ •ํ™•ํžˆ ๊ธฐ๋ก๋˜์—ˆ๋Š”๊ฐ€?", f"{info['training_date']} ๊ธฐ๋ก๋จ", "์ถฉ์กฑ (Pass)"),
866
+ ("ํ›ˆ๋ จ์‹œ๊ฐ„ ๊ธฐ๋ก", "ํ›ˆ๋ จ ์‹œ์ž‘ ๋ฐ ์ข…๋ฃŒ ์‹œ๊ฐ„(์˜ˆ: 1์‹œ๊ฐ„ ์ด์ƒ)์ด ์ƒ์„ธํžˆ ๊ธฐ๋ก๋˜์—ˆ๋Š”๊ฐ€?", f"{info['training_time']} ๊ธฐ๋ก๋จ", "์ถฉ์กฑ (Pass)"),
867
+ ("ํ›ˆ๋ จ์žฅ์†Œ ๊ธฐ๋ก", "ํ›ˆ๋ จ์ด ์‹ค์‹œ๋œ ๊ตฌ์ฒด์ ์ธ ์žฅ์†Œ๊ฐ€ ๋ช…์‹œ๋˜์–ด ์žˆ๋Š”๊ฐ€?", f"{info['training_location']} ๊ธฐ๋ก๋จ", "์ถฉ์กฑ (Pass)"),
868
+ ("์ฐธ์—ฌ์ž ๋ช…๋‹จ", "ํ›ˆ๋ จ์— ์ฐธ์—ฌํ•œ ์ˆ˜๊ธ‰์ž์™€ ์ข…์‚ฌ์ž์˜ ๋ช…๋‹จ์ด ์ฒจ๋ถ€ ๋˜๋Š” ๊ธฐ๋ก๋˜์—ˆ๋Š”๊ฐ€?", f"์ด {info['total_participants']}๋ช… ๋ช…๋‹จ ํ™•์ธ", "์ถฉ์กฑ (Pass)"),
869
+ ("์ง์ข…๋ณ„ ์—ญํ• ๋ถ„๋‹ด", "์‹œ์„ค์žฅ, ๋ณต์ง€์‚ฌ, ์š”์–‘๋ณดํ˜ธ์‚ฌ ๋“ฑ ๋‹ค์ง์ข… ์—ญํ•  ๋ถ„๋‹ด์ด ๊ณ„ํš์„œ์— ์ˆ˜๋ฆฝ๋˜์—ˆ๋Š”๊ฐ€?", "5๊ฐœ ์ง์ข… ์—ญํ•  ์ˆ˜๋ฆฝ", "์ถฉ์กฑ (Pass)"),
870
+ ("๋Œ€ํ”ผ์ทจ์•ฝ์ž ์ง€์›๊ณ„ํš", "ํœ ์ฒด์–ด, ๋ณดํ–‰๋ณด์กฐ ํ•„์š” ๋“ฑ ๋Œ€ํ”ผ์ทจ์•ฝ์ž ๊ฐœ๋ณ„ ์ด๋™์ง€์› ๊ณ„ํš์ด ์ˆ˜๋ฆฝ๋˜์—ˆ๋Š”๊ฐ€?", f"๋Œ€ํ”ผ์ทจ์•ฝ์ž {info['vulnerable_count']}๋ช… ์ง€์› ๊ณ„ํš ๋ฐ˜์˜", "์ถฉ์กฑ (Pass)"),
871
+ ("๋น„์ƒ์—ฐ๋ฝ์ฒด๊ณ„", "์†Œ๋ฐฉ์„œ, ๊ฒฝ์ฐฐ์„œ, ํ˜‘๋ ฅ๋ณ‘์› ๋“ฑ ์œ ๊ด€๊ธฐ๊ด€ ๋น„์ƒ์—ฐ๋ฝ์ฒด๊ณ„๊ฐ€ ๊ตฌ์„ฑ๋˜์—ˆ๋Š”๊ฐ€?", f"{info['contact_checked']}", "์ถฉ์กฑ (Pass)"),
872
+ ("๋Œ€ํ”ผ๊ฒฝ๋กœ", "ํ”ผ๋‚œ๋™์„  ๋ฐ ๋น„์ƒ ๋Œ€ํ”ผ๊ฒฝ๋กœ๊ฐ€ ์ง€์ •๋˜๊ณ  ์‚ฌ์ „์— ํ™•์ธ๋˜์—ˆ๋Š”๊ฐ€?", f"{info['route_checked']}", "์ถฉ์กฑ (Pass)"),
873
+ ("์†Œํ™”๊ธฐ ์‚ฌ์šฉ ๋˜๋Š” ํ™”์žฌ๋Œ€์‘", "ํ›ˆ๋ จ ๋‚ด์šฉ ์ค‘ ์†Œํ™”์„ค๋น„ ์‹œ์—ฐ ๋˜๋Š” ํ™”์žฌ ๋Œ€ํ”ผ ์‹ค๋ฌด๊ฐ€ ํฌํ•จ๋˜์—ˆ๋Š”๊ฐ€?", f"{info['fire_ext_demo']}", "์ถฉ์กฑ (Pass)"),
874
+ ("์‹ค์ œ ๋Œ€ํ”ผํ›ˆ๋ จ ์‹ค์‹œ ์—ฌ๋ถ€", "๋ชจ์˜ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ „์›์ด ์‹ค์ œ๋กœ ์•ผ์™ธ ๋Œ€ํ”ผ ๋™์„ ์œผ๋กœ ๋Œ€ํ”ผ๋ฅผ ์‹ค์‹œํ–ˆ๋Š”๊ฐ€?", "์‹ค์ œ ๋Œ€ํ”ผํ›ˆ๋ จ ์‹ค์‹œ", "์ถฉ์กฑ (Pass)"),
875
+ ("์‚ฌ์ง„ ์ฒจ๋ถ€๋ž€", "ํ›ˆ๋ จ ์žฅ๋ฉด์„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ์ง„์ฒฉ ๋˜๋Š” ๋ถ€์ฐฉ ๊ณต๊ฐ„์ด ๋งˆ๋ จ๋˜์—ˆ๋Š”๊ฐ€?", "์‚ฌ์ง„ ์ฒจ๋ถ€ ๊ณต๊ฐ„ ํ™•๋ณด", "์ถฉ์กฑ (Pass)"),
876
+ ("๊ฐœ์„ ์กฐ์น˜", "ํ›ˆ๋ จ ๊ณผ์ •์—์„œ ๋…ธ์ถœ๋œ ๋ฌธ์ œ์ ์— ๋Œ€ํ•ด ๋ช…ํ™•ํ•œ ๊ฐœ์„ ์กฐ์น˜๊ฐ€ ์ˆ˜๋ฆฝ๋˜์—ˆ๋Š”๊ฐ€?", "๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ๊ฐœ์„ ์กฐ์น˜ ์ˆ˜๋ฆฝ", "์ถฉ์กฑ (Pass)"),
877
+ ("๋‹ค์Œ ํ›ˆ๋ จ ๋ฐ˜์˜์‚ฌํ•ญ", "๊ธˆ๋ฒˆ ํ›ˆ๋ จ ํ‰๊ฐ€ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค์Œ๋ฒˆ ํ›ˆ๋ จ ๊ณ„ํš์— ๊ตฌ์ฒด์ ์œผ๋กœ ๋ฐ˜์˜๋˜์—ˆ๋Š”๊ฐ€?", "๋‹ค์Œ ํ›ˆ๋ จ ๋ฐ˜์˜์‚ฌํ•ญ ์ˆ˜๋ฆฝ", "์ถฉ์กฑ (Pass)"),
878
+ ("๋ณดํ˜ธ์ž ์ „ํ™” ์˜๊ฒฌ ๋ฐ˜์˜๋ž€", "ํ›ˆ๋ จ ๊ฒฐ๊ณผ์— ๋Œ€ํ•ด ๋ณดํ˜ธ์ž์˜ ์œ ์„  ํ”ผ๋“œ๋ฐฑ์„ ๊ธฐ๋กํ•˜๊ณ  ์„œ๋น„์Šค๊ณ„ํš์— ๋ฐ˜์˜ํ•˜์˜€๋Š”๊ฐ€?", "๋ณดํ˜ธ์ž ์˜๊ฒฌ ์ˆ˜๋ ด ์™„๋ฃŒ", "์ถฉ์กฑ (Pass)")
879
+ ]
880
+
881
+ r_num = 7
882
+ for item, desc, status, compliance in checklist_items:
883
+ ws.row_dimensions[r_num].height = 24
884
+ ws.merge_cells(start_row=r_num, start_column=1, end_row=r_num, end_column=2)
885
+ ws.cell(row=r_num, column=1, value=item)
886
+ ws.merge_cells(start_row=r_num, start_column=3, end_row=r_num, end_column=5)
887
+ ws.cell(row=r_num, column=3, value=desc)
888
+ ws.merge_cells(start_row=r_num, start_column=6, end_row=r_num, end_column=7)
889
+ ws.cell(row=r_num, column=6, value=status)
890
+ ws.merge_cells(start_row=r_num, start_column=8, end_row=r_num, end_column=9)
891
+ ws.cell(row=r_num, column=8, value=compliance)
892
+
893
+ style_range(ws, f"A{r_num}:B{r_num}", fill=header_fill, font=label_font, alignment=align_center, border=thin_border)
894
+ style_range(ws, f"C{r_num}:E{r_num}", font=value_font, alignment=align_left, border=thin_border)
895
+ style_range(ws, f"F{r_num}:G{r_num}", font=value_font, alignment=align_center, border=thin_border)
896
+
897
+ pass_fill = PatternFill(start_color="E8F8F5", end_color="E8F8F5", fill_type="solid")
898
+ pass_font = Font(name="๋ง‘์€ ๊ณ ๋”•", size=9.5, bold=True, color="0E6251")
899
+ style_range(ws, f"H{r_num}:I{r_num}", fill=pass_fill, font=pass_font, alignment=align_center, border=thin_border)
900
+
901
+ r_num += 1
902
+
903
+ # ---------------------------------------------------------
904
+ # Main Excel Workbook Generator
905
+ # ---------------------------------------------------------
906
+ def create_excel(info, training_type):
907
+ data = compile_document_data(info, training_type)
908
+ wb = openpyxl.Workbook()
909
+
910
+ # ---------------------------------------------------------
911
+ # TAB 1: ํ›ˆ๋ จ ๊ณ„ํš์„œ (Plan)
912
+ # ---------------------------------------------------------
913
+ ws_plan = wb.active
914
+ ws_plan.title = "ํ›ˆ๋ จ ๊ณ„ํš์„œ"
915
+
916
+ col_widths = {
917
+ 'A': 10, 'B': 10, 'C': 12, 'D': 12, 'E': 12, 'F': 12, 'G': 12, 'H': 14, 'I': 14
918
+ }
919
+ for col, width in col_widths.items():
920
+ ws_plan.column_dimensions[col].width = width
921
+
922
+ setup_page_print(ws_plan)
923
+ write_title_and_approval(ws_plan, f"{training_type} ๊ณ„ํš์„œ", data)
924
+ write_spacer(ws_plan, 3)
925
+
926
+ write_general_info_row(ws_plan, 4, "๊ธฐ๊ด€๋ช…", data['facility_name'], "ํ›ˆ๋ จ์ผ์ž", data['training_date'])
927
+ write_general_info_row(ws_plan, 5, "ํ›ˆ๋ จ์‹œ๊ฐ„", data['training_time'], "ํ›ˆ๋ จ์žฅ์†Œ", data['training_location'])
928
+ write_general_info_row(ws_plan, 6, "ํ›ˆ๋ จ์œ ํ˜•", f"{training_type} (๋Œ€ํ”ผ์‹ค๋ฌด ํฌํ•จ)", "ํ›ˆ๋ จ์ฃผ๊ด€์ž", data['host'])
929
+ write_spacer(ws_plan, 7)
930
+
931
+ write_section_header(ws_plan, 8, "1. ํ›ˆ๋ จ ์ฐธ์—ฌ์ž ๊ณ„ํš ํ˜„ํ™ฉ")
932
+ write_plan_participants(ws_plan, 9, data)
933
+ write_spacer(ws_plan, 11)
934
+
935
+ write_plan_details(ws_plan, 12, data)
936
+
937
+ # ---------------------------------------------------------
938
+ # TAB 2: ํ›ˆ๋ จ ๊ฒฐ๊ณผ๋ณด๊ณ ์„œ (Result Report)
939
+ # ---------------------------------------------------------
940
+ ws_report = wb.create_sheet(title="ํ›ˆ๋ จ ๊ฒฐ๊ณผ๋ณด๊ณ ์„œ")
941
+ for col, width in col_widths.items():
942
+ ws_report.column_dimensions[col].width = width
943
+
944
+ setup_page_print(ws_report)
945
+ write_title_and_approval(ws_report, f"{training_type} ๊ฒฐ๊ณผ๋ณด๊ณ ์„œ & ๊ฐ์‚ฌ ์˜๊ฒฌ์„œ", data)
946
+ write_spacer(ws_report, 3)
947
+
948
+ write_general_info_row(ws_report, 4, "๊ธฐ๊ด€๋ช…", data['facility_name'], "ํ›ˆ๋ จ์ผ์ž", data['training_date'])
949
+ write_general_info_row(ws_report, 5, "ํ›ˆ๋ จ์‹œ๊ฐ„", data['training_time'], "ํ›ˆ๋ จ์žฅ์†Œ", data['training_location'])
950
+ write_general_info_row(ws_report, 6, "ํ›ˆ๋ จ์œ ํ˜•", f"{training_type} (์‹ค์ œ ํ›ˆ๋ จ์™„๋ฃŒ)", "ํ›ˆ๋ จ์ฃผ๊ด€์ž", data['host'])
951
+ write_spacer(ws_report, 7)
952
+
953
+ # 1. ํ›ˆ๋ จ ์‹ค์ œ ์ฐธ์—ฌ ๋ฐ ๋ฐ์ดํ„ฐ ๊ฒฐ๊ณผ
954
+ write_section_header(ws_report, 8, "1. ํ›ˆ๋ จ ์‹ค์ œ ์ฐธ์—ฌ ๋ฐ ๋ฐ์ดํ„ฐ ๊ฒฐ๊ณผ")
955
+ curr_row = write_report_participants(ws_report, 9, data)
956
+
957
+ curr_row += 1
958
+ write_spacer(ws_report, curr_row)
959
+ curr_row += 1
960
+
961
+ # 2. ๋‹ค์ง์ข…๋ณ„ ํ›ˆ๋ จ ํ‰๊ฐ€ ๋ฐ ํšŒ์˜ ์˜๊ฒฌ
962
+ write_section_header(ws_report, curr_row, "2. ๋‹ค์ง์ข…๋ณ„ ํ›ˆ๋ จ ํ‰๊ฐ€ ๋ฐ ํšŒ์˜ ์˜๊ฒฌ")
963
+ curr_row += 1
964
+
965
+ curr_row = write_role_meeting_opinion(
966
+ ws_report, curr_row, "์‹œ์„ค์žฅ",
967
+ f"- ํ‰๊ฐ€ ๋ฐ ์šด์˜์ƒ ํ•„์š”ํ•œ ์กฐ์น˜: {data['opinion_์‹œ์„ค์žฅ_1']}",
968
+ f"- ๊ธฐ๊ด€ ์ฐจ์›์˜ ์ง€์›: {data['opinion_์‹œ์„ค์žฅ_2']}",
969
+ f"- ์—ญํ• : {data['opinion_์‹œ์„ค์žฅ_role']}"
970
+ )
971
+ curr_row += 1
972
+ curr_row = write_role_meeting_opinion(
973
+ ws_report, curr_row, "์‚ฌํšŒ๋ณต์ง€์‚ฌ",
974
+ f"- ์‚ฌ๋ก€๊ด€๋ฆฌ ๊ด€์ : {data['opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_1']}",
975
+ f"- ์„œ๋น„์Šค๊ณ„ํš ๋ฐ˜์˜: {data['opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_2']}",
976
+ f"- ์—ญํ• : {data['opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_role']}"
977
+ )
978
+ curr_row += 1
979
+ curr_row = write_role_meeting_opinion(
980
+ ws_report, curr_row, "์š”์–‘๋ณดํ˜ธ์‚ฌ",
981
+ f"- ์ผ์ƒ์ƒํ™œ ๊ด€์ฐฐ: {data['opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_1']}",
982
+ f"- ๋Œ๋ด„ ์ œ๊ณต ์‹œ ์œ ์˜์‚ฌํ•ญ: {data['opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_2']}",
983
+ f"- ์—ญํ• : {data['opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_role']}"
984
+ )
985
+ curr_row += 1
986
+ curr_row = write_role_meeting_opinion(
987
+ ws_report, curr_row, "๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ",
988
+ f"- ๊ฑด๊ฐ•์ƒํƒœ ํ™•์ธ: {data['opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_1']}",
989
+ f"- ๋ณต์•ฝยทํ”ผ๋ถ€ยท๊ฐ์—ผ๊ด€๋ฆฌ: {data['opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_2']}",
990
+ f"- ์—ญํ• : {data['opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_role']}"
991
+ )
992
+ curr_row += 1
993
+ curr_row = write_role_meeting_opinion(
994
+ ws_report, curr_row, "๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ",
995
+ f"- ์‹ ์ฒด๊ธฐ๋Šฅ ํ‰๊ฐ€: {data['opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_1']}",
996
+ f"- ๋‚™์ƒ์˜ˆ๋ฐฉ ๋ฐ ์šด๋™๊ณ„ํš: {data['opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_2']}",
997
+ f"- ์—ญํ• : {data['opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_role']}"
998
+ )
999
+
1000
+ curr_row += 1
1001
+ write_spacer(ws_report, curr_row)
1002
+ curr_row += 1
1003
+
1004
+ # 3. ํ›ˆ๋ จ ๊ฒฐ๊ณผ ๋ถ„์„ ๋ฐ 2์ฐจ ๋ฐ˜์˜ (2์ฐจ ๊ฒฐ๊ณผ ๋ฐ˜์˜)
1005
+ write_section_header(ws_report, curr_row, "3. ํ›ˆ๋ จ ๊ฒฐ๊ณผ ๋ถ„์„ ๋ฐ 2์ฐจ ๋ฐ˜์˜ (2์ฐจ ๊ฒฐ๊ณผ ๋ฐ˜์˜)")
1006
+ curr_row += 1
1007
+
1008
+ curr_row = write_secondary_result_row(ws_report, curr_row, "1์ฐจ ๋ฌธ์ œ์ƒํƒœ", data['result_problem'])
1009
+ curr_row += 1
1010
+ curr_row = write_secondary_result_row(ws_report, curr_row, "์ ์šฉํ•œ ์กฐ์น˜", data['result_action'])
1011
+ curr_row += 1
1012
+ curr_row = write_secondary_result_row(ws_report, curr_row, "์ง์ข…๋ณ„ ์ˆ˜ํ–‰๋‚ด์šฉ", data['result_role_actions'])
1013
+ curr_row += 1
1014
+ curr_row = write_secondary_result_row(ws_report, curr_row, "๋ณ€ํ™”๋œ ๊ฒฐ๊ณผ", data['result_outcome'])
1015
+ curr_row += 1
1016
+ curr_row = write_secondary_result_row(ws_report, curr_row, "๊ตฌ์ฒด์  ๋ฐ์ดํ„ฐ", data['result_data'])
1017
+ curr_row += 1
1018
+ curr_row = write_secondary_result_row(ws_report, curr_row, "๋‚จ์€ ์œ„ํ—˜์š”์ธ", data['result_risks'])
1019
+ curr_row += 1
1020
+ curr_row = write_secondary_result_row(ws_report, curr_row, "ํ–ฅํ›„ ๊ณ„ํš", data['result_next'])
1021
+ curr_row += 1
1022
+ curr_row = write_secondary_result_row(ws_report, curr_row, "๋ณดํ˜ธ์ž ์˜๊ฒฌ ๋ฐ˜์˜๋‚ด์šฉ", data['result_guardian'])
1023
+
1024
+ curr_row += 1
1025
+ write_spacer(ws_report, curr_row)
1026
+ curr_row += 1
1027
+
1028
+ # 4. ๋ณดํ˜ธ์ž ์ „ํ™” ์˜๊ฒฌ ๋ฐ˜์˜
1029
+ write_section_header(ws_report, curr_row, "4. ๋ณดํ˜ธ์ž ์ „ํ™” ์˜๊ฒฌ ๋ฐ˜์˜")
1030
+ curr_row += 1
1031
+ curr_row = write_guardian_feedback(ws_report, curr_row, data)
1032
+
1033
+ curr_row += 1
1034
+ write_spacer(ws_report, curr_row)
1035
+ curr_row += 1
1036
+
1037
+ # 5. ํ›ˆ๋ จ ์‚ฌ์ง„ ์ฒจ๋ถ€๋ž€
1038
+ write_section_header(ws_report, curr_row, "5. ํ›ˆ๋ จ ์‚ฌ์ง„ ์ฒจ๋ถ€๋ž€")
1039
+ curr_row += 1
1040
+ curr_row = write_photo_section(ws_report, curr_row)
1041
+
1042
+ # ---------------------------------------------------------
1043
+ # TAB 3: ํ‰๊ฐ€๋ˆ„๋ฝ ์ฒดํฌ๋ฆฌ์ŠคํŠธ (Checklist)
1044
+ # ---------------------------------------------------------
1045
+ ws_checklist = wb.create_sheet(title="ํ‰๊ฐ€๋ˆ„๋ฝ ์ฒดํฌ๋ฆฌ์ŠคํŠธ")
1046
+ write_checklist_tab(ws_checklist, data)
1047
+
1048
+ excel_stream = io.BytesIO()
1049
+ wb.save(excel_stream)
1050
+ excel_stream.seek(0)
1051
+ return excel_stream
1052
+
1053
+ # ---------------------------------------------------------
1054
+ # Streamlit Application User Interface
1055
+ # ---------------------------------------------------------
1056
+ def main():
1057
+ st.markdown('<div class="title-card"><h1>๐Ÿš’ ์žฅ๊ธฐ์š”์–‘๊ธฐ๊ด€ ํ‰๊ฐ€ ๋Œ€์‘ ํ›ˆ๋ จ ๋ฌธ์„œ ์ž๋™์ƒ์„ฑ๊ธฐ</h1><p>๋‹ค์ง์ข… ๊ฐ์‚ฌ ์—์ด์ „ํŠธ์˜ ์ง€์นจ์„ 100% ๋ฐ˜์˜ํ•˜์—ฌ, ์‹ค์ œ ํ˜„์žฅ ๋ฐ ํ‰๊ฐ€ ๋Œ€์‘์ด ๊ฐ€๋Šฅํ•œ ์ˆ˜์ค€์˜ ํ›ˆ๋ จ ๋ฌธ์„œ๋ฅผ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.</p></div>', unsafe_allow_html=True)
1058
+
1059
+ col_left, col_right = st.columns([1, 2.2])
1060
+
1061
+ with col_left:
1062
+ st.markdown('<div class="section-header">๐Ÿข ๊ธฐ๊ด€ ๊ธฐ๋ณธ ์ •๋ณด</div>', unsafe_allow_html=True)
1063
+ facility_name = st.text_input("๊ธฐ๊ด€๋ช…", value="ํ–‰๋ณต์š”์–‘์›")
1064
+ facility_head = st.text_input("์‹œ์„ค์žฅ๋ช…", value="ํ™๊ธธ๋™")
1065
+ writer = st.text_input("๋‹ด๋‹น์ž (์ž‘์„ฑ์ž) ๋ช…", value="๊น€๋ณต์ง€")
1066
+ training_date = st.date_input("ํ›ˆ๋ จ/๊ต์œก ์ผ์ž", value=datetime.today())
1067
+ training_time = st.text_input("ํ›ˆ๋ จ/๊ต์œก ์‹œ๊ฐ„", value="14:00 ~ 15:00")
1068
+ training_location = st.text_input("ํ›ˆ๋ จ/๊ต์œก ์žฅ์†Œ", value="์š”์–‘์› ์ „ ์ธต ๋ฐ ์•ผ์™ธ ๋Œ€ํ”ผ๊ด‘์žฅ")
1069
+
1070
+ st.markdown('<div class="section-header">โš™๏ธ ํ›ˆ๋ จ ๋ฐ ๊ต์œก ์„ค์ •</div>', unsafe_allow_html=True)
1071
+ training_type = st.selectbox("ํ›ˆ๋ จ/๊ต์œก ์œ ํ˜•", ["์†Œ๋ฐฉํ›ˆ๋ จ", "์žฌ๋‚œํ›ˆ๋ จ", "์•ˆ์ „๊ต์œก"])
1072
+ host = st.text_input("ํ›ˆ๋ จ ์ฃผ๊ด€์ž", value=f"์‹œ์„ค์žฅ {facility_head}")
1073
+
1074
+ with col_right:
1075
+ tab_inputs, tab_guardian, tab_preview = st.tabs(["๐Ÿ“Š ์ƒ์„ธ ์ •๋Ÿ‰์  ๋ฐ์ดํ„ฐ", "๐Ÿ“ž ๋ณดํ˜ธ์ž ์˜๊ฒฌ ๋ฐ˜์˜", "๐Ÿ‘๏ธ ์ „๋ฌธ์„ฑ๊ฐ•ํ™” ๊ฐ์‚ฌ ๋ฌธ์žฅ ์‹ค์‹œ๊ฐ„ ํ”„๋ฆฌ๋ทฐ"])
1076
+
1077
+ with tab_inputs:
1078
+ st.markdown("##### ํ›ˆ๋ จ ์ฐธ์—ฌ ์ •๋Ÿ‰ ๋ฐ์ดํ„ฐ")
1079
+ col1, col2, col3 = st.columns(3)
1080
+ with col1:
1081
+ staff_participants = st.number_input("์ข…์‚ฌ์ž ์ฐธ์—ฌ์ž ์ˆ˜ (๋ช…)", value=8, min_value=1)
1082
+ vulnerable_count = st.number_input("๋Œ€ํ”ผ์ทจ์•ฝ์ž ์ˆ˜ (๋ช…)", value=5, min_value=0)
1083
+ with col2:
1084
+ recipient_participants = st.number_input("์ˆ˜๊ธ‰์ž ์ฐธ์—ฌ์ž ์ˆ˜ (๋ช…)", value=12, min_value=1)
1085
+ wheelchair_count = st.number_input("ํœ ์ฒด์–ด ์‚ฌ์šฉ ๋Œ€์ƒ์ž ์ˆ˜ (๋ช…)", value=3, min_value=0)
1086
+ with col3:
1087
+ total_participants = staff_participants + recipient_participants
1088
+ st.metric("์ด ์ฐธ์—ฌ ์ธ์› (์ข…์‚ฌ์ž + ์ˆ˜๊ธ‰์ž)", f"{total_participants} ๋ช…")
1089
+ walk_aid_count = st.number_input("๋ณดํ–‰๋ณด์กฐ ํ•„์š”์ž ์ˆ˜ (๋ช…)", value=4, min_value=0)
1090
+
1091
+ st.markdown("##### ํ›ˆ๋ จ ๊ด€๋ จ ํ™•์ธ/์ ๊ฒ€ ์ง€ํ‘œ")
1092
+ col4, col5 = st.columns(2)
1093
+ with col4:
1094
+ evac_time = st.text_input("๋Œ€ํ”ผ์™„๋ฃŒ ์‹œ๊ฐ„", value="4๋ถ„ 30์ดˆ")
1095
+ route_checked = st.selectbox("๋Œ€ํ”ผ๊ฒฝ๋กœ ํ™•์ธ ์—ฌ๋ถ€", ["ํ™•์ธ์™„๋ฃŒ", "๋ฏธํ™•์ธ"])
1096
+ contact_checked = st.selectbox("๋น„์ƒ์—ฐ๋ฝ๋ง ์ž‘๋™ ์—ฌ๋ถ€", ["์ž‘๋™ํ™•์ธ", "๋ฏธํ™•์ธ"])
1097
+ with col5:
1098
+ emergency_mock = st.selectbox("์‘๊ธ‰์ƒํ™ฉ ๋ชจ์˜๋Œ€์‘ ์—ฌ๋ถ€", ["์‹ค์‹œ ๋ฐ ์–‘ํ˜ธ", "๋ฏธ์‹ค์‹œ"])
1099
+ fire_ext_demo = st.selectbox("์†Œํ™”๊ธฐ ์‚ฌ์šฉ ์‹œ์—ฐ ์—ฌ๋ถ€", ["์‹ค์‹œ ๋ฐ ์–‘ํ˜ธ", "๋ฏธ์‹ค์‹œ"])
1100
+
1101
+ with tab_guardian:
1102
+ st.markdown("##### ํ›ˆ๋ จ ํ›„ ๋ณดํ˜ธ์ž ์œ ์„  ํ”ผ๋“œ๋ฐฑ ์ˆ˜๋ ด (์‚ฌํ›„ ์˜๊ฒฌ ๋ฐ˜์˜)")
1103
+ col_date, col_reflected = st.columns(2)
1104
+ with col_date:
1105
+ guardian_call_date = st.date_input("๋ณดํ˜ธ์ž ์œ ์„  ์—ฐ๋ฝ ์ผ์ž", value=datetime.today())
1106
+ with col_reflected:
1107
+ guardian_reflected = st.selectbox("์•ˆ์ „๊ด€๋ฆฌ/์„œ๋น„์Šค๊ณ„ํš ๋ฐ˜์˜ ์—ฌ๋ถ€", [
1108
+ "๋ฐ˜์˜์™„๋ฃŒ (์„œ๋น„์Šค๊ณ„ํš ๋ฐ ์•ˆ์ „๊ด€๋ฆฌ๊ณ„ํš ๋ฐ˜์˜)",
1109
+ "๋ฐ˜์˜์™„๋ฃŒ (๋ณดํ˜ธ์ž ์•ˆ๋‚ด ๋ฐ ์—ฐ๋ฝ๋ง ์ตœ์‹ ํ™”)",
1110
+ "๋ฏธ๋ฐ˜์˜"
1111
+ ])
1112
+
1113
+ guardian_opinion = st.text_area(
1114
+ "๋ณดํ˜ธ์ž ํ†ตํ™” ์˜๊ฒฌ",
1115
+ value="ํ›ˆ๋ จ ์‹œ ๊ฑฐ๋™์ด ๋ถˆํŽธํ•œ ์–ด๋ฅด์‹ ๋“ค์ด ๋‚™์ƒํ•˜์ง€ ์•Š๋„๋ก ํŠน๋ณ„ํžˆ ์‹ ๊ฒฝ ์จ ์ฃผ์…จ์œผ๋ฉด ์ข‹๊ฒ ๊ณ , ๋น„์ƒ์‹œ ์—ฐ๋ฝ์ด ์ž˜ ๋‹ฟ์„ ์ˆ˜ ์žˆ๊ฒŒ ๋น„์ƒ ์—ฐ๋ฝ๋ง ๊ด€๋ฆฌ๋ฅผ ์ฒ ์ €ํžˆ ํ•ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜์…จ์Šต๋‹ˆ๋‹ค."
1116
+ )
1117
+ guardian_response = st.text_area(
1118
+ "๊ธฐ๊ด€ ์„ค๋ช… ๋ฐ ๋Œ€์ฑ… ๋‚ด์šฉ",
1119
+ value="ํ›ˆ๋ จ ์ „ ๋Œ€ํ”ผ์ทจ์•ฝ์ž๋กœ ๋ถ„๋ฅ˜ํ•˜์—ฌ ์š”์–‘๋ณดํ˜ธ์‚ฌ๋ฅผ 1:1 ๋งค์นญํ•˜์—ฌ ์ด๋™์„ ์ง€์›ํ•  ๊ณ„ํš์ž„์„ ์„ค๋ช…ํ•˜์˜€์œผ๋ฉฐ, ๋ณดํ˜ธ์ž ๋น„์ƒ์—ฐ๋ฝ์ฒ˜ ์ตœ์‹ ํ™”๋ฅผ ๋งˆ์ณค๊ณ  ํ›ˆ๋ จ ์งํ›„ ๊ฒฐ๊ณผ๋ฅผ ์•ˆ๋‚ดํ•  ์˜ˆ์ •์ž„์„ ์„ค๋ช…ํ•จ."
1120
+ )
1121
+
1122
+ with tab_preview:
1123
+ preview_info = {
1124
+ 'facility_name': facility_name,
1125
+ 'total_participants': total_participants,
1126
+ 'staff_participants': staff_participants,
1127
+ 'recipient_participants': recipient_participants,
1128
+ 'evac_time': evac_time,
1129
+ 'vulnerable_count': vulnerable_count,
1130
+ 'wheelchair_count': wheelchair_count,
1131
+ 'walk_aid_count': walk_aid_count,
1132
+ 'emergency_mock': emergency_mock,
1133
+ 'fire_ext_demo': fire_ext_demo,
1134
+ 'route_checked': route_checked,
1135
+ 'contact_checked': contact_checked,
1136
+ 'guardian_call_date': str(guardian_call_date),
1137
+ 'guardian_reflected': guardian_reflected
1138
+ }
1139
+
1140
+ st.markdown(f"### ๐Ÿ“ {training_type} ๋‹ค์ง์ข… ๊ฐ์‚ฌ ์˜๊ฒฌ์„œ ๋ฐ 2์ฐจ ๊ฒฐ๊ณผ ํ”„๋ฆฌ๋ทฐ")
1141
+
1142
+ st.markdown("#### [๋‹ค์ง์ข… ํšŒ์˜ ์˜๊ฒฌ]")
1143
+ roles_list = ['์‹œ์„ค์žฅ', '์‚ฌํšŒ๋ณต์ง€์‚ฌ', '์š”์–‘๋ณดํ˜ธ์‚ฌ', '๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ', '๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ']
1144
+ for r in roles_list:
1145
+ st.markdown(f"**๐Ÿ”น {r} ์˜๊ฒฌ**")
1146
+ if r == '์‹œ์„ค์žฅ':
1147
+ st.write(f"- ํ‰๊ฐ€ ๋ฐ ์šด์˜์ƒ ํ•„์š”ํ•œ ์กฐ์น˜: {generate_narrative_text(preview_info, 'opinion_์‹œ์„ค์žฅ_1', training_type)}")
1148
+ st.write(f"- ๊ธฐ๊ด€ ์ฐจ์›์˜ ์ง€์›: {generate_narrative_text(preview_info, 'opinion_์‹œ์„ค์žฅ_2', training_type)}")
1149
+ elif r == '์‚ฌํšŒ๋ณต์ง€์‚ฌ':
1150
+ st.write(f"- ์‚ฌ๋ก€๊ด€๋ฆฌ ๊ด€์ : {generate_narrative_text(preview_info, 'opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_1', training_type)}")
1151
+ st.write(f"- ์„œ๋น„์Šค๊ณ„ํš ๋ฐ˜์˜: {generate_narrative_text(preview_info, 'opinion_์‚ฌํšŒ๋ณต์ง€์‚ฌ_2', training_type)}")
1152
+ elif r == '์š”์–‘๋ณดํ˜ธ์‚ฌ':
1153
+ st.write(f"- ์ผ์ƒ์ƒํ™œ ๊ด€์ฐฐ: {generate_narrative_text(preview_info, 'opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_1', training_type)}")
1154
+ st.write(f"- ๋Œ๋ด„ ์ œ๊ณต ์‹œ ์œ ์˜์‚ฌํ•ญ: {generate_narrative_text(preview_info, 'opinion_์š”์–‘๋ณดํ˜ธ์‚ฌ_2', training_type)}")
1155
+ elif r == '๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ':
1156
+ st.write(f"- ๊ฑด๊ฐ•์ƒํƒœ ํ™•์ธ: {generate_narrative_text(preview_info, 'opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_1', training_type)}")
1157
+ st.write(f"- ๋ณต์•ฝยทํ”ผ๋ถ€ยท๊ฐ์—ผ๊ด€๋ฆฌ: {generate_narrative_text(preview_info, 'opinion_๊ฐ„ํ˜ธ์กฐ๋ฌด์‚ฌ_2', training_type)}")
1158
+ elif r == '๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ':
1159
+ st.write(f"- ์‹ ์ฒด๊ธฐ๋Šฅ ํ‰๊ฐ€: {generate_narrative_text(preview_info, 'opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_1', training_type)}")
1160
+ st.write(f"- ๋‚™์ƒ์˜ˆ๋ฐฉ ๋ฐ ์šด๋™๊ณ„ํš: {generate_narrative_text(preview_info, 'opinion_๋ฌผ๋ฆฌ์น˜๋ฃŒ์‚ฌ_2', training_type)}")
1161
+ st.write(f"- ์—ญํ• : {generate_narrative_text(preview_info, f'opinion_{r}_role', training_type)}")
1162
+
1163
+ st.markdown("#### [2์ฐจ ๊ฒฐ๊ณผ ๋ฐ˜์˜]")
1164
+ st.write(f"**1์ฐจ ๋ฌธ์ œ์ƒํƒœ**: {generate_narrative_text(preview_info, 'result_problem', training_type)}")
1165
+ st.write(f"**์ ์šฉํ•œ ์กฐ์น˜**: {generate_narrative_text(preview_info, 'result_action', training_type)}")
1166
+ st.write(f"**์ง์ข…๋ณ„ ์ˆ˜ํ–‰๋‚ด์šฉ**: {generate_narrative_text(preview_info, 'result_role_actions', training_type)}")
1167
+ st.write(f"**๋ณ€ํ™”๋œ ๊ฒฐ๊ณผ**: {generate_narrative_text(preview_info, 'result_outcome', training_type)}")
1168
+ st.write(f"**๊ตฌ์ฒด์  ๋ฐ์ดํ„ฐ**: {generate_narrative_text(preview_info, 'result_data', training_type)}")
1169
+ st.write(f"**๋‚จ์€ ์œ„ํ—˜์š”์ธ**: {generate_narrative_text(preview_info, 'result_risks', training_type)}")
1170
+ st.write(f"**ํ–ฅํ›„ ๊ณ„ํš**: {generate_narrative_text(preview_info, 'result_next', training_type)}")
1171
+ st.write(f"**๋ณดํ˜ธ์ž ์˜๊ฒฌ ๋ฐ˜์˜๋‚ด์šฉ**: {generate_narrative_text(preview_info, 'result_guardian', training_type)}")
1172
+
1173
+ st.markdown('<div style="margin-top: 2rem;"></div>', unsafe_allow_html=True)
1174
+
1175
+ info_payload = {
1176
+ 'facility_name': facility_name,
1177
+ 'facility_head': facility_head,
1178
+ 'writer': writer,
1179
+ 'training_date': training_date,
1180
+ 'training_time': training_time,
1181
+ 'training_location': training_location,
1182
+ 'host': host,
1183
+ 'total_participants': total_participants,
1184
+ 'staff_participants': staff_participants,
1185
+ 'recipient_participants': recipient_participants,
1186
+ 'evac_time': evac_time,
1187
+ 'vulnerable_count': vulnerable_count,
1188
+ 'wheelchair_count': wheelchair_count,
1189
+ 'walk_aid_count': walk_aid_count,
1190
+ 'emergency_mock': emergency_mock,
1191
+ 'fire_ext_demo': fire_ext_demo,
1192
+ 'route_checked': route_checked,
1193
+ 'contact_checked': contact_checked,
1194
+ 'guardian_call_date': guardian_call_date,
1195
+ 'guardian_opinion': guardian_opinion,
1196
+ 'guardian_response': guardian_response,
1197
+ 'guardian_reflected': guardian_reflected,
1198
+ }
1199
+
1200
+ excel_file = create_excel(info_payload, training_type)
1201
+ filename = f"{facility_name}_{training_date.strftime('%Y%m%d')}_{training_type}_๋‹ค์ง์ข…ํ‰๊ฐ€๋Œ€์‘_ํ†ตํ•ฉ๋ฌธ์„œ.xlsx"
1202
+
1203
+ st.download_button(
1204
+ label=f"๐Ÿ“ฅ {training_type} ๊ณ„ํš์„œ/๊ฒฐ๊ณผ๋ณด๊ณ ์„œ ์—‘์…€ ๋‹ค์šด๋กœ๋“œ (๊ฐ์‚ฌ ๋ฐ˜์˜๋ณธ)",
1205
+ data=excel_file,
1206
+ file_name=filename,
1207
+ mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1208
+ )
1209
+
1210
+ if __name__ == "__main__":
1211
+ main()