ll7098ll commited on
Commit
9313759
·
verified ·
1 Parent(s): d39af66

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -294
app.py CHANGED
@@ -87,10 +87,7 @@ ALL_TEXTS = {
87
  "desk_feedback_title": "📢 AI 편집장님의 한마디",
88
  "status_loading_assignment": "{year}년 {turn}번째 날, 무슨 일이 있을까? 기다려주세요...",
89
  "status_actions_taken": "오늘 할 일을 다 했어요. 기사를 쓰거나 다음 날로 넘어가세요.",
90
- "sidebar_title": "메뉴",
91
  "sidebar_glossary_title": "📰 어려운 말/사람 이야기",
92
- "sidebar_current_source_title": "📎 지금 보는 도움 자료",
93
- "sidebar_no_source": "지금은 특별히 볼 만한 자료가 없어요.",
94
  "button_submit_article": "기사 보내기 (AI 편집장님께)",
95
  "article_headline_label": "기사 제목:",
96
  "article_body_label": "기사 내용 요약 (짧게 3~5줄):",
@@ -108,12 +105,10 @@ ALL_TEXTS = {
108
  "log_safety_change_article": " - 기자님 안전이 {change:+}만큼 바뀌었어요.",
109
  "log_assignment_over": "--- {scenario_name} 취재 끝 ---",
110
  "log_next_day_start": "--- {year}년 {turn}번째 날 시작 ---",
111
- "button_go_to_article_writing": "기사 쓰러 가기",
112
  "error_openai_api": "AI 편집장님 연결에 문제가 생겼어요: {error}",
113
 
114
  # --- 4.19 혁명 취재 시나리오 ---
115
- "scenario_4.19_revolution_name": "4.19 혁명 이야기 (1960년)", # 키 수정 (scenario_419_revolution_name -> scenario_4.19_revolution_name)
116
- # Turn 1 (3.15 부정선거)
117
  "event_419_t1_assignment": "오늘은 3월 15일, 대통령과 부통령을 뽑는 날이에요. 투표하는 곳에서 나쁜 사람들이 규칙을 어기고 자기편만 뽑으려고 할지도 몰라요. 그런 이상한 점을 찾아내고, 투표를 지켜보는 사람, 투표하는 사람, 선거를 관리하는 사람들에게 이야기를 들어보는 것이 오늘 할 일이에요. 특히 반대편 사람들이 잘 감시하는지, 힘 있는 쪽 사람들이 몰래 나쁜 일을 꾸미는지 잘 살펴보세요.",
118
  "event_419_t1_source": "[알아두면 좋아요] 지금 자유당이라는 당이 오랫동안 나라를 다스려서 사람들이 불만이 많아요. 이번 선거에서 이승만 대통령이 또 대통령이 되고, 이기붕 아저씨가 부통령이 되려고 자유당이 나쁜 방법을 쓸 거라는 소문이 많아요. 미리 투표한 표를 몰래 바꾸거나, 없는 사람 표를 넣거나, 여럿이 같이 보면서 투표하게 만들거나, 반대편 감시하는 사람들을 쫓아낸다는 이야기가 돌고 있어요.",
119
  "action_419_t1_opt1_text": "서울 투표하는 곳에 몰래 들어가서 사진 찍어보기",
@@ -122,7 +117,6 @@ ALL_TEXTS = {
122
  "info_419_t1_opt1_got": "새로운 사실: 종로 A투표소에서 자유당 표시를 한 사람들이 투표함에 표를 많이 넣는 걸 멀리서 봤어요. 가까이 가려니까 무섭게 쳐다봤어요. (힌트: 표 몰래 넣기, 자유당 표시, 무서움)",
123
  "info_419_t1_opt2_got": "새로운 사실: 민주당 쪽 감시원 박 아저씨가 화나서 말했어요. '성북 B투표소에서 경찰이 어떤 사람들 투표하는 곳까지 따라가서 누굴 찍는지 봤어요! 안 된다고 했는데 내 말을 안 들었어요!' 사진도 조금 찍었대요. (힌트: 경찰이 투표 방해, 감시원 말 무시, 민주당)",
124
  "info_419_t1_opt3_got": "새로운 사실: 이름을 밝히기 싫어하는 선거 관리 직원이 떨면서 말했어요. '오늘 새벽에 어떤 투표함들을 이상한 차가 가져가는 걸 봤어요. 너무 무서워요.' (힌트: 투표함 몰래 바꾼 듯, 선거 관리 직원 제보, 무서움)",
125
- # Turn 2 (김주열 열사 발견)
126
  "event_419_t2_assignment": "마산에서 나쁜 선거에 반대하며 시위하던 김주열 학생이 사라졌는데, 바다에서 슬픈 모습으로 발견됐어요. 왜 김주열 학생이 죽었는지, 경찰은 처음에 어떻게 했는지, 마산 사람들이 얼마나 화가 났는지 자세히 알아보세요.",
127
  "event_419_t2_source": "[알아두면 좋아요] 4월 11일, 마산 앞바다에서 눈에 최루탄이 박힌 김주열 학생의 모습은 사람들에게 큰 충격을 줬어요. 경찰은 처음엔 그냥 물에 빠져 죽었다고 하려 했지만, 모습이 알려지면서 거짓말 아니냐는 말이 많아졌어요. 마산은 이미 시위 때문에 분위기가 안 좋았어요.",
128
  "action_419_t2_opt1_text": "김주열 학생이 있는 병원에 가서 의사 선생님 만나보기",
@@ -131,7 +125,6 @@ ALL_TEXTS = {
131
  "info_419_t2_opt1_got": "새로운 사실: 병원 관계자가 몰래 말해줬어요. '김주열 학생은 최루탄 때문에 머리를 다쳐서 죽은 것 같아요. 경찰이 이걸 알리지 말라고 하고 있어요.' (힌트: 최루탄 때문에 죽음, 머리 다침, 경찰이 숨김)",
132
  "info_419_t2_opt2_got": "새로운 사실: 마산상고 학생들이 '친구를 살려내라!', '나쁜 경찰 혼내주자!' 외치며 경찰과 싸우고 있어요. 돌멩이랑 불도 던지고, 경찰��� 최루탄을 마구 쏴요. 다친 학생들이 많아요. (힌트: 마산 학생 시위, 경찰이 심하게 막음, 다친 사람 많음)",
133
  "info_419_t2_opt3_got": "새로운 사실: 김주열 학생 어머니가 울면서 말했어요. '우리 아들은 시위하러 간다고 하고 나갔어요. 경찰이 죽인 게 틀림없어요. 너무 억울해요.' (힌트: 김주열 가족, 경찰이 죽였다고 생각, 억울함)",
134
- # Turn 3 (고려대생 피습)
135
  "event_419_t3_assignment": "4월 18일, 나쁜 선거를 반대하는 시위를 마치고 학교로 돌아가던 고려대학교 학생들이 나쁜 아저씨들에게 맞았어요. 무슨 일이 있었는지, 경찰은 뭘 했는지, 다른 사람들은 어떻게 생각하는지 알아보세요.",
136
  "event_419_t3_source": "[알아두면 좋아요] 김주열 학생 일 때문에 학생들이 더 많이 시위하고 있는데, 이번엔 깡패 아저씨들이 나타나서 학생들을 때렸어요. 사람들이 더 화가 났어요. 경찰이 이걸 보고도 못 본 척한 거 아니냐는 말도 나와요.",
137
  "action_419_t3_opt1_text": "학생들이 맞은 곳과 다친 학생들이 있는 병원에 가보기",
@@ -140,7 +133,6 @@ ALL_TEXTS = {
140
  "info_419_t3_opt1_got": "새로운 사실: 다친 학생이 말했어요. '시위 끝나고 조용히 가는데 갑자기 쇠파이프 든 아저씨들이 때렸어요. 살려달라고 해도 마구 때렸어요.' 병원에는 다친 학생들이 많았어요. (힌트: 고려대생 맞음, 깡패, 쇠파이프, 단체로 때림)",
141
  "info_419_t3_opt2_got": "새로운 사실: 경찰 아저씨가 말했어요. '학생들끼리 싸운 것 같아요. 깡패가 있다는 건 그냥 소문이에요.' 더 조사할 생각은 없어 보였어요. (힌트: 경찰이 대충 조사, 그냥 싸웠다고 함, 뒤에 누가 있는지 모른 척)",
142
  "info_419_t3_opt3_got": "새로운 사실: 서울대 학생 대표가 말했어요. '이건 나쁜 테러예요! 나라에서 도와주지 않으면 불가능한 일이에요. 모든 학생이 힘을 합쳐 싸울 거예요!' (힌트: 다른 학생들도 화남, 나라가 뒤에 있다고 의심, 같이 싸우자)",
143
- # Turn 4 (4.19 당일, 경무대 앞 발포)
144
  "event_419_t4_assignment": "4월 19일, 서울에서 아주 큰 시위가 일어나서 대통령이 사는 경무대로 가고 있어요. 얼마나 많은 사람들이 모였는지, 뭘 원하는지, 경찰은 어떻게 하는지(총을 쏘는지 포함), 다치거나 죽은 사람은 없는지 빨리 알려야 해요. 아주 위험하니까 조심 또 조심하세요!",
145
  "event_419_t4_source": "[알아두면 좋아요] 고려대 학생들이 맞은 일 때문에 서울에 있는 대학생, 중고등학생, 어른들까지 거리로 나와서 '이승만 대통령 물러나라!', '나쁜 선거 다시 하자!' 외치면서 경무대로 가고 있어요. 경찰은 최루탄이랑 소방차로 막고 있지만 사람들이 너무 많아요.",
146
  "action_419_t4_opt1_text": "경무대 근처 시위대 맨 앞에 가서 직접 보기 (아주 위험!)",
@@ -149,7 +141,6 @@ ALL_TEXTS = {
149
  "info_419_t4_opt1_got": "새로운 사실: 시위대가 경찰 막는 걸 뚫고 경무대로 가려고 해요. 경찰이 시위대한테 마구 총을 쏘기 시작했어요! 눈앞에서 학생들이 피 흘리며 쓰러져요. 너무 무서운 현장이에요. (힌트: 경무대에서 총쏨, 마구 쏨, 학생들 죽음, 끔찍함)",
150
  "info_419_t4_opt2_got": "새로운 사실: 수만 명의 사람들이 태평로와 광화문을 꽉 채웠어요. 경찰이 최루탄이랑 진짜 총알을 쏘는 걸 봤어요. 길거리가 전쟁터 같아요. (힌트: 아주 큰 시위, 경찰이 진짜 총쏨, 전쟁터 같음)",
151
  "info_419_t4_opt3_got": "새로운 사실: 세브란스 병원 응급실에 총 맞은 사람들로 가득해요. 죽은 사람도 많아요. 의사 선생님들이 바쁘게 움직이지만 사람이 너무 많아요. '학생들이 죽어가고 있어요!' 하고 소리쳐요. (힌트: 총 맞은 환자, 많이 죽음, 병원도 힘듦, 의사 부족)",
152
- # Turn 5 (계엄령 선포)
153
  "event_419_t5_assignment": "정부가 서울이랑 다른 큰 도시에 '비상계엄'을 내렸어요. 군인들이 어디에 있는지, 사람들은 어떻게 생각하는지, 계엄령 아래서 신문이나 방송은 어떻게 되는지 알아보세요.",
154
  "event_419_t5_source": "[알아두면 좋아요] 4.19 시위가 너무 커지니까 정부가 4월 19일 오후 5시에 서울에 비상계엄을 내리고 군인들을 보냈어요. 그 후 부산, 대구, 광주 같은 큰 도시에도 계엄령이 내려졌어요. 계엄사령부는 모이거나 시위하는 걸 금지하고, 신문 기사도 미리 검사한다고 했어요.",
155
  "action_419_t5_opt1_text": "시내 중요 장소에 군인들이 있는지, 사람들 지나가는 거 검사하는지 보기",
@@ -158,7 +149,6 @@ ALL_TEXTS = {
158
  "info_419_t5_opt1_got": "새로운 사실: 탱크랑 장갑차를 탄 군인들이 길이랑 중요한 건물들을 지키고 있어요. 사람들이 마음대로 못 다니게 하고, 어떤 곳에서는 학생들을 막 잡아갔어요. (힌트: 군인이 도시 장악, 탱크 장갑차, 못 다니게 함, 강제로 잡아감)",
159
  "info_419_t5_opt2_got": "새로운 사실: 어떤 아저씨가 말했어요. '군인들이 총 들고 다니니까 무섭지만, 이렇게 나쁜 정치를 그냥 둘 수는 없어요. 기회가 되면 다시 시위할 거예요.' (힌트: 계엄령 속 사람들 마음, 무섭지만 싸우고 싶음, 나쁜 정치 싫음)",
160
  "info_419_t5_opt3_got": "새로운 사실: 계엄사령부에서 말했어요. '나라를 안전하게 하려고 신문 내용을 미리 검사할 거예요. 거짓 소문 퍼뜨리면 혼내줄 거예요.' 사실상 정부가 시키는 대로만 써야 해요. (힌트: 신문 검사, 정부 말만 쓰게 함, 계엄사령부, 정보 막음)",
161
- # Turn 6 (대학교수단 시위)
162
  "event_419_t6_assignment": "4월 25일, 전국 대학교수님들이 '우리도 할 말이 있다!' 하면서 거리로 나왔어요. 교수님들이 뭘 원하는지, 얼마나 많이 모였는지, 정부랑 사람들은 어떻게 생각하는지 알아보세요.",
163
  "event_419_t6_source": "[알아두면 좋아요] 학생들이 피 흘리는 걸 보고 똑똑한 어른들도 화가 났어요. 서울대학교 교수님들을 시작으로 전국 27개 대학교 258명의 교수님들이 '학생들의 피에 보답하라!' 하면서 이승만 대통령 물러나고 정부도 다 그만두라고 외치며 거리로 나왔어요. 이건 정부에게 큰 충격이었어요.",
164
  "action_419_t6_opt1_text": "교수님들 시위하는 곳(국회의사당 앞 등)에 같이 가보기",
@@ -167,7 +157,6 @@ ALL_TEXTS = {
167
  "info_419_t6_opt1_got": "새로운 사실: 수백 명의 교수님들이 '이승만 물러나라', '민주주의 지키자' 같은 글을 들고 조용히 걸었어요. 사람들은 박수치고 응원했어요. 경찰도 전보다 덜 막았어요. (힌트: 교수님들 시위, 이승만 물러나라고 함, 사람들 응원, 조용한 시위)",
168
  "info_419_t6_opt2_got": "새로운 사실: 서울대 K교수님이 말했어요. '더 이상 나쁜 일을 보고만 있을 수 없었어요. 이 대통령은 빨리 물러나고, 민주주의를 다시 찾아야 해요.' (힌트: 교수님들 생각, 나쁜 일 못 참음, 민주주의 되찾자)",
169
  "info_419_t6_opt3_got": "새로운 사실: 시위 보던 어떤 아줌마가 울면서 말했어요. '교수님들까지 나오시니 이제 정말 이 정권 끝났어요. 우리 학생들, 사람들 힘내요!' (힌트: 사람들 감동, 교수님들 응원, 정권 끝날 것 같음)",
170
- # Turn 7 (미국의 압력과 이승만 하야 결심)
171
  "event_419_t7_assignment": "미국 정부가 지금 우리나라 상황이 걱정된다면서 이승만 대통령에게 중요한 결정을 하라고 했다는 소문이 있어요. 이승만 대통령 마음이 어떻게 변했는지, 정말 물러날 건지, 자유당 사람들은 어떻게 움직이는지 빨리 알아보세요.",
172
  "event_419_t7_source": "[알아두면 좋아요] 4.19 혁명이 커지니까 미국 정부가 우리나라에 있는 미국 대사를 통해 이승만 대통령에게 사실상 물러나라고 했어요. 외국에서도 외면받고, 나라 안에서도 사람들이 계속 반대하니까 이 대통령은 아주 중요한 결정을 해야 해요.",
173
  "action_419_t7_opt1_text": "경무대 근처에서 대통령 주변 사람들 어떻게 하는지 보기",
@@ -176,7 +165,6 @@ ALL_TEXTS = {
176
  "info_419_t7_opt1_got": "새로운 사실: 경무대에서 일하는 사람이 몰래 말해줬어요. '대통령님이 며칠 동안 잠도 못 자고 깊이 고민하고 계세요. 곧 아주 중요한 발표가 있을 거라는 소문이 많아요.' (힌트: 이승만 대통령 고민, 중요한 발표 곧 할 듯, 경무대 분위기 심각)",
177
  "info_419_t7_opt2_got": "새로운 사실: 자유당 국회의원 M아저씨가 말했어요. '이미 끝났어요. 대통령님이 멋있게 물러나시는 게 유일한 방법이에요. 우리 당 안에서도 물러나시라고 말해야 한다는 목소리가 커지고 있어요.' (힌트: 자유당도 물러나라고 함, 멋있게 그만두길 바람, 당 안에서도 의견 갈림)",
178
  "info_419_t7_opt3_got": "새로운 사실: 미국 대사관 사람이 몰래 말해줬어요. '미국 정부는 한국이 다시 민주주의를 찾고, 평화롭게 정권이 바뀌길 바라요. 지금 상황이 계속되는 건 좋지 않아요.' (힌트: 미국 정부 생각, 민주주의 되찾길 바람, 평화롭게 바뀌길 바람)",
179
- # Turn 8 (이승만 대통령 하야 발표)
180
  "event_419_t8_assignment": "4월 26일, 이승만 대통령이 물러나겠다고 발표했어요! 대통령이 뭐라고 말했는지, 사람들은 어떤 반응인지, 앞으로 나라는 어떻게 될지 다 합쳐서 특별 기사를 써야 해요. (이번엔 취재 활동 없이 바로 기사 쓰기로 가요.)",
181
  "event_419_t8_source": "[긴급 뉴스] 이승만 대통령, 국민들이 원해서 대통령 자리에서 물러나겠다고 발표. 라디오로 이야기했어요. 사람들이 거리로 나와서 기뻐하고 있어요. 12년 동안 계속된 자유당 정치가 끝났어요.",
182
  "action_419_t8_opt1_text": "대통령이 물러나면서 한 말 자세히 보기",
@@ -187,8 +175,7 @@ ALL_TEXTS = {
187
  "info_419_t8_opt3_got": "새로운 사실: 정치학자 P교수님이 말했어요. '허정 아저씨가 잠깐 나라를 맡고, 곧 국회의원 선거를 다시 할 것 같아요. 민주당이 중심이 돼서 나라를 다스릴 가능성이 높아요. 하지만 좀 시끄럽고 사람들이 원하는 게 많아질 수도 있어요.' (힌트: 허정 아저씨가 임시로 맡음, 다시 선거, 민주당 중심 정치, 좀 시끄러울 수도 있음)",
188
 
189
  # --- 5.18 광주 취재 시나리오 ---
190
- "scenario_5.18_gwangju_name": "5.18 광주 이야기 (1980년)", # 키 수정 (scenario_518_gwangju_name -> scenario_5.18_gwangju_name)
191
- # Turn 1 (5.17 비상계엄 전국 확대)
192
  "event_518_t1_assignment": "5월 17일 밤부터 '비상계엄'이 전국으로 커졌어요. 광주 분위기는 어떤지, 중요한 사람들(학생 대표, 숨어있는 어른들)은 어떻게 움직이는지, 군인들은 뭘 하는지 알아보고 알려주세요. 신문이나 방송을 못 믿게 하니까 몰래 조심해서 취재해야 해요.",
193
  "event_518_t1_source": "[알아두면 좋아요] 10.26 사건 뒤에 '서울의 봄'이라고 해서 좋은 세상이 올 것 같았지만, 새로운 군인 아저씨들이 12.12 군사반란으로 힘을 잡으면서 다시 무서워졌어요. 새 군인들은 나라가 시끄럽다면서 비상계엄을 전국으로 넓히고, 김대중, 김영삼 같은 유명한 정치인들을 잡아가거나 못 나오게 했어요. 광주 대학교에서는 학생들이 시위하려는 움직임이 보여요.",
194
  "action_518_t1_opt1_text": "전남대학교 같은 대학교 학생회관 근처에서 이야기 들어보기",
@@ -197,7 +184,6 @@ ALL_TEXTS = {
197
  "info_518_t1_opt1_got": "새로운 사실: 전남대 학생 대표들이 '계엄 확대는 나쁜 짓이다!' 하면서 내일(18일) 아침에 학교에서 시위할 계획이래요. '학교 문 닫지 마라, 계엄령 없애라!' 외칠 준비를 하고 있어요. (힌트: 전남대 학생 시위 예고, 계엄 반대, 학교 문 열라고 함)",
198
  "info_518_t1_opt2_got": "새로운 사실: 광주역, 버스터미널, 도청 같은 중요한 곳에 무서운 무기를 든 공수부대 군인들이 나타나기 시작했어요. 사람들은 무서워하고 불안해해요. (힌트: 공수부대 나타남, 무섭게 지킴, 사람들 불안)",
199
  "info_518_t1_opt3_got": "새로운 사실: 이름을 밝히기 싫어하는 종교 지도자가 한숨 쉬며 말했어요. '새 군인들이 자기들 마음대로 하려고 사람들을 아주 심하게 혼내줄 것 같아요. 광주가 큰일 날까 봐 걱정돼요.' (힌트: 새 군인들 무섭게 할 듯, 광주 걱정, 종교 어른 생각)",
200
- # Turn 2 (5.18 첫날, 전남대 앞 충돌)
201
  "event_518_t2_assignment": "5월 18일 아침, 전남대학교 앞에서 학생들과 군인들이 처음으로 싸웠어요. 왜 싸움이 났는지, 어떻게 싸웠는지, 학생들과 군인들은 얼마나 다쳤는지, 다른 사람들은 어떻게 생각하는지 빨리 알아보세요. 현장에 갈 땐 아주 조심해야 해요!",
202
  "event_518_t2_source": "[알아두면 좋아요] 어제(17일) 비상계엄이 전국으로 커지면서 대학교 문을 닫으라고 했지만, 전남대 학생들은 반대하면서 학교 문 앞에서 시위를 했어요. 계엄군(공수부대)은 이걸 아주 세게 막기 시작했어요.",
203
  "action_518_t2_opt1_text": "전남대학교 정문 앞 시위 현장에 직접 가보기 (아주 위험!)",
@@ -206,7 +192,6 @@ ALL_TEXTS = {
206
  "info_518_t2_opt1_got": "새로운 사실: 공수부대 군인들이 학교 문으로 들어가려는 학생들을 몽둥이로 마구 때리고 군홧발로 찼어요. 여자든 남자든 가리지 않고 때렸어요. 학생들이 피 흘리며 쓰러지고 끌려가는 걸 봤어요. (힌트: 공수부대 너무 심하게 때림, 마구 때림, 학생들 다침, 전남대 정문)",
207
  "info_518_t2_opt2_got": "새로운 사실: 병원 응급실에 머리나 뼈를 다친 학생들로 가득해요. 한 학생은 '그냥 학교에 들어가려고 했는데, 군인들이 갑자기 몽둥이로 때렸어요!' 하면서 울었어요. (힌트: 학생들 많이 다침, 병원 응급실, 군인이 때렸다고 함)",
208
  "info_518_t2_opt3_got": "새로운 사실: 근처 가게 주인이 화내면서 말했어요. '학생들이 뭘 그렇게 잘못했다고 저렇게까지 때리나. 이건 너무 심해요. 군인이 아니라 깡패 같아요!' (힌트: 사람들 화남, 군인들 나쁘다고 함, 너무 심하게 막는 거 봄)",
209
- # Turn 3 (시위 확산과 계엄군의 잔혹한 진압)
210
  "event_518_t3_assignment": "학생들 시위가 광주 시내 전체로 퍼지고 있어요. 일반 시민들도 함께하고 있어요. 하지만 공수부대 군인들이 더 잔인하게 사람들을 때리고 잡아가고 있다는 소문이 들려요. 이 상황을 자세히 취재해주세요. 정말 위험하니 몸조심하세요!",
211
  "event_518_t3_source": "[알아두면 좋아요] 전남대 앞에서 시작된 군인들의 폭력은 오히려 시민들의 분노를 키웠어요. 학생들뿐만 아니라 일반 시민들도 거리로 나와 '계엄 철폐', '살인마 전두환 물러가라' 등을 외치고 있어요. 공수부대는 시위대뿐 아니라 길 가던 사람들에게도 폭력을 행사하고 있다는 목격담이 나오고 있어요.",
212
  "action_518_t3_opt1_text": "금남로 등 시위가 격렬한 곳으로 가서 상황 보기 (매우 위험!)",
@@ -215,7 +200,6 @@ ALL_TEXTS = {
215
  "info_518_t3_opt1_got": "새로운 사실: 금남로에서 군인들이 곤봉과 대검으로 사람들을 마구 찌르고 때리고 있어요. 길바닥에 피가 흥건하고, 비명소리가 끊이지 않아요. 젊은이, 노인 가리지 않아요. (힌트: 금남로, 군인들 잔인함, 피, 비명)",
216
  "info_518_t3_opt2_got": "새로운 사실: 한 아주머니가 울면서 말했어요. '내 아들이 학생도 아닌데 길 가다가 군인들에게 끌려갔어요! 살려주세요!' 많은 시민들이 군인들의 만행에 치를 떨고 있어요. (힌트: 시민들 분노, 아무나 잡아감, 군인 만행)",
217
  "info_518_t3_opt3_got": "새로운 사실: 군인에게 맞아서 다리가 부러진 아저씨를 만났어요. '그냥 집에 가던 길이었는데, 갑자기 군인 서너 명이 달려들어 때렸어요. 이유도 없었어요.' (힌트: 무차별 폭행, 이유 없는 폭력, 시민 피해)",
218
- # Turn 4 (시민들의 자체 무장과 항쟁 시작)
219
  "event_518_t4_assignment": "군인들의 폭력이 너무 심해지자, 일부 시민들이 스스로를 지키기 위해 무기를 들기 시작했다는 소식이 있어요. '시민군'이 만들어졌다는 말도 들려요. 광주 상황이 어떻게 변하고 있는지, 시민들은 왜 무기를 들었는지 알아보세요.",
220
  "event_518_t4_source": "[알아두면 좋아요] 계엄군의 무자비한 살상 행위에 맞서 시민들은 더 이상 맨손으로 저항할 수 없다고 판단하기 시작했어요. 경찰서나 예비군 무기고에서 총기 등을 확보하고, 스스로를 '시민군'이라 부르며 조직적으로 저항하려는 움직임이 나타나고 있어요. 광주는 외부와 완전히 차단된 상태예요.",
221
  "action_518_t4_opt1_text": "시민군이 모여 있다는 곳(도청 주변 등)에 조심스럽게 접근해보기",
@@ -224,7 +208,6 @@ ALL_TEXTS = {
224
  "info_518_t4_opt1_got": "새로운 사실: 도청 주변에 젊은이들이 총을 들고 모여 있어요. 스스로를 '시민군'이라고 부르며, '계엄군으로부터 광주를 지키겠다'고 외치고 있어요. 분위기가 아주 긴장돼요. (힌트: 시민군 등장, 도청, 총 든 시민, 광주 지키기)",
225
  "info_518_t4_opt2_got": "새로운 사실: 총을 든 한 청년이 말했어요. '우리 가족과 친구들이 군인들에게 맞아 죽는 걸 더는 볼 수 없었어요. 우리도 살기 위해 싸우는 거예요!' (힌트: 시민군 된 이유, 가족 보호, 살기 위한 싸움)",
226
  "info_518_t4_opt3_got": "새로운 사실: 병원에 총 맞은 사람들이 계속 실려오고 있어요. 의사, 간호사, 약품 모두 부족해요. '제발 도와주세요!' 하는 소리가 들려요. (힌트: 총상 환자 많음, 병원 부족, 도움 필요)",
227
- # Turn 5 (해방 광주와 시민 자치)
228
  "event_518_t5_assignment": "계엄군이 잠시 광주 외곽으로 물러나고, 시민들이 광주를 스스로 다스리고 있다는 소식이 있어요. 이 짧은 '해방 광주' 기간 동안 시민들은 어떻게 지내고 있는지, 질서는 잘 지켜지는지, 앞으로 뭘 걱정하는지 취재해주세요.",
229
  "event_518_t5_source": "[알아두면 좋아요] 시민들의 거센 저항에 밀려 계엄군이 5월 21일 광주 시내에서 철수했어요. 이후 며칠간 시민들은 스스로 질서를 유지하며 식량과 생필품을 나누고, 부상자를 돌봤어요. 하지만 계엄군이 다시 공격해올 거라는 불안감도 컸어요.",
230
  "action_518_t5_opt1_text": "시민들이 모여 회의하는 곳(도청 광장 등)에 가보기",
@@ -233,7 +216,6 @@ ALL_TEXTS = {
233
  "info_518_t5_opt1_got": "새로운 사실: 도청 광장에서 시민들이 모여 앞으로 어떻게 할지 이야기하고 있어요. '우리의 요구를 정부에 알려야 한다', '끝까지 싸우자' 같은 목소리가 나와요. (힌트: 시민 회의, 도청 광장, 요구 전달, 계속 싸우자)",
234
  "info_518_t5_opt2_got": "새로운 사실: 한 상인이 말���어요. '군인들이 없으니 잠시 평화롭지만, 언제 다시 쳐들어올지 몰라 무서워요. 제발 이 일이 빨리 해결됐으면 좋겠어요.' (힌트: 잠시 평화, 다시 공격 걱정, 빨리 해결되길 바람)",
235
  "info_518_t5_opt3_got": "새로운 사실: 아주머니들이 주먹밥을 만들어서 시민군과 배고픈 사람들에게 나눠주고 있어요. 서로 돕고 아끼는 모습이 감동적이에요. (힌트: 시민들 서로 도움, 주먹밥 나눔, 감동적)",
236
- # Turn 6 (계엄군의 재진입 임박과 마지막 저항 준비)
237
  "event_518_t6_assignment": "계엄군이 다시 광주로 쳐들어올 거라는 소문이 파다해요. 시민들은 마지막까지 싸울 준비를 하고 있는 것 같아요. 도청을 중심으로 한 시민군의 상황과 광주 전체의 긴장된 분위기를 전해주세요. 매우 위험한 상황입니다.",
238
  "event_518_t6_source": "[알아두면 좋아요] '해방 광주'는 오래가지 못했어요. 신군부는 대규모 병력을 동원해 광주를 다시 점령할 계획을 세웠어요. 시민들은 이 사실을 알고 있었지만, 많은 이들이 끝까지 남아 광주를 지키려 했어요. 외부와의 통신은 거의 끊긴 상태예요.",
239
  "action_518_t6_opt1_text": "도청 주변 시민군들의 마지막 방어 준비 모습 살펴보기 (극도로 위험!)",
@@ -242,7 +224,6 @@ ALL_TEXTS = {
242
  "info_518_t6_opt1_got": "새로운 사실: 도청 주변에 시민군들이 바리케이드를 쌓고 무기를 점검하고 있어요. 표정은 굳어있지만, 눈빛은 결연해요. '광주는 우리가 지킨다!'는 말이 들려요. (힌트: 도청 방어 준비, 시민군 결의, 마지막 저항)",
243
  "info_518_t6_opt2_got": "새로운 사실: 어린 학생 시민군이 말했어요. '무섭지만 도망가지 않을 거예요. 여기서 죽더라도 광주를 지키고 싶어요.' 많은 사람들이 비장한 각오를 하고 있어요. (힌트: 남은 시민들 각오, 두려움과 용기, 광주 지키기)",
244
  "info_518_t6_opt3_got": "새로운 사실: 광주의 진실을 알리려는 일부 시민들이 몰래 외부로 편지나 사진을 보내려고 애쓰고 있어요. 하지만 군인들이 철저히 막고 있어서 쉽지 않아 보여요. (힌트: 진실 알리기 노력, 외부 연락 시도, 군인 통제)",
245
- # Turn 7 (5.27 새벽, 계엄군 도청 진압 작전)
246
  "event_518_t7_assignment": "5월 27일 새벽, 결국 계엄군이 탱크를 앞세우고 도청으로 쳐들어왔어요. 마지막까지 저항하던 시민군과 계엄군 사이에 큰 전투가 벌어지고 있어요. 이 비극적인 상황을 기록해야 합니다. 안전을 최우선으로 하세요.",
247
  "event_518_t7_source": "[알아두면 좋아요] 5월 27일 새벽, 계엄군은 '상무충정작전'이라는 이름으로 전남도청을 무력으로 점령했어요. 도청을 사수하던 많은 시민군이 이 과정에서 희생되었어요. 이로써 열흘간의 광주민주화운동은 비극적으로 막을 내리게 됩니다.",
248
  "action_518_t7_opt1_text": "도청 근처 안전한 곳에서 총소리와 상황 파악하기 (매우 위험!)",
@@ -251,7 +232,6 @@ ALL_TEXTS = {
251
  "info_518_t7_opt1_got": "새로운 사실: 새벽부터 도청 쪽에서 총소리가 쉴 새 없이 들려요. 탱크 소리도 들리고, 하늘에는 헬리콥터가 날아다녀요. 마치 전쟁터 같아요. (힌트: 도청 진압, 총소리, 탱크, 전쟁터)",
252
  "info_518_t7_opt2_got": "새로운 사실: 날이 밝자 군인들이 도청을 완전히 장악했어요. 거리에는 군인들만 보이고, 시민들은 두려움에 떨며 숨어있어요. 광주 전체가 슬픔과 절망에 빠졌어요. (힌트: 군인들 도청 장악, 시민들 공포, 슬픔과 절망)",
253
  "info_518_t7_opt3_got": "새로운 사실: 병원에는 새벽 전투로 다치거나 죽은 시민군들이 계속 들어오고 있어요. 가족들의 울음소리가 끊이지 않아요. 너무나 많은 희생자가 나왔어요. (힌트: 많은 사상자, 병원 비상, 가족들 슬픔)",
254
- # Turn 8 (항쟁 이후, 남겨진 이야기들)
255
  "event_518_t8_assignment": "광주에서의 큰 싸움은 끝났지만, 슬픔과 아픔은 계속되고 있어요. 살아남은 사람들의 이야기, 숨겨진 진실, 그리고 앞으로 광주가 어떻게 될지 마지막으로 취재해서 알려주세요.",
256
  "event_518_t8_source": "[알아두면 좋아요] 5.18 광주민주화운동은 비록 군인들에게 진압되었지만, 이후 한국 민주주의 발전에 큰 영향을 주었어요. 하지만 오랫동안 진실이 제대로 알려지지 않아 많은 사람들이 아픔을 겪었어요.",
257
  "action_518_t8_opt1_text": "희생자 가족이나 살아남은 시민군을 만나 이야기 듣기",
@@ -260,8 +240,7 @@ ALL_TEXTS = {
260
  "info_518_t8_opt2_got": "새로운 사실: 군인들이 시민들을 몰래 묻었다는 소문이 있어요. 정부는 사망자 수를 줄여서 발표하고, 진실을 ���기려고 해요. 사람들은 언젠가 모든 것이 밝혀지길 바라고 있어요. (힌트: 숨겨진 진실, 정부의 은폐, 진실 규명 바람)",
261
 
262
  # --- 6월 항쟁 취재 시나리오 ---
263
- "scenario_june_struggle_name": "6월 항쟁 이야기 (1987년)", # 이 키는 이미 올바른 형식임
264
- # Turn 1 (박종철 고문치사 사건)
265
  "event_june_t1_assignment": "서울대학교 학생 박종철 군이 경찰 조사를 받다가 죽었어요. 경찰은 '책상을 탁 치니 억 하고 죽었다'고 이상하게 말했지만, 고문으로 죽었다는 의심이 커지고 있어요. 이 사건의 진짜 이유와 사람들의 반응을 알아보세요.",
266
  "event_june_t1_source": "[알아두면 좋아요] 1987년 1월 14일, 박종철 학생은 경찰서(남영동 대공분실)에서 조사를 받다가 죽었어요. 경찰이 이상하게 설명해서 사람들이 많이 화가 났고, 진짜 이유를 밝히라는 목소리가 커지고 있어요. 전두환 대통령 정부에게 큰 문제가 될 것 같아요.",
267
  "action_june_t1_opt1_text": "사건 담당 경찰서나 치안본부 근처에서 경찰들 이야기 몰래 듣기",
@@ -270,7 +249,6 @@ ALL_TEXTS = {
270
  "info_june_t1_opt1_got": "새로운 사실: 치안본부에서 일하는 사람이 몰래 말해줬어요. '높은 사람이 이 사건 빨리 덮으라고 시켰어요. 그냥 놀라서 죽었다고 하래요.' (힌트: 경찰 윗사람 지시, 사건 숨기려 함, 놀라서 죽었다고 거짓말)",
271
  "info_june_t1_opt2_got": "새로운 사실: 박종철 학생 아버지가 울면서 말했어요. '철아, 잘 가거라... 아빠는 할 말이 없다...' 친구들은 '고문해서 죽인 사람 벌주세요!' 하면서 화를 냈어요. (힌트: 박종철 가족 슬픔, 고문해서 죽였다고 화냄, 학생들 분노)",
272
  "info_june_t1_opt3_got": "새로운 사실: 박종철 학생 몸을 본 의사 선생님이 조심스럽게 말했어요. '목에 눌린 자국이 있고 폐에서 이상한 소리가 났어요. 그냥 놀라서 죽은 것 같지 않아요. 물고문했을 수도 있어요.' (힌트: 의사 선생님 증언, 물고문 의심, 경찰 말과 다름)",
273
- # Turn 2 (4.13 호헌 조치 발표와 민심 악화)
274
  "event_june_t2_assignment": "전두환 대통령이 '지금 헌법(대통령을 직접 뽑지 않는 법)을 바꾸지 않겠다'는 '4.13 호헌 조치'를 발표했어요. 많은 사람들이 대통령을 직접 뽑고 싶어 했는데, 이 발표 때문에 더 화가 난 것 같아요. 사람들의 반응과 앞으로 시위가 더 커질지 알아보세요.",
275
  "event_june_t2_source": "[알아두면 좋아요] 박종철 학생 사건으로 민주주의를 원하는 목소리가 커졌지만, 전두환 대통령은 4월 13일에 헌법을 고치지 않겠다고 발표했어요. 이건 국민들의 바람을 무시하는 거라서, 학생, 종교인, 일반 시민들까지 모두 크게 반발하고 있어요.",
276
  "action_june_t2_opt1_text": "대학교에 가서 학생들 반응과 시위 계획 알아보기",
@@ -279,7 +257,6 @@ ALL_TEXTS = {
279
  "info_june_t2_opt1_got": "새로운 사실: 대학교 학생들이 '독재 타도! 직선제 쟁취!' 같은 구호를 외치며 시위를 준비하고 있어요. '더 이상 참을 수 없다'며 격렬하게 싸울 거라고 해요. (힌트: 학생들 분노, 직선제 요구, 큰 시위 예고)",
280
  "info_june_t2_opt2_got": "새로운 사실: 한 신부님이 말했어요. '정부가 국민의 목소리를 듣지 않으니, 우리가 직접 나서서 민주주의를 되찾아야 합니다. 모든 양심 있는 사람들이 힘을 합칠 것입니다.' (힌트: 종교계 반발, 민주주의 되찾기, 힘 합치자)",
281
  "info_june_t2_opt3_got": "새로운 사실: 시장에서 만난 아주머니가 말했어요. '대통령을 내 손으로 뽑고 싶은데, 왜 못하게 하는지 모르겠어요. 너무 답답해요.' 많은 사람들이 실망하고 화가 나 있어요. (힌트: 시민들 실망, 직선제 바람, 답답함)",
282
- # Turn 3 (이한열 학생 피격 사건)
283
  "event_june_t3_assignment": "6월 9일, 연세대학교에서 시위하던 이한열 학생이 경찰이 쏜 최루탄에 머리를 맞아 쓰러졌어요. 지금 아주 위독하다고 해요. 이 사건 때문에 사람들이 더 크게 분노하고 있어요. 사건 현장 상황과 학생들, 시민들 반응을 긴급히 취재해주세요.",
284
  "event_june_t3_source": "[알아두면 좋아요] '4.13 호헌 조치' 이후 시위가 계속되던 중, 6월 9일 연세대 앞에서 이한열 학생이 경찰이 직격으로 쏜 최루탄에 맞아 의식을 잃었어요. 이 모습이 사진으로 알려지면서 국민들의 분노는 극에 달했고, 6월 항쟁이 전국적으로 확산되는 결정적인 계기가 되었어요.",
285
  "action_june_t3_opt1_text": "이한열 학생이 쓰러진 연세대 앞 시위 현장 가보기 (위험!)",
@@ -288,7 +265,6 @@ ALL_TEXTS = {
288
  "info_june_t3_opt1_got": "새로운 사실: 연세대 앞은 전쟁터 같아요. 학생들이 돌을 던지고, 경찰은 최루탄을 마구 쏘고 있어요. 이한열 학생이 쓰러졌던 자리에는 아직도 핏자국이 남아있어요. (힌트: 연세대 시위 격렬, 최루탄 난사, 이한열 학생 피격 현장)",
289
  "info_june_t3_opt2_got": "새로운 사실: 병원에서 만난 이한열 학생 친구들이 울면서 말했어요. '경찰이 한열이를 죽이려고 했어요! 이건 살인미수예요!' 학생은 의식이 없고 매우 위독한 상태라고 해요. (힌트: 이한열 학생 위독, 친구들 분노, 경찰 비판)",
290
  "info_june_t3_opt3_got": "새로운 사실: 명동성당 주변에 학생들이 모여들고 있어요. '이한열을 살려내라!', '군부독재 물러가라!' 외치고 있어요. 내일(6월 10일) 아주 큰 시위가 있을 거라는 소문이 돌아요. (힌트: 명동성당 시위 준비, 이한열 살리자, 큰 시위 예고)",
291
- # Turn 4 (6.10 국민대회와 항쟁의 확산)
292
  "event_june_t4_assignment": "오늘 6월 10일, 전국에서 '박종철 고문살인 규탄 및 민주헌법 쟁취 국민대회'라는 아주 큰 시위가 열리고 있어요. 서울뿐 아니라 부산, 광주 등 다른 도시에서도 많은 사람들이 거리로 나왔다고 해요. 시위 규모와 모습, 경찰 대응, 그리고 '넥타이 부대'라고 불리는 회사원들 참여 모습 등을 취재해주세요.",
293
  "event_june_t4_source": "[알아두면 좋아요] 이한열 학생 사건은 6월 10일로 예정되어 있던 국민대회에 기름을 부었어요. 전국 주요 도시에서 수십만 명의 학생과 시민들이 거리로 쏟아져 나와 '호헌 철폐', '독재 타도'를 외쳤어요. 특히 평범한 회사원들(넥타이 부대)까지 시위에 참여하면서 항쟁은 더욱 커졌어요.",
294
  "action_june_t4_opt1_text": "서울 시청 앞이나 명동 등 주요 시위 현장 한복판에 가보기 (매우 위험!)",
@@ -297,7 +273,6 @@ ALL_TEXTS = {
297
  "info_june_t4_opt1_got": "새로운 사실: 서울 시내가 온통 시위하는 사람들로 가득 찼어요! 경찰이 최루탄을 쏘며 막고 있지만, 사람들은 물러서지 않고 '독재 타도!'를 외치고 있어요. 여기저기서 싸움이 벌어지고 있어요. (힌트: 6.10 국민대회, 대규모 시위, 경찰과 충돌, 독재 타도)",
298
  "info_june_t4_opt2_got": "새로운 사실: 양복 입은 회사원 아저씨가 말했어요. '더 이상 나라가 이렇게 되는 걸 보고만 있을 수 없어서 나왔습니다. 우리 아이들에게 부끄럽지 않은 나라를 만들어주고 싶어요.' (힌트: 넥타이 부대 참여, 민주주의 열망, 미래 세대 걱정)",
299
  "info_june_t4_opt3_got": "새로운 사실: 부산 특파원이 알려왔어요. '부산역 광장에도 수만 명이 모여 시위를 벌이고 있습니다. 경찰과 격렬하게 대치 중이고, 부상자도 나오고 있습니다.' 전국이 들끓고 있어요. (힌트: 전국적 시위, 부산 상황, 지방도 뜨거움)",
300
- # Turn 5 (명동성당 농성과 확산되는 민주화 요구)
301
  "event_june_t5_assignment": "시위대 중 일부가 명동성당으로 들어가 농성을 시작했어요. 명동성당은 시위대에게 안전한 곳이 되어주고 있는 것 같아요. 성당 안팎의 분위기, 농성하는 사람들의 요구, 그리고 정부가 어떻게 나올지 사람들의 예상을 취재해주세요.",
302
  "event_june_t5_source": "[알아두면 좋아요] 6월 항쟁 기간 동안 명동성당은 민주화 운동의 중요한 장소가 되었어요. 경찰의 폭력을 피해 많은 시위대가 성당으로 들어와 농성을 벌였고, 종교계는 이들을 보호했어요. 이는 정부에게 큰 부담을 주었어요.",
303
  "action_june_t5_opt1_text": "명동성당 안으로 들어가 농성 중인 학생이나 시민들 만나보기",
@@ -306,7 +281,6 @@ ALL_TEXTS = {
306
  "info_june_t5_opt1_got": "새로운 사실: 명동성당 안은 학생들과 시민들로 가득해요. 지쳤지만 눈빛은 살아있어요. '대통령 직선제 실시하라!', '민주정부 수립하자!' 같은 구호를 외치고 있어요. (힌트: 명동성당 농성, 직선제 요구, 민주정부 희망)",
307
  "info_june_t5_opt2_got": "새로운 사실: 성당 밖에서 한 수녀님이 기도하며 말했어요. '저들이 평화롭게 자기 목소리를 낼 수 있도록, 그리고 아무도 다치지 않도록 기도하고 있어요. 정의가 이길 거예요.' (힌트: 성직자 지지, 평화 기원, 정의 승리 믿음)",
308
  "info_june_t5_opt3_got": "새로운 사실: 경찰 관계자가 몰래 말했어요. '성당 안으로 함부로 들어갈 수가 없어서 골치 아파요. 하지만 계속 저렇게 둘 수는 없을 텐데...' 정부도 고민이 많은 것 같아요. (힌트: 경찰 고민, 성당 진입 어려움, 정부 압박감)",
309
- # Turn 6 (6.26 평화대행진과 최루탄 없는 날)
310
  "event_june_t6_assignment": "오늘은 '국민평화대행진'이 있는 날이에요. 전국적으로 100만 명이 넘는 사람들이 거리로 나올 거라고 해요. 특히 오늘은 경찰이 최루탄을 쏘지 않기로 했다는 소문도 있어요. 정말 평화로운 시위가 될지, 사람들의 열기는 어떨지 현장에서 확인해주세요.",
311
  "event_june_t6_source": "[알아두면 좋아요] 6월 항쟁이 계속되면서 국민들의 민주화 요구는 더욱 거세졌어요. 6월 26일에는 전국 33개 도시에서 100만 명이 넘는 시민들이 참여하는 '국민평화대행진'이 계획되었어요. 정부도 더 이상 강경 대응만으로는 사태를 해결할 수 없다는 것을 느끼기 시작했어요.",
312
  "action_june_t6_opt1_text": "서울 도심 평화대행진 행렬에 참여해서 시민들과 함께 걷기",
@@ -315,7 +289,6 @@ ALL_TEXTS = {
315
  "info_june_t6_opt1_got": "새로운 사실: 정말 많은 사람들이 거리로 나왔어요! 아이 손을 잡고 나온 가족, 나이 드신 할아버지 할머니까지 모두 함께 '민주주의'를 외치며 걷고 있어요. (힌트: 6.26 평화대행진, 엄청난 인파, 다양한 시민 참여)",
316
  "info_june_t6_opt2_got": "새로운 사실: 신기하게도 오늘은 경찰이 최루탄을 쏘지 않아요! 시위는 아주 평화롭고 질서있게 진행되고 있어요. 마치 축제 같아요. 사람들은 노래도 부르고 춤도 춰요. (힌트: 최루탄 없는 날, 평화 시위, 축제 분위기)",
317
  "info_june_t6_opt3_got": "새로운 사실: 한 초등학생이 아빠 목마를 타고 말했어요. '우리나라가 더 좋은 나라가 됐으면 좋겠어요!' 어른들은 이 모습을 보며 눈물을 글썽였어요. (힌트: 미래세대 희망, 감동적인 모습, 좋은 나라 염원)",
318
- # Turn 7 (6.29 선언 발표)
319
  "event_june_t7_assignment": "오늘, 정부 여당의 노태우 대표가 갑자기 '6.29 선언'이라는 것을 발표했어요! 대통령 직선제를 받아들이고, 김대중 씨도 풀어주겠다는 등 놀라운 내용이 많다고 해요. 이 발표 내용과 사람들의 반응, 그리고 진짜로 민주주의가 올지 마지막으로 취재해주세요. (이번엔 취재 활동 없이 바로 기사 쓰기로 가요.)",
320
  "event_june_t7_source": "[긴급 뉴스] 6월 29일, 민정당 노태우 대표가 국민들의 민주화 요구를 받아들여 대통령 직선제 개헌, 김대중 사면복권 등 8개 항목의 시국 수습 방안을 발표했어요. 이것은 사실상 국민들의 승리를 의미해요!",
321
  "action_june_t7_opt1_text": "6.29 선언 내용 자세히 살펴보고 중요한 점 정리하기",
@@ -576,7 +549,6 @@ def process_reporter_action(selected_option, game_state):
576
  status['reporter_safety'] = max(0, min(100, status['reporter_safety']))
577
 
578
  st.session_state['actions_taken_this_turn'] += 1
579
- return info_text
580
 
581
  # --- 기사 작성 인터페이스 생성 ---
582
  def generate_article_interface(game_state):
@@ -587,13 +559,13 @@ def generate_article_interface(game_state):
587
  for idx, note in enumerate(game_state['reporter_notebook']):
588
  st.markdown(f"- {note}")
589
  else:
590
- st.caption("아직 취재한 내용이 없어요. 취재 활동을 해서 정보를 모아보세요.")
591
 
592
  st.markdown("---")
593
 
594
  with st.form(key="article_form"):
595
  article_headline = st.text_input(get_text_func("article_headline_label"), placeholder="예: 나쁜 선거, 그 비밀을 밝힌다!")
596
- article_body_summary = st.text_area(get_text_func("article_body_label"), height=150, placeholder="예: 오늘 대통령 뽑는 날, 나쁜 사람들이 몰래 표를 바꿨어요. 사람들이 화가 많이 났어요...")
597
 
598
  article_tones = {
599
  "fact_based": get_text_func("article_tone_fact_based"),
@@ -613,18 +585,12 @@ def generate_article_interface(game_state):
613
  if not article_headline or not article_body_summary:
614
  st.warning(get_text_func("warning_empty_article"))
615
  return None
616
-
617
  if not game_state['reporter_notebook']:
618
- st.warning("취재 노트에 내용이 없어요. 조금이라도 알아낸 게 있어야 기사를 쓸 수 있어요.")
619
  return None
620
-
621
  return {
622
- "turn": game_state['current_turn'],
623
- "headline": article_headline,
624
- "body_summary": article_body_summary,
625
- "tone": selected_tone_key,
626
- "raw_notes": list(game_state['reporter_notebook']),
627
- "ai_score": 0
628
  }
629
  return None
630
 
@@ -632,89 +598,52 @@ def generate_article_interface(game_state):
632
  def evaluate_article_and_get_feedback_openai(article, game_state, assignment_data):
633
  status = game_state['status']
634
  get_text_func = lambda k: get_text(k)
635
-
636
  current_assignment_text = assignment_data["assignment_text"]
637
  reporter_notes_str = "\n".join([f"- {note}" for note in article['raw_notes']])
638
  article_tone_text = get_text_func(f"article_tone_{article['tone']}")
639
 
640
  prompt = f"""
641
- 당신은 어린이 신문사의 따뜻하면서도 명철한 편집장입니다. 당신의 목표는 새내기 기자가 최고의 기사를 쓸 수 있도록 돕는 것입니다.
642
- 이 기자는 초등학생 독자들도 이해할 수 있는 글을 쓰려고 노력하고 있습니다. 칭찬할 부분은 구체적으로 언급하여 격려하고, 개선이 필요한 부분은 명확한 근거와 함께 친절하게 설명해주세요.
643
- 피드백은 기자가 **어떤 부분을 잘했고, 어떤 부분을 왜, 어떻게 개선해야 하는지** 명확히 이해하도록 돕는 데 초점을 맞춥니다.
644
-
645
- [오늘의 할 일 (취재 지시)]
646
- {current_assignment_text}
647
-
648
- [기자가 적은 내용 (취재 노트)]
649
- {reporter_notes_str}
650
-
651
- [기자가 쓴 기사]
652
- - 제목: {article['headline']}
653
- - 내용 요약: {article['body_summary']}
654
- - 선택한 분위기: {article_tone_text}
655
-
656
- [피드백 작성 가이드]
657
- 1. **칭찬과 개선점의 조화:** 잘한 점과 아쉬운 점을 균형 있게 언급해주세요.
658
- 2. **구체적인 인용:** 피드백 시, **기자가 작성한 제목, 내용 요약, 또는 취재 노트의 특정 부분을 직접 인용**하며 설명해주세요.
659
- 예: "제목에서 'OOO'라는 표현은 독자들의 호기심을 자극하는 좋은 시도예요." 또는 "내용 요약 중 'XXX' 부분은 YY라는 점에서 조금 아쉬워요. ZZZ처럼 바꿔보면 어떨까요?"
660
- 3. **초등학생 눈높이 고려:** 모든 설명은 초등학생 기자가 이해할 수 있도록 쉽고 명확해야 합니다.
661
-
662
- [평가 항목 피드백]
663
- 항목별로 점수를 부여하고, 가이드에 따라 구체적인 피드백을 작성해주세요.
664
-
665
- 1. **내용의 정확성, 중요도 깊이 (40점 만점):**
666
- * 취재 노트의 핵심 정보와 취재 지시의 요구사항이 기사에 정확하고 충분히 반영되었나요?
667
- * 예: "취재 노트에 있는 'OOO' 정보는 매우 중요한데, 기사 내용 요약의 '...' 부분에서 이 점이 잘 드러나서 좋았어요." 또는 "취재 지시에서 요청한 'XXX' 내용이 기사 요약에 빠져있네요. 'YYY' 부분에 이 내용을 추가하면 기사가 더 풍부해질 거예요."
668
- * 단순 사실 나열을 넘어, 사건의 의미나 배경에 대한 고민이 담겨 있나요? (초등학생 눈높이에서)
669
- * 예: "내용 요약 중 '...' 부분은 사건의 결과를 잘 설명했지만, 왜 그런 결과가 나왔는지에 대한 배경 설명이 추가되면 독자들이 더 깊이 이해할 수 있을 거예요."
670
- * 불필요하거나 중요도가 낮은 내용이 포함되지는 않았나요? 혹은 중요한 내용이 누락되지는 않았나요?
671
- * 예: "기사 요약의 '...' 부분은 재미있지만, 지금 다루는 주제와는 거리가 있어 보여요. 대신 취재 노트에 있는 'OOO' 내용을 넣어보는 건 어떨까요?"
672
-
673
- 2. **논리적 흐름, 명확성 및 어휘 수준 (30점 만점):**
674
- * 기사의 논리가 명확하고, 문장 간 연결이 자연스러운가요?
675
- * 예: "내용 요약에서 '...' 문장 다음에 '...' 문장이 이어지는 부분이 조금 갑작스러워요. 사이에 '그래서'나 '왜냐하면' 같은 연결어를 넣어주면 흐름이 더 자연스러워질 거예요."
676
- * 초등학생 독자가 이해하기 어려운 단어나 복잡한 문장 구조는 없나요? 있다면 구체적으로 지적하고, 쉬운 대안을 제시해주세요.
677
- * 예: "제목에 쓰인 '유비무환'이라는 단어는 초등학생에게 조금 어려울 수 있어요. '미리 준비하면 걱정이 없어요'처럼 풀어서 설명하거나, '철저한 준비' 같이 더 쉬운 단어로 바꾸는 것을 추천해요."
678
- * 예: "내용 요약 중 '...' 문장은 내용이 좋지만 조금 길어서 이해하기 어려울 수 있어요. 두 문장으로 나눠서 '...' 하고, 그 다음에 '...' 라고 설명하면 더 명확해질 거예요."
679
- * 주장이나 설명에 대한 근거가 명확한가요?
680
- * 예: "기사 요약에서 '...라고 생각한다'고 했는데, 왜 그렇게 생각하는지에 대한 이유를 취재 노트의 'OOO' 내용을 바탕으로 설명해주면 더욱 설득력이 있을 거예요."
681
-
682
- 3. **기사 분위기의 적절성, 객관성 및 잠재적 영향 (30점 만점):**
683
- * 선택한 기사 분위기가 사건의 본질과 기사 내용에 부합하나요? 감정에 치우치지 않고 객관성을 유지했나요?
684
- * 예: "선택한 '{article_tone_text}' 분위기는 이번 사건을 다루기에 아주 적절했어요. 특히 내용 요약의 '...' 부분에서 그 분위기가 잘 느껴져서 독자들이 사건에 몰입하기 좋았을 거예요."
685
- * 예: "내용 요약 중 '정말 최악이다'와 같은 표현은 기자의 감정이 너무 많이 들어간 것 같아요. '{article_tone_text}' 분위기를 선택했지만, 조금 더 객관적으로 '매우 아쉬운 상황이다' 정도로 표현하는 것이 어떨까요?"
686
- * 기사가 독자에게 미칠 영향을 고려했나요?
687
- * 예: "이 기사는 독자들이 'OOO'에 대해 다시 한번 생각해보는 좋은 계기가 될 것 같아요. 특히 '...' 부분은 독자들에게 긍정적인 영향을 줄 수 있겠네요."
688
- * 예: "기사 내용이 다소 비판적일 수 있는데, 내용 요약의 '...' 부분은 자칫 오해를 불러일으킬 수도 있겠어요. 독자들이 균형 잡힌 시각을 가질 수 있도록 '...'와 같은 내용을 추가하는 것을 고려해보세요."
689
-
690
- [총평 및 최종 조언]
691
- 각 항목별 점수와 피드백을 바탕으로 총점(100점 만점)을 계산하고, "overall_feedback"에는 기사의 전반적인 강점과 개선점을 균형 있게 요약하여 전달합니다.
692
- **칭찬할 부분은 구체적으로 언급하고, 개선이 필요한 부분은 기자가 다음 기사에서 더욱 발전할 수 있도록 명확하고 건설적인 조언을 담아주세요.**
693
- 예시: "이번 기사는 [구체적인 칭찬 내용, 예: '제목의 OOO 표현' 또는 '내용 요약의 XXX 부분']에서 기자님의 고민과 성장이 엿보여 정말 좋았어요. 다만, [가장 개선이 필요한 부분, 예: '논리적 연결' 또는 '어휘 선택']에 대해서는 조금 더 신경 써주면 훨씬 훌륭한 기사가 될 거예요. 특히 [가장 중요한 개선점 한 가지]를 다음 취재 때 꼭 기억해주세요!"
694
-
695
- 반드시 아래 JSON 형식으로 응답해주세요:
696
- {{
697
- "score_fact": 점수(숫자),
698
- "comment_fact": "내용의 정확성, 중요도, 깊이에 대한 구체적이고 건설적인 피드백 (문자열, 실제 작성 내용 인용 포함)",
699
- "score_logic": 점수(숫자),
700
- "comment_logic": "논리적 흐름, 명확성, 어휘 수준에 대한 구체적이고 건설적인 피드백 (문자열, 실제 작성 내용 인용 포함)",
701
- "score_tone": 점수(숫자),
702
- "comment_tone": "기사 분위기의 적절성, 객관성, 영향에 대한 구체적이고 건설적인 피드백 (문자열, 실제 작성 내용 인용 포함)",
703
- "total_score": 총점(숫자),
704
- "overall_feedback": "기사의 전반적인 강점과 개선 방향에 대한 따뜻하지만 명확한 조언 (문자열, 칭찬과 개선점 균형있게)"
705
- }}
706
- """
707
  try:
708
  with st.spinner("AI 편집장님이 기사를 꼼꼼히 검토하고 있습니다..."):
709
  response = client.chat.completions.create(
710
  model="gpt-4o-mini",
711
  messages=[{"role": "user", "content": prompt}],
712
  response_format={"type": "json_object"},
713
- temperature=0.1,
714
- max_tokens=2500
715
  )
716
- ai_evaluation_str = response.choices[0].message.content
717
- ai_evaluation = json.loads(ai_evaluation_str)
718
  total_score = ai_evaluation.get("total_score", 0)
719
  overall_feedback = ai_evaluation.get("overall_feedback", "AI 편집장 연결 오류로 자동 평가되었습니다.")
720
  except Exception as e:
@@ -751,77 +680,58 @@ def evaluate_article_and_get_feedback_openai(article, game_state, assignment_dat
751
 
752
  # --- UI 표시 함수들 ---
753
  def display_reporter_dashboard(game_state):
754
- get_text_for_ui = lambda k: get_text(k)
755
  status = game_state['status']
756
  avg_score = (status['article_score_total'] / status['article_count']) if status['article_count'] > 0 else 0
757
- col1, col2 = st.columns(2)
758
- col3, col4 = st.columns(2)
759
- with col1: st.metric(get_text_for_ui("term_public_trust"), f"{status['public_trust']}%")
760
- with col2: st.metric(get_text_for_ui("term_press_freedom"), f"{status['press_freedom']}%")
761
- with col3: st.metric(get_text_for_ui("term_reporter_safety"), f"{status['reporter_safety']}%")
762
- with col4: st.metric(get_text_for_ui("term_article_score_avg"), f"{avg_score:.1f}점")
763
-
764
- # [버그 수정] display_historical_glossary_for_reporter 함수
765
- def display_historical_glossary_for_reporter(scenario_key):
766
- get_text_for_ui = lambda k: get_text(k)
767
- st.subheader(get_text_for_ui("sidebar_glossary_title"))
768
-
769
- # scenario_key에 '.'이 포함된 경우(예: 4.19_revolution) '_'로 치환하여 키 접두사를 만듦
770
  prefix_key = scenario_key.replace('.', '_')
771
  glossary_prefix = f'glossary_{prefix_key}_'
772
-
773
- glossary_keys_for_scenario = [k for k in ALL_TEXTS if k.startswith(glossary_prefix)]
774
-
775
- if not glossary_keys_for_scenario:
776
- st.caption(f"이 시대의 용어 정보가 아직 없어요.")
777
  else:
778
- for key in sorted(glossary_keys_for_scenario): # 가나다순 정렬을 위해 sorted 추가
779
- term_definition = get_text_for_ui(key)
780
- st.markdown(term_definition)
781
 
782
  def display_final_results(game_state):
783
- get_text_main = lambda key: get_text(key)
784
  st.balloons()
785
- st.header(get_text_main("assignment_over_title"))
786
- st.subheader(get_text_main("assignment_over_subtitle"))
787
 
788
  with st.container(border=True):
789
- st.markdown("#### 🏆 최종 결과")
790
  display_reporter_dashboard(game_state)
791
 
792
- st.markdown("---")
793
  with st.container(border=True):
794
- st.markdown("#### 🗞️ 내가 보낸 주요 기사들")
795
  if game_state['submitted_articles']:
796
  for article in game_state['submitted_articles']:
797
- tone_text_key = f"article_tone_{article['tone']}"
798
- tone_display_text = get_text_main(tone_text_key)
799
- ai_score = article.get('ai_score', '점수 없음')
800
- st.markdown(f"**{article['turn']}번째 날:** \"{article['headline']}\" (분위기: {tone_display_text}, AI 점수: **{ai_score}점**)")
801
  else:
802
  st.caption("이번 취재 동안 보낸 기사가 없어요.")
803
 
804
- with st.expander("📖 모든 취재 기록 보기"):
805
- log_text = "\n".join(game_state.get('event_log', [])[::-1])
806
- st.text_area("로그 내용", log_text, height=300, disabled=True, key="final_log_reporter_main")
807
-
808
  # --- 세션 상태 초기화 ---
809
- if 'game_mode' not in st.session_state: st.session_state.game_mode = 'scenario_select'
810
- if 'current_scenario_key' not in st.session_state: st.session_state.current_scenario_key = None
811
- if 'game_state' not in st.session_state: st.session_state.game_state = None
812
- if 'current_assignment_data' not in st.session_state: st.session_state.current_assignment_data = None
813
- if 'actions_taken_this_turn' not in st.session_state: st.session_state.actions_taken_this_turn = 0
814
- if 'desk_feedback_message' not in st.session_state: st.session_state.desk_feedback_message = None
815
- if 'active_main_tab' not in st.session_state: st.session_state.active_main_tab = "오늘 할 일 보기"
816
 
817
  # --- 메인 게임 로직 ---
818
  def reporter_simulation_main():
819
- get_text_main = lambda key: get_text(key)
820
- st.title(get_text_main("game_title"))
821
 
822
  # --- 시나리오 선택 화면 ---
823
  if st.session_state.game_mode == 'scenario_select':
824
- st.header(get_text_main("scenario_select_title"))
825
  st.write("기자가 되어 우리나라의 중요한 역사적 순간으로 시간 여행을 떠나보세요!")
826
  st.divider()
827
  scenario_descriptions = {
@@ -829,158 +739,127 @@ def reporter_simulation_main():
829
  "5.18_gwangju": "1980년 5월, 광주라는 도시에서 아주 슬픈 일이 있었어요. 용감한 기자가 되어서 그곳 사람들의 이야기를 듣고 진실을 알려야 해요. (조금 무섭거나 슬픈 내용이 나올 수 있어요.)",
830
  "june_struggle": "1987년, 우리나라 사람들이 '우리 손으로 대통령을 뽑고 싶다!'고 외쳤던 때예요. 사회부 기자가 되어서 뜨거운 현장의 목소리를 담아보세요."
831
  }
832
- for key, scenario_info in SCENARIOS.items():
833
  with st.container(border=True):
834
- st.subheader(get_text_main(scenario_info["display_name"]))
835
- st.caption(f"🕰️ **언제:** {scenario_info['start_year']}년 | 🧑‍💼 **나는 누구?:** {scenario_info['player_role']}")
836
- st.markdown(scenario_descriptions.get(key, "이 시대에는 어떤 일이 있었을까요?"))
837
- if st.button(get_text_main("scenario_select_button"), key=f"select_{key}", use_container_width=True):
838
- st.session_state.current_scenario_key = key
839
  st.session_state.game_state = initialize_reporter_scenario_state(key)
840
- st.session_state.game_mode = 'assignment_briefing'
841
  st.rerun()
842
  st.stop()
843
 
844
- # --- 게임 진행 화면 (3단 컬럼) ---
845
- if st.session_state.game_mode != 'scenario_select' and st.session_state.game_state:
846
- game_state = st.session_state.game_state
847
- scenario_key = st.session_state.current_scenario_key
848
-
849
- # --- 취재 기간 종료 처리 ---
850
- if st.session_state.game_mode == 'assignment_over':
851
- display_final_results(game_state)
852
- if st.button(get_text_main("button_restart_assignment"), key="restart_assignment_main_btn", use_container_width=True):
853
- st.session_state.game_state = initialize_reporter_scenario_state(scenario_key)
854
- st.session_state.game_mode = 'assignment_briefing'
855
- st.rerun()
856
- st.stop()
857
-
858
- # --- 새 턴 시작 시 데이터 로딩 ---
859
- if st.session_state.game_mode == 'assignment_briefing':
860
- spinner_text = get_text_main('status_loading_assignment').format(year=game_state['game_year'], turn=game_state['current_turn'])
861
- with st.spinner(spinner_text):
862
- time.sleep(0.5)
863
- assignment = get_next_assignment(scenario_key, game_state['current_turn'], game_state)
864
- if assignment:
865
- st.session_state.current_assignment_data = assignment
866
- st.session_state.actions_taken_this_turn = 0
867
- st.session_state.desk_feedback_message = None
868
- st.session_state.game_mode = 'reporter_action'
869
- st.session_state.active_main_tab = get_text_main("reporter_actions_title")
870
- else:
871
- st.session_state.game_mode = 'assignment_over'
872
- game_state['event_log'].append(get_text_main("log_assignment_over").format(scenario_name=get_text_main(SCENARIOS[scenario_key]['display_name'])))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
873
  st.rerun()
874
 
875
- # --- 3단 컬럼 레이아웃 정의 ---
876
- col1, col2, col3 = st.columns([2.5, 5, 2.5], gap="large")
877
 
878
- # --- 왼쪽 컬럼: 상태 제어 ---
879
- with col1:
880
- st.markdown(f"### {get_text_main(SCENARIOS[scenario_key]['display_name'])}")
881
- st.caption(f"**역할:** {game_state['player_role']}")
882
- st.markdown(f"#### {get_text_main('dashboard_term').format(year=game_state['game_year'], turn=game_state['current_turn'])}")
883
-
884
- with st.container(border=True):
885
- display_reporter_dashboard(game_state)
886
-
887
- st.divider()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
888
 
889
- can_proceed = st.session_state.game_mode != 'article_writing' and st.session_state.actions_taken_this_turn >= ACTIONS_PER_TURN_LIMIT
890
- if st.button(get_text_main("button_next_day"), use_container_width=True, disabled=not can_proceed, type="primary"):
891
  if game_state['current_turn'] >= game_state['max_turns']:
892
  st.session_state.game_mode = 'assignment_over'
893
  else:
894
  game_state['current_turn'] += 1
895
- st.session_state.game_mode = 'assignment_briefing'
896
  st.rerun()
897
 
898
- if st.button(get_text_main("button_back_to_scenario_select"), use_container_width=True):
899
- st.session_state.game_mode = 'scenario_select'
900
- st.rerun()
901
-
902
- # --- 중앙 컬럼: 메인 활동 ---
903
- with col2:
904
- assignment_data = st.session_state.current_assignment_data
905
- if assignment_data:
906
- with st.container(border=True):
907
- st.markdown(f"### {get_text_main('current_assignment_title')}")
908
- st.write(assignment_data['assignment_text'])
909
- st.divider()
910
-
911
- tab_titles = [get_text_main("reporter_actions_title")]
912
- if assignment_data.get("article_writing_phase"):
913
- tab_titles.append(get_text_main("article_writing_title"))
914
- if st.session_state.desk_feedback_message:
915
- tab_titles.append(get_text_main("desk_feedback_title"))
916
-
917
- tabs_ui = st.tabs(tab_titles)
918
-
919
- with tabs_ui[0]: # 무엇을 할까요?
920
- if st.session_state.actions_taken_this_turn < ACTIONS_PER_TURN_LIMIT:
921
- st.info(f"남은 활동 횟수: **{ACTIONS_PER_TURN_LIMIT - st.session_state.actions_taken_this_turn}번**")
922
- for i, opt in enumerate(assignment_data['options']):
923
- risk_score = opt.get('cost_freedom_risk',0) + opt.get('safety_risk',0)
924
- risk_str = "🚨 매우 위험!" if risk_score > 40 else "⚠️ 조금 위험" if risk_score > 0 else "👍 안전함"
925
- if st.button(get_text_main("action_button_label").format(action=opt['action_text'], risk_str=risk_str), key=f"action_{i}", use_container_width=True):
926
- process_reporter_action(opt, game_state)
927
- st.rerun()
928
- else:
929
- st.success(get_text_main("status_actions_taken"))
930
-
931
- if get_text_main("article_writing_title") in tab_titles:
932
- with tabs_ui[1]: # 기사 쓰기
933
- if st.session_state.actions_taken_this_turn >= ACTIONS_PER_TURN_LIMIT:
934
- st.session_state.game_mode = 'article_writing'
935
- submitted_article = generate_article_interface(game_state)
936
- if submitted_article:
937
- feedback = evaluate_article_and_get_feedback_openai(submitted_article, game_state, assignment_data)
938
- st.session_state.desk_feedback_message = feedback
939
- st.session_state.game_mode = 'reporter_action'
940
- st.rerun()
941
- else:
942
- st.info(f"취재 활동을 먼저 완료해주세요. (남은 활동: {ACTIONS_PER_TURN_LIMIT - st.session_state.actions_taken_this_turn}번)")
943
-
944
- if get_text_main("desk_feedback_title") in tab_titles:
945
- with tabs_ui[-1]: # 편집장 피드백
946
- st.info(f"**AI 편집장님:** {st.session_state.desk_feedback_message}")
947
- st.success("피드백을 확인했습니다. 왼쪽의 '다음 날로 가기' 버튼을 눌러주세요.")
948
-
949
- # --- 오른쪽 컬럼: 지원 정보 ---
950
- with col3:
951
- st.markdown("### 🔍 취재 지원 정보")
952
- assignment_data = st.session_state.current_assignment_data
953
- if assignment_data and assignment_data.get('source_text'):
954
- st.info(assignment_data['source_text'])
955
 
956
- st.divider()
 
957
 
958
- with st.container(border=True):
959
- display_historical_glossary_for_reporter(scenario_key)
960
-
961
- st.divider()
962
-
963
- with st.expander("💡 FAQ & 게임 팁"):
964
- st.markdown("""
965
- **Q. 이 게임은 무엇인가요?**
966
- A. 옛날 신문 기자가 되어서, 우리나라의 중요한 역사 속으로 들어가 직접 취재하고 기사를 써보는 게임이에요.
967
-
968
- **Q. 점수는 왜 자꾸 바뀌나요?**
969
- A. 위험한 곳을 취재하거나, 정부가 싫어하는 기사를 쓰면 '자유'나 '안전' 점수가 낮아질 수 있어요. 옛날 기자들의 어려움을 체험해보는 거예요.
970
-
971
- **Q. 기사는 어떻게 써야 점수가 높나요?**
972
- A. '내가 적은 내용'에 있는 힌트를 잘 활용하고, '오늘 할 일'에서 시킨 내용을 빠짐없이 담아보세요.
973
-
974
- **Q. 문제가 생기면 어떻게 해요?**
975
- A. **ll7098ll@bonggokcho.com (구미봉곡초 교사 이병민)** 으로 이메일을 보내주세요.
976
- """)
977
-
978
- # --- 게임 상태 오류 처리 ---
979
- elif st.session_state.game_mode != 'scenario_select' and not st.session_state.game_state:
980
- st.warning("게임 정보가 사라졌어요. 처음 화면으로 돌아갑니다.")
981
- time.sleep(2)
982
- st.session_state.game_mode = 'scenario_select'
983
- st.rerun()
984
 
985
  if __name__ == "__main__":
986
  reporter_simulation_main()
 
87
  "desk_feedback_title": "📢 AI 편집장님의 한마디",
88
  "status_loading_assignment": "{year}년 {turn}번째 날, 무슨 일이 있을까? 기다려주세요...",
89
  "status_actions_taken": "오늘 할 일을 다 했어요. 기사를 쓰거나 다음 날로 넘어가세요.",
 
90
  "sidebar_glossary_title": "📰 어려운 말/사람 이야기",
 
 
91
  "button_submit_article": "기사 보내기 (AI 편집장님께)",
92
  "article_headline_label": "기사 제목:",
93
  "article_body_label": "기사 내용 요약 (짧게 3~5줄):",
 
105
  "log_safety_change_article": " - 기자님 안전이 {change:+}만큼 바뀌었어요.",
106
  "log_assignment_over": "--- {scenario_name} 취재 끝 ---",
107
  "log_next_day_start": "--- {year}년 {turn}번째 날 시작 ---",
 
108
  "error_openai_api": "AI 편집장님 연결에 문제가 생겼어요: {error}",
109
 
110
  # --- 4.19 혁명 취재 시나리오 ---
111
+ "scenario_4.19_revolution_name": "4.19 혁명 이야기 (1960년)",
 
112
  "event_419_t1_assignment": "오늘은 3월 15일, 대통령과 부통령을 뽑는 날이에요. 투표하는 곳에서 나쁜 사람들이 규칙을 어기고 자기편만 뽑으려고 할지도 몰라요. 그런 이상한 점을 찾아내고, 투표를 지켜보는 사람, 투표하는 사람, 선거를 관리하는 사람들에게 이야기를 들어보는 것이 오늘 할 일이에요. 특히 반대편 사람들이 잘 감시하는지, 힘 있는 쪽 사람들이 몰래 나쁜 일을 꾸미는지 잘 살펴보세요.",
113
  "event_419_t1_source": "[알아두면 좋아요] 지금 자유당이라는 당이 오랫동안 나라를 다스려서 사람들이 불만이 많아요. 이번 선거에서 이승만 대통령이 또 대통령이 되고, 이기붕 아저씨가 부통령이 되려고 자유당이 나쁜 방법을 쓸 거라는 소문이 많아요. 미리 투표한 표를 몰래 바꾸거나, 없는 사람 표를 넣거나, 여럿이 같이 보면서 투표하게 만들거나, 반대편 감시하는 사람들을 쫓아낸다는 이야기가 돌고 있어요.",
114
  "action_419_t1_opt1_text": "서울 투표하는 곳에 몰래 들어가서 사진 찍어보기",
 
117
  "info_419_t1_opt1_got": "새로운 사실: 종로 A투표소에서 자유당 표시를 한 사람들이 투표함에 표를 많이 넣는 걸 멀리서 봤어요. 가까이 가려니까 무섭게 쳐다봤어요. (힌트: 표 몰래 넣기, 자유당 표시, 무서움)",
118
  "info_419_t1_opt2_got": "새로운 사실: 민주당 쪽 감시원 박 아저씨가 화나서 말했어요. '성북 B투표소에서 경찰이 어떤 사람들 투표하는 곳까지 따라가서 누굴 찍는지 봤어요! 안 된다고 했는데 내 말을 안 들었어요!' 사진도 조금 찍었대요. (힌트: 경찰이 투표 방해, 감시원 말 무시, 민주당)",
119
  "info_419_t1_opt3_got": "새로운 사실: 이름을 밝히기 싫어하는 선거 관리 직원이 떨면서 말했어요. '오늘 새벽에 어떤 투표함들을 이상한 차가 가져가는 걸 봤어요. 너무 무서워요.' (힌트: 투표함 몰래 바꾼 듯, 선거 관리 직원 제보, 무서움)",
 
120
  "event_419_t2_assignment": "마산에서 나쁜 선거에 반대하며 시위하던 김주열 학생이 사라졌는데, 바다에서 슬픈 모습으로 발견됐어요. 왜 김주열 학생이 죽었는지, 경찰은 처음에 어떻게 했는지, 마산 사람들이 얼마나 화가 났는지 자세히 알아보세요.",
121
  "event_419_t2_source": "[알아두면 좋아요] 4월 11일, 마산 앞바다에서 눈에 최루탄이 박힌 김주열 학생의 모습은 사람들에게 큰 충격을 줬어요. 경찰은 처음엔 그냥 물에 빠져 죽었다고 하려 했지만, 모습이 알려지면서 거짓말 아니냐는 말이 많아졌어요. 마산은 이미 시위 때문에 분위기가 안 좋았어요.",
122
  "action_419_t2_opt1_text": "김주열 학생이 있는 병원에 가서 의사 선생님 만나보기",
 
125
  "info_419_t2_opt1_got": "새로운 사실: 병원 관계자가 몰래 말해줬어요. '김주열 학생은 최루탄 때문에 머리를 다쳐서 죽은 것 같아요. 경찰이 이걸 알리지 말라고 하고 있어요.' (힌트: 최루탄 때문에 죽음, 머리 다침, 경찰이 숨김)",
126
  "info_419_t2_opt2_got": "새로운 사실: 마산상고 학생들이 '친구를 살려내라!', '나쁜 경찰 혼내주자!' 외치며 경찰과 싸우고 있어요. 돌멩이랑 불도 던지고, 경찰��� 최루탄을 마구 쏴요. 다친 학생들이 많아요. (힌트: 마산 학생 시위, 경찰이 심하게 막음, 다친 사람 많음)",
127
  "info_419_t2_opt3_got": "새로운 사실: 김주열 학생 어머니가 울면서 말했어요. '우리 아들은 시위하러 간다고 하고 나갔어요. 경찰이 죽인 게 틀림없어요. 너무 억울해요.' (힌트: 김주열 가족, 경찰이 죽였다고 생각, 억울함)",
 
128
  "event_419_t3_assignment": "4월 18일, 나쁜 선거를 반대하는 시위를 마치고 학교로 돌아가던 고려대학교 학생들이 나쁜 아저씨들에게 맞았어요. 무슨 일이 있었는지, 경찰은 뭘 했는지, 다른 사람들은 어떻게 생각하는지 알아보세요.",
129
  "event_419_t3_source": "[알아두면 좋아요] 김주열 학생 일 때문에 학생들이 더 많이 시위하고 있는데, 이번엔 깡패 아저씨들이 나타나서 학생들을 때렸어요. 사람들이 더 화가 났어요. 경찰이 이걸 보고도 못 본 척한 거 아니냐는 말도 나와요.",
130
  "action_419_t3_opt1_text": "학생들이 맞은 곳과 다친 학생들이 있는 병원에 가보기",
 
133
  "info_419_t3_opt1_got": "새로운 사실: 다친 학생이 말했어요. '시위 끝나고 조용히 가는데 갑자기 쇠파이프 든 아저씨들이 때렸어요. 살려달라고 해도 마구 때렸어요.' 병원에는 다친 학생들이 많았어요. (힌트: 고려대생 맞음, 깡패, 쇠파이프, 단체로 때림)",
134
  "info_419_t3_opt2_got": "새로운 사실: 경찰 아저씨가 말했어요. '학생들끼리 싸운 것 같아요. 깡패가 있다는 건 그냥 소문이에요.' 더 조사할 생각은 없어 보였어요. (힌트: 경찰이 대충 조사, 그냥 싸웠다고 함, 뒤에 누가 있는지 모른 척)",
135
  "info_419_t3_opt3_got": "새로운 사실: 서울대 학생 대표가 말했어요. '이건 나쁜 테러예요! 나라에서 도와주지 않으면 불가능한 일이에요. 모든 학생이 힘을 합쳐 싸울 거예요!' (힌트: 다른 학생들도 화남, 나라가 뒤에 있다고 의심, 같이 싸우자)",
 
136
  "event_419_t4_assignment": "4월 19일, 서울에서 아주 큰 시위가 일어나서 대통령이 사는 경무대로 가고 있어요. 얼마나 많은 사람들이 모였는지, 뭘 원하는지, 경찰은 어떻게 하는지(총을 쏘는지 포함), 다치거나 죽은 사람은 없는지 빨리 알려야 해요. 아주 위험하니까 조심 또 조심하세요!",
137
  "event_419_t4_source": "[알아두면 좋아요] 고려대 학생들이 맞은 일 때문에 서울에 있는 대학생, 중고등학생, 어른들까지 거리로 나와서 '이승만 대통령 물러나라!', '나쁜 선거 다시 하자!' 외치면서 경무대로 가고 있어요. 경찰은 최루탄이랑 소방차로 막고 있지만 사람들이 너무 많아요.",
138
  "action_419_t4_opt1_text": "경무대 근처 시위대 맨 앞에 가서 직접 보기 (아주 위험!)",
 
141
  "info_419_t4_opt1_got": "새로운 사실: 시위대가 경찰 막는 걸 뚫고 경무대로 가려고 해요. 경찰이 시위대한테 마구 총을 쏘기 시작했어요! 눈앞에서 학생들이 피 흘리며 쓰러져요. 너무 무서운 현장이에요. (힌트: 경무대에서 총쏨, 마구 쏨, 학생들 죽음, 끔찍함)",
142
  "info_419_t4_opt2_got": "새로운 사실: 수만 명의 사람들이 태평로와 광화문을 꽉 채웠어요. 경찰이 최루탄이랑 진짜 총알을 쏘는 걸 봤어요. 길거리가 전쟁터 같아요. (힌트: 아주 큰 시위, 경찰이 진짜 총쏨, 전쟁터 같음)",
143
  "info_419_t4_opt3_got": "새로운 사실: 세브란스 병원 응급실에 총 맞은 사람들로 가득해요. 죽은 사람도 많아요. 의사 선생님들이 바쁘게 움직이지만 사람이 너무 많아요. '학생들이 죽어가고 있어요!' 하고 소리쳐요. (힌트: 총 맞은 환자, 많이 죽음, 병원도 힘듦, 의사 부족)",
 
144
  "event_419_t5_assignment": "정부가 서울이랑 다른 큰 도시에 '비상계엄'을 내렸어요. 군인들이 어디에 있는지, 사람들은 어떻게 생각하는지, 계엄령 아래서 신문이나 방송은 어떻게 되는지 알아보세요.",
145
  "event_419_t5_source": "[알아두면 좋아요] 4.19 시위가 너무 커지니까 정부가 4월 19일 오후 5시에 서울에 비상계엄을 내리고 군인들을 보냈어요. 그 후 부산, 대구, 광주 같은 큰 도시에도 계엄령이 내려졌어요. 계엄사령부는 모이거나 시위하는 걸 금지하고, 신문 기사도 미리 검사한다고 했어요.",
146
  "action_419_t5_opt1_text": "시내 중요 장소에 군인들이 있는지, 사람들 지나가는 거 검사하는지 보기",
 
149
  "info_419_t5_opt1_got": "새로운 사실: 탱크랑 장갑차를 탄 군인들이 길이랑 중요한 건물들을 지키고 있어요. 사람들이 마음대로 못 다니게 하고, 어떤 곳에서는 학생들을 막 잡아갔어요. (힌트: 군인이 도시 장악, 탱크 장갑차, 못 다니게 함, 강제로 잡아감)",
150
  "info_419_t5_opt2_got": "새로운 사실: 어떤 아저씨가 말했어요. '군인들이 총 들고 다니니까 무섭지만, 이렇게 나쁜 정치를 그냥 둘 수는 없어요. 기회가 되면 다시 시위할 거예요.' (힌트: 계엄령 속 사람들 마음, 무섭지만 싸우고 싶음, 나쁜 정치 싫음)",
151
  "info_419_t5_opt3_got": "새로운 사실: 계엄사령부에서 말했어요. '나라를 안전하게 하려고 신문 내용을 미리 검사할 거예요. 거짓 소문 퍼뜨리면 혼내줄 거예요.' 사실상 정부가 시키는 대로만 써야 해요. (힌트: 신문 검사, 정부 말만 쓰게 함, 계엄사령부, 정보 막음)",
 
152
  "event_419_t6_assignment": "4월 25일, 전국 대학교수님들이 '우리도 할 말이 있다!' 하면서 거리로 나왔어요. 교수님들이 뭘 원하는지, 얼마나 많이 모였는지, 정부랑 사람들은 어떻게 생각하는지 알아보세요.",
153
  "event_419_t6_source": "[알아두면 좋아요] 학생들이 피 흘리는 걸 보고 똑똑한 어른들도 화가 났어요. 서울대학교 교수님들을 시작으로 전국 27개 대학교 258명의 교수님들이 '학생들의 피에 보답하라!' 하면서 이승만 대통령 물러나고 정부도 다 그만두라고 외치며 거리로 나왔어요. 이건 정부에게 큰 충격이었어요.",
154
  "action_419_t6_opt1_text": "교수님들 시위하는 곳(국회의사당 앞 등)에 같이 가보기",
 
157
  "info_419_t6_opt1_got": "새로운 사실: 수백 명의 교수님들이 '이승만 물러나라', '민주주의 지키자' 같은 글을 들고 조용히 걸었어요. 사람들은 박수치고 응원했어요. 경찰도 전보다 덜 막았어요. (힌트: 교수님들 시위, 이승만 물러나라고 함, 사람들 응원, 조용한 시위)",
158
  "info_419_t6_opt2_got": "새로운 사실: 서울대 K교수님이 말했어요. '더 이상 나쁜 일을 보고만 있을 수 없었어요. 이 대통령은 빨리 물러나고, 민주주의를 다시 찾아야 해요.' (힌트: 교수님들 생각, 나쁜 일 못 참음, 민주주의 되찾자)",
159
  "info_419_t6_opt3_got": "새로운 사실: 시위 보던 어떤 아줌마가 울면서 말했어요. '교수님들까지 나오시니 이제 정말 이 정권 끝났어요. 우리 학생들, 사람들 힘내요!' (힌트: 사람들 감동, 교수님들 응원, 정권 끝날 것 같음)",
 
160
  "event_419_t7_assignment": "미국 정부가 지금 우리나라 상황이 걱정된다면서 이승만 대통령에게 중요한 결정을 하라고 했다는 소문이 있어요. 이승만 대통령 마음이 어떻게 변했는지, 정말 물러날 건지, 자유당 사람들은 어떻게 움직이는지 빨리 알아보세요.",
161
  "event_419_t7_source": "[알아두면 좋아요] 4.19 혁명이 커지니까 미국 정부가 우리나라에 있는 미국 대사를 통해 이승만 대통령에게 사실상 물러나라고 했어요. 외국에서도 외면받고, 나라 안에서도 사람들이 계속 반대하니까 이 대통령은 아주 중요한 결정을 해야 해요.",
162
  "action_419_t7_opt1_text": "경무대 근처에서 대통령 주변 사람들 어떻게 하는지 보기",
 
165
  "info_419_t7_opt1_got": "새로운 사실: 경무대에서 일하는 사람이 몰래 말해줬어요. '대통령님이 며칠 동안 잠도 못 자고 깊이 고민하고 계세요. 곧 아주 중요한 발표가 있을 거라는 소문이 많아요.' (힌트: 이승만 대통령 고민, 중요한 발표 곧 할 듯, 경무대 분위기 심각)",
166
  "info_419_t7_opt2_got": "새로운 사실: 자유당 국회의원 M아저씨가 말했어요. '이미 끝났어요. 대통령님이 멋있게 물러나시는 게 유일한 방법이에요. 우리 당 안에서도 물러나시라고 말해야 한다는 목소리가 커지고 있어요.' (힌트: 자유당도 물러나라고 함, 멋있게 그만두길 바람, 당 안에서도 의견 갈림)",
167
  "info_419_t7_opt3_got": "새로운 사실: 미국 대사관 사람이 몰래 말해줬어요. '미국 정부는 한국이 다시 민주주의를 찾고, 평화롭게 정권이 바뀌길 바라요. 지금 상황이 계속되는 건 좋지 않아요.' (힌트: 미국 정부 생각, 민주주의 되찾길 바람, 평화롭게 바뀌길 바람)",
 
168
  "event_419_t8_assignment": "4월 26일, 이승만 대통령이 물러나겠다고 발표했어요! 대통령이 뭐라고 말했는지, 사람들은 어떤 반응인지, 앞으로 나라는 어떻게 될지 다 합쳐서 특별 기사를 써야 해요. (이번엔 취재 활동 없이 바로 기사 쓰기로 가요.)",
169
  "event_419_t8_source": "[긴급 뉴스] 이승만 대통령, 국민들이 원해서 대통령 자리에서 물러나겠다고 발표. 라디오로 이야기했어요. 사람들이 거리로 나와서 기뻐하고 있어요. 12년 동안 계속된 자유당 정치가 끝났어요.",
170
  "action_419_t8_opt1_text": "대통령이 물러나면서 한 말 자세히 보기",
 
175
  "info_419_t8_opt3_got": "새로운 사실: 정치학자 P교수님이 말했어요. '허정 아저씨가 잠깐 나라를 맡고, 곧 국회의원 선거를 다시 할 것 같아요. 민주당이 중심이 돼서 나라를 다스릴 가능성이 높아요. 하지만 좀 시끄럽고 사람들이 원하는 게 많아질 수도 있어요.' (힌트: 허정 아저씨가 임시로 맡음, 다시 선거, 민주당 중심 정치, 좀 시끄러울 수도 있음)",
176
 
177
  # --- 5.18 광주 취재 시나리오 ---
178
+ "scenario_5.18_gwangju_name": "5.18 광주 이야기 (1980년)",
 
179
  "event_518_t1_assignment": "5월 17일 밤부터 '비상계엄'이 전국으로 커졌어요. 광주 분위기는 어떤지, 중요한 사람들(학생 대표, 숨어있는 어른들)은 어떻게 움직이는지, 군인들은 뭘 하는지 알아보고 알려주세요. 신문이나 방송을 못 믿게 하니까 몰래 조심해서 취재해야 해요.",
180
  "event_518_t1_source": "[알아두면 좋아요] 10.26 사건 뒤에 '서울의 봄'이라고 해서 좋은 세상이 올 것 같았지만, 새로운 군인 아저씨들이 12.12 군사반란으로 힘을 잡으면서 다시 무서워졌어요. 새 군인들은 나라가 시끄럽다면서 비상계엄을 전국으로 넓히고, 김대중, 김영삼 같은 유명한 정치인들을 잡아가거나 못 나오게 했어요. 광주 대학교에서는 학생들이 시위하려는 움직임이 보여요.",
181
  "action_518_t1_opt1_text": "전남대학교 같은 대학교 학생회관 근처에서 이야기 들어보기",
 
184
  "info_518_t1_opt1_got": "새로운 사실: 전남대 학생 대표들이 '계엄 확대는 나쁜 짓이다!' 하면서 내일(18일) 아침에 학교에서 시위할 계획이래요. '학교 문 닫지 마라, 계엄령 없애라!' 외칠 준비를 하고 있어요. (힌트: 전남대 학생 시위 예고, 계엄 반대, 학교 문 열라고 함)",
185
  "info_518_t1_opt2_got": "새로운 사실: 광주역, 버스터미널, 도청 같은 중요한 곳에 무서운 무기를 든 공수부대 군인들이 나타나기 시작했어요. 사람들은 무서워하고 불안해해요. (힌트: 공수부대 나타남, 무섭게 지킴, 사람들 불안)",
186
  "info_518_t1_opt3_got": "새로운 사실: 이름을 밝히기 싫어하는 종교 지도자가 한숨 쉬며 말했어요. '새 군인들이 자기들 마음대로 하려고 사람들을 아주 심하게 혼내줄 것 같아요. 광주가 큰일 날까 봐 걱정돼요.' (힌트: 새 군인들 무섭게 할 듯, 광주 걱정, 종교 어른 생각)",
 
187
  "event_518_t2_assignment": "5월 18일 아침, 전남대학교 앞에서 학생들과 군인들이 처음으로 싸웠어요. 왜 싸움이 났는지, 어떻게 싸웠는지, 학생들과 군인들은 얼마나 다쳤는지, 다른 사람들은 어떻게 생각하는지 빨리 알아보세요. 현장에 갈 땐 아주 조심해야 해요!",
188
  "event_518_t2_source": "[알아두면 좋아요] 어제(17일) 비상계엄이 전국으로 커지면서 대학교 문을 닫으라고 했지만, 전남대 학생들은 반대하면서 학교 문 앞에서 시위를 했어요. 계엄군(공수부대)은 이걸 아주 세게 막기 시작했어요.",
189
  "action_518_t2_opt1_text": "전남대학교 정문 앞 시위 현장에 직접 가보기 (아주 위험!)",
 
192
  "info_518_t2_opt1_got": "새로운 사실: 공수부대 군인들이 학교 문으로 들어가려는 학생들을 몽둥이로 마구 때리고 군홧발로 찼어요. 여자든 남자든 가리지 않고 때렸어요. 학생들이 피 흘리며 쓰러지고 끌려가는 걸 봤어요. (힌트: 공수부대 너무 심하게 때림, 마구 때림, 학생들 다침, 전남대 정문)",
193
  "info_518_t2_opt2_got": "새로운 사실: 병원 응급실에 머리나 뼈를 다친 학생들로 가득해요. 한 학생은 '그냥 학교에 들어가려고 했는데, 군인들이 갑자기 몽둥이로 때렸어요!' 하면서 울었어요. (힌트: 학생들 많이 다침, 병원 응급실, 군인이 때렸다고 함)",
194
  "info_518_t2_opt3_got": "새로운 사실: 근처 가게 주인이 화내면서 말했어요. '학생들이 뭘 그렇게 잘못했다고 저렇게까지 때리나. 이건 너무 심해요. 군인이 아니라 깡패 같아요!' (힌트: 사람들 화남, 군인들 나쁘다고 함, 너무 심하게 막는 거 봄)",
 
195
  "event_518_t3_assignment": "학생들 시위가 광주 시내 전체로 퍼지고 있어요. 일반 시민들도 함께하고 있어요. 하지만 공수부대 군인들이 더 잔인하게 사람들을 때리고 잡아가고 있다는 소문이 들려요. 이 상황을 자세히 취재해주세요. 정말 위험하니 몸조심하세요!",
196
  "event_518_t3_source": "[알아두면 좋아요] 전남대 앞에서 시작된 군인들의 폭력은 오히려 시민들의 분노를 키웠어요. 학생들뿐만 아니라 일반 시민들도 거리로 나와 '계엄 철폐', '살인마 전두환 물러가라' 등을 외치고 있어요. 공수부대는 시위대뿐 아니라 길 가던 사람들에게도 폭력을 행사하고 있다는 목격담이 나오고 있어요.",
197
  "action_518_t3_opt1_text": "금남로 등 시위가 격렬한 곳으로 가서 상황 보기 (매우 위험!)",
 
200
  "info_518_t3_opt1_got": "새로운 사실: 금남로에서 군인들이 곤봉과 대검으로 사람들을 마구 찌르고 때리고 있어요. 길바닥에 피가 흥건하고, 비명소리가 끊이지 않아요. 젊은이, 노인 가리지 않아요. (힌트: 금남로, 군인들 잔인함, 피, 비명)",
201
  "info_518_t3_opt2_got": "새로운 사실: 한 아주머니가 울면서 말했어요. '내 아들이 학생도 아닌데 길 가다가 군인들에게 끌려갔어요! 살려주세요!' 많은 시민들이 군인들의 만행에 치를 떨고 있어요. (힌트: 시민들 분노, 아무나 잡아감, 군인 만행)",
202
  "info_518_t3_opt3_got": "새로운 사실: 군인에게 맞아서 다리가 부러진 아저씨를 만났어요. '그냥 집에 가던 길이었는데, 갑자기 군인 서너 명이 달려들어 때렸어요. 이유도 없었어요.' (힌트: 무차별 폭행, 이유 없는 폭력, 시민 피해)",
 
203
  "event_518_t4_assignment": "군인들의 폭력이 너무 심해지자, 일부 시민들이 스스로를 지키기 위해 무기를 들기 시작했다는 소식이 있어요. '시민군'이 만들어졌다는 말도 들려요. 광주 상황이 어떻게 변하고 있는지, 시민들은 왜 무기를 들었는지 알아보세요.",
204
  "event_518_t4_source": "[알아두면 좋아요] 계엄군의 무자비한 살상 행위에 맞서 시민들은 더 이상 맨손으로 저항할 수 없다고 판단하기 시작했어요. 경찰서나 예비군 무기고에서 총기 등을 확보하고, 스스로를 '시민군'이라 부르며 조직적으로 저항하려는 움직임이 나타나고 있어요. 광주는 외부와 완전히 차단된 상태예요.",
205
  "action_518_t4_opt1_text": "시민군이 모여 있다는 곳(도청 주변 등)에 조심스럽게 접근해보기",
 
208
  "info_518_t4_opt1_got": "새로운 사실: 도청 주변에 젊은이들이 총을 들고 모여 있어요. 스스로를 '시민군'이라고 부르며, '계엄군으로부터 광주를 지키겠다'고 외치고 있어요. 분위기가 아주 긴장돼요. (힌트: 시민군 등장, 도청, 총 든 시민, 광주 지키기)",
209
  "info_518_t4_opt2_got": "새로운 사실: 총을 든 한 청년이 말했어요. '우리 가족과 친구들이 군인들에게 맞아 죽는 걸 더는 볼 수 없었어요. 우리도 살기 위해 싸우는 거예요!' (힌트: 시민군 된 이유, 가족 보호, 살기 위한 싸움)",
210
  "info_518_t4_opt3_got": "새로운 사실: 병원에 총 맞은 사람들이 계속 실려오고 있어요. 의사, 간호사, 약품 모두 부족해요. '제발 도와주세요!' 하는 소리가 들려요. (힌트: 총상 환자 많음, 병원 부족, 도움 필요)",
 
211
  "event_518_t5_assignment": "계엄군이 잠시 광주 외곽으로 물러나고, 시민들이 광주를 스스로 다스리고 있다는 소식이 있어요. 이 짧은 '해방 광주' 기간 동안 시민들은 어떻게 지내고 있는지, 질서는 잘 지켜지는지, 앞으로 뭘 걱정하는지 취재해주세요.",
212
  "event_518_t5_source": "[알아두면 좋아요] 시민들의 거센 저항에 밀려 계엄군이 5월 21일 광주 시내에서 철수했어요. 이후 며칠간 시민들은 스스로 질서를 유지하며 식량과 생필품을 나누고, 부상자를 돌봤어요. 하지만 계엄군이 다시 공격해올 거라는 불안감도 컸어요.",
213
  "action_518_t5_opt1_text": "시민들이 모여 회의하는 곳(도청 광장 등)에 가보기",
 
216
  "info_518_t5_opt1_got": "새로운 사실: 도청 광장에서 시민들이 모여 앞으로 어떻게 할지 이야기하고 있어요. '우리의 요구를 정부에 알려야 한다', '끝까지 싸우자' 같은 목소리가 나와요. (힌트: 시민 회의, 도청 광장, 요구 전달, 계속 싸우자)",
217
  "info_518_t5_opt2_got": "새로운 사실: 한 상인이 말���어요. '군인들이 없으니 잠시 평화롭지만, 언제 다시 쳐들어올지 몰라 무서워요. 제발 이 일이 빨리 해결됐으면 좋겠어요.' (힌트: 잠시 평화, 다시 공격 걱정, 빨리 해결되길 바람)",
218
  "info_518_t5_opt3_got": "새로운 사실: 아주머니들이 주먹밥을 만들어서 시민군과 배고픈 사람들에게 나눠주고 있어요. 서로 돕고 아끼는 모습이 감동적이에요. (힌트: 시민들 서로 도움, 주먹밥 나눔, 감동적)",
 
219
  "event_518_t6_assignment": "계엄군이 다시 광주로 쳐들어올 거라는 소문이 파다해요. 시민들은 마지막까지 싸울 준비를 하고 있는 것 같아요. 도청을 중심으로 한 시민군의 상황과 광주 전체의 긴장된 분위기를 전해주세요. 매우 위험한 상황입니다.",
220
  "event_518_t6_source": "[알아두면 좋아요] '해방 광주'는 오래가지 못했어요. 신군부는 대규모 병력을 동원해 광주를 다시 점령할 계획을 세웠어요. 시민들은 이 사실을 알고 있었지만, 많은 이들이 끝까지 남아 광주를 지키려 했어요. 외부와의 통신은 거의 끊긴 상태예요.",
221
  "action_518_t6_opt1_text": "도청 주변 시민군들의 마지막 방어 준비 모습 살펴보기 (극도로 위험!)",
 
224
  "info_518_t6_opt1_got": "새로운 사실: 도청 주변에 시민군들이 바리케이드를 쌓고 무기를 점검하고 있어요. 표정은 굳어있지만, 눈빛은 결연해요. '광주는 우리가 지킨다!'는 말이 들려요. (힌트: 도청 방어 준비, 시민군 결의, 마지막 저항)",
225
  "info_518_t6_opt2_got": "새로운 사실: 어린 학생 시민군이 말했어요. '무섭지만 도망가지 않을 거예요. 여기서 죽더라도 광주를 지키고 싶어요.' 많은 사람들이 비장한 각오를 하고 있어요. (힌트: 남은 시민들 각오, 두려움과 용기, 광주 지키기)",
226
  "info_518_t6_opt3_got": "새로운 사실: 광주의 진실을 알리려는 일부 시민들이 몰래 외부로 편지나 사진을 보내려고 애쓰고 있어요. 하지만 군인들이 철저히 막고 있어서 쉽지 않아 보여요. (힌트: 진실 알리기 노력, 외부 연락 시도, 군인 통제)",
 
227
  "event_518_t7_assignment": "5월 27일 새벽, 결국 계엄군이 탱크를 앞세우고 도청으로 쳐들어왔어요. 마지막까지 저항하던 시민군과 계엄군 사이에 큰 전투가 벌어지고 있어요. 이 비극적인 상황을 기록해야 합니다. 안전을 최우선으로 하세요.",
228
  "event_518_t7_source": "[알아두면 좋아요] 5월 27일 새벽, 계엄군은 '상무충정작전'이라는 이름으로 전남도청을 무력으로 점령했어요. 도청을 사수하던 많은 시민군이 이 과정에서 희생되었어요. 이로써 열흘간의 광주민주화운동은 비극적으로 막을 내리게 됩니다.",
229
  "action_518_t7_opt1_text": "도청 근처 안전한 곳에서 총소리와 상황 파악하기 (매우 위험!)",
 
232
  "info_518_t7_opt1_got": "새로운 사실: 새벽부터 도청 쪽에서 총소리가 쉴 새 없이 들려요. 탱크 소리도 들리고, 하늘에는 헬리콥터가 날아다녀요. 마치 전쟁터 같아요. (힌트: 도청 진압, 총소리, 탱크, 전쟁터)",
233
  "info_518_t7_opt2_got": "새로운 사실: 날이 밝자 군인들이 도청을 완전히 장악했어요. 거리에는 군인들만 보이고, 시민들은 두려움에 떨며 숨어있어요. 광주 전체가 슬픔과 절망에 빠졌어요. (힌트: 군인들 도청 장악, 시민들 공포, 슬픔과 절망)",
234
  "info_518_t7_opt3_got": "새로운 사실: 병원에는 새벽 전투로 다치거나 죽은 시민군들이 계속 들어오고 있어요. 가족들의 울음소리가 끊이지 않아요. 너무나 많은 희생자가 나왔어요. (힌트: 많은 사상자, 병원 비상, 가족들 슬픔)",
 
235
  "event_518_t8_assignment": "광주에서의 큰 싸움은 끝났지만, 슬픔과 아픔은 계속되고 있어요. 살아남은 사람들의 이야기, 숨겨진 진실, 그리고 앞으로 광주가 어떻게 될지 마지막으로 취재해서 알려주세요.",
236
  "event_518_t8_source": "[알아두면 좋아요] 5.18 광주민주화운동은 비록 군인들에게 진압되었지만, 이후 한국 민주주의 발전에 큰 영향을 주었어요. 하지만 오랫동안 진실이 제대로 알려지지 않아 많은 사람들이 아픔을 겪었어요.",
237
  "action_518_t8_opt1_text": "희생자 가족이나 살아남은 시민군을 만나 이야기 듣기",
 
240
  "info_518_t8_opt2_got": "새로운 사실: 군인들이 시민들을 몰래 묻었다는 소문이 있어요. 정부는 사망자 수를 줄여서 발표하고, 진실을 ���기려고 해요. 사람들은 언젠가 모든 것이 밝혀지길 바라고 있어요. (힌트: 숨겨진 진실, 정부의 은폐, 진실 규명 바람)",
241
 
242
  # --- 6월 항쟁 취재 시나리오 ---
243
+ "scenario_june_struggle_name": "6월 항쟁 이야기 (1987년)",
 
244
  "event_june_t1_assignment": "서울대학교 학생 박종철 군이 경찰 조사를 받다가 죽었어요. 경찰은 '책상을 탁 치니 억 하고 죽었다'고 이상하게 말했지만, 고문으로 죽었다는 의심이 커지고 있어요. 이 사건의 진짜 이유와 사람들의 반응을 알아보세요.",
245
  "event_june_t1_source": "[알아두면 좋아요] 1987년 1월 14일, 박종철 학생은 경찰서(남영동 대공분실)에서 조사를 받다가 죽었어요. 경찰이 이상하게 설명해서 사람들이 많이 화가 났고, 진짜 이유를 밝히라는 목소리가 커지고 있어요. 전두환 대통령 정부에게 큰 문제가 될 것 같아요.",
246
  "action_june_t1_opt1_text": "사건 담당 경찰서나 치안본부 근처에서 경찰들 이야기 몰래 듣기",
 
249
  "info_june_t1_opt1_got": "새로운 사실: 치안본부에서 일하는 사람이 몰래 말해줬어요. '높은 사람이 이 사건 빨리 덮으라고 시켰어요. 그냥 놀라서 죽었다고 하래요.' (힌트: 경찰 윗사람 지시, 사건 숨기려 함, 놀라서 죽었다고 거짓말)",
250
  "info_june_t1_opt2_got": "새로운 사실: 박종철 학생 아버지가 울면서 말했어요. '철아, 잘 가거라... 아빠는 할 말이 없다...' 친구들은 '고문해서 죽인 사람 벌주세요!' 하면서 화를 냈어요. (힌트: 박종철 가족 슬픔, 고문해서 죽였다고 화냄, 학생들 분노)",
251
  "info_june_t1_opt3_got": "새로운 사실: 박종철 학생 몸을 본 의사 선생님이 조심스럽게 말했어요. '목에 눌린 자국이 있고 폐에서 이상한 소리가 났어요. 그냥 놀라서 죽은 것 같지 않아요. 물고문했을 수도 있어요.' (힌트: 의사 선생님 증언, 물고문 의심, 경찰 말과 다름)",
 
252
  "event_june_t2_assignment": "전두환 대통령이 '지금 헌법(대통령을 직접 뽑지 않는 법)을 바꾸지 않겠다'는 '4.13 호헌 조치'를 발표했어요. 많은 사람들이 대통령을 직접 뽑고 싶어 했는데, 이 발표 때문에 더 화가 난 것 같아요. 사람들의 반응과 앞으로 시위가 더 커질지 알아보세요.",
253
  "event_june_t2_source": "[알아두면 좋아요] 박종철 학생 사건으로 민주주의를 원하는 목소리가 커졌지만, 전두환 대통령은 4월 13일에 헌법을 고치지 않겠다고 발표했어요. 이건 국민들의 바람을 무시하는 거라서, 학생, 종교인, 일반 시민들까지 모두 크게 반발하고 있어요.",
254
  "action_june_t2_opt1_text": "대학교에 가서 학생들 반응과 시위 계획 알아보기",
 
257
  "info_june_t2_opt1_got": "새로운 사실: 대학교 학생들이 '독재 타도! 직선제 쟁취!' 같은 구호를 외치며 시위를 준비하고 있어요. '더 이상 참을 수 없다'며 격렬하게 싸울 거라고 해요. (힌트: 학생들 분노, 직선제 요구, 큰 시위 예고)",
258
  "info_june_t2_opt2_got": "새로운 사실: 한 신부님이 말했어요. '정부가 국민의 목소리를 듣지 않으니, 우리가 직접 나서서 민주주의를 되찾아야 합니다. 모든 양심 있는 사람들이 힘을 합칠 것입니다.' (힌트: 종교계 반발, 민주주의 되찾기, 힘 합치자)",
259
  "info_june_t2_opt3_got": "새로운 사실: 시장에서 만난 아주머니가 말했어요. '대통령을 내 손으로 뽑고 싶은데, 왜 못하게 하는지 모르겠어요. 너무 답답해요.' 많은 사람들이 실망하고 화가 나 있어요. (힌트: 시민들 실망, 직선제 바람, 답답함)",
 
260
  "event_june_t3_assignment": "6월 9일, 연세대학교에서 시위하던 이한열 학생이 경찰이 쏜 최루탄에 머리를 맞아 쓰러졌어요. 지금 아주 위독하다고 해요. 이 사건 때문에 사람들이 더 크게 분노하고 있어요. 사건 현장 상황과 학생들, 시민들 반응을 긴급히 취재해주세요.",
261
  "event_june_t3_source": "[알아두면 좋아요] '4.13 호헌 조치' 이후 시위가 계속되던 중, 6월 9일 연세대 앞에서 이한열 학생이 경찰이 직격으로 쏜 최루탄에 맞아 의식을 잃었어요. 이 모습이 사진으로 알려지면서 국민들의 분노는 극에 달했고, 6월 항쟁이 전국적으로 확산되는 결정적인 계기가 되었어요.",
262
  "action_june_t3_opt1_text": "이한열 학생이 쓰러진 연세대 앞 시위 현장 가보기 (위험!)",
 
265
  "info_june_t3_opt1_got": "새로운 사실: 연세대 앞은 전쟁터 같아요. 학생들이 돌을 던지고, 경찰은 최루탄을 마구 쏘고 있어요. 이한열 학생이 쓰러졌던 자리에는 아직도 핏자국이 남아있어요. (힌트: 연세대 시위 격렬, 최루탄 난사, 이한열 학생 피격 현장)",
266
  "info_june_t3_opt2_got": "새로운 사실: 병원에서 만난 이한열 학생 친구들이 울면서 말했어요. '경찰이 한열이를 죽이려고 했어요! 이건 살인미수예요!' 학생은 의식이 없고 매우 위독한 상태라고 해요. (힌트: 이한열 학생 위독, 친구들 분노, 경찰 비판)",
267
  "info_june_t3_opt3_got": "새로운 사실: 명동성당 주변에 학생들이 모여들고 있어요. '이한열을 살려내라!', '군부독재 물러가라!' 외치고 있어요. 내일(6월 10일) 아주 큰 시위가 있을 거라는 소문이 돌아요. (힌트: 명동성당 시위 준비, 이한열 살리자, 큰 시위 예고)",
 
268
  "event_june_t4_assignment": "오늘 6월 10일, 전국에서 '박종철 고문살인 규탄 및 민주헌법 쟁취 국민대회'라는 아주 큰 시위가 열리고 있어요. 서울뿐 아니라 부산, 광주 등 다른 도시에서도 많은 사람들이 거리로 나왔다고 해요. 시위 규모와 모습, 경찰 대응, 그리고 '넥타이 부대'라고 불리는 회사원들 참여 모습 등을 취재해주세요.",
269
  "event_june_t4_source": "[알아두면 좋아요] 이한열 학생 사건은 6월 10일로 예정되어 있던 국민대회에 기름을 부었어요. 전국 주요 도시에서 수십만 명의 학생과 시민들이 거리로 쏟아져 나와 '호헌 철폐', '독재 타도'를 외쳤어요. 특히 평범한 회사원들(넥타이 부대)까지 시위에 참여하면서 항쟁은 더욱 커졌어요.",
270
  "action_june_t4_opt1_text": "서울 시청 앞이나 명동 등 주요 시위 현장 한복판에 가보기 (매우 위험!)",
 
273
  "info_june_t4_opt1_got": "새로운 사실: 서울 시내가 온통 시위하는 사람들로 가득 찼어요! 경찰이 최루탄을 쏘며 막고 있지만, 사람들은 물러서지 않고 '독재 타도!'를 외치고 있어요. 여기저기서 싸움이 벌어지고 있어요. (힌트: 6.10 국민대회, 대규모 시위, 경찰과 충돌, 독재 타도)",
274
  "info_june_t4_opt2_got": "새로운 사실: 양복 입은 회사원 아저씨가 말했어요. '더 이상 나라가 이렇게 되는 걸 보고만 있을 수 없어서 나왔습니다. 우리 아이들에게 부끄럽지 않은 나라를 만들어주고 싶어요.' (힌트: 넥타이 부대 참여, 민주주의 열망, 미래 세대 걱정)",
275
  "info_june_t4_opt3_got": "새로운 사실: 부산 특파원이 알려왔어요. '부산역 광장에도 수만 명이 모여 시위를 벌이고 있습니다. 경찰과 격렬하게 대치 중이고, 부상자도 나오고 있습니다.' 전국이 들끓고 있어요. (힌트: 전국적 시위, 부산 상황, 지방도 뜨거움)",
 
276
  "event_june_t5_assignment": "시위대 중 일부가 명동성당으로 들어가 농성을 시작했어요. 명동성당은 시위대에게 안전한 곳이 되어주고 있는 것 같아요. 성당 안팎의 분위기, 농성하는 사람들의 요구, 그리고 정부가 어떻게 나올지 사람들의 예상을 취재해주세요.",
277
  "event_june_t5_source": "[알아두면 좋아요] 6월 항쟁 기간 동안 명동성당은 민주화 운동의 중요한 장소가 되었어요. 경찰의 폭력을 피해 많은 시위대가 성당으로 들어와 농성을 벌였고, 종교계는 이들을 보호했어요. 이는 정부에게 큰 부담을 주었어요.",
278
  "action_june_t5_opt1_text": "명동성당 안으로 들어가 농성 중인 학생이나 시민들 만나보기",
 
281
  "info_june_t5_opt1_got": "새로운 사실: 명동성당 안은 학생들과 시민들로 가득해요. 지쳤지만 눈빛은 살아있어요. '대통령 직선제 실시하라!', '민주정부 수립하자!' 같은 구호를 외치고 있어요. (힌트: 명동성당 농성, 직선제 요구, 민주정부 희망)",
282
  "info_june_t5_opt2_got": "새로운 사실: 성당 밖에서 한 수녀님이 기도하며 말했어요. '저들이 평화롭게 자기 목소리를 낼 수 있도록, 그리고 아무도 다치지 않도록 기도하고 있어요. 정의가 이길 거예요.' (힌트: 성직자 지지, 평화 기원, 정의 승리 믿음)",
283
  "info_june_t5_opt3_got": "새로운 사실: 경찰 관계자가 몰래 말했어요. '성당 안으로 함부로 들어갈 수가 없어서 골치 아파요. 하지만 계속 저렇게 둘 수는 없을 텐데...' 정부도 고민이 많은 것 같아요. (힌트: 경찰 고민, 성당 진입 어려움, 정부 압박감)",
 
284
  "event_june_t6_assignment": "오늘은 '국민평화대행진'이 있는 날이에요. 전국적으로 100만 명이 넘는 사람들이 거리로 나올 거라고 해요. 특히 오늘은 경찰이 최루탄을 쏘지 않기로 했다는 소문도 있어요. 정말 평화로운 시위가 될지, 사람들의 열기는 어떨지 현장에서 확인해주세요.",
285
  "event_june_t6_source": "[알아두면 좋아요] 6월 항쟁이 계속되면서 국민들의 민주화 요구는 더욱 거세졌어요. 6월 26일에는 전국 33개 도시에서 100만 명이 넘는 시민들이 참여하는 '국민평화대행진'이 계획되었어요. 정부도 더 이상 강경 대응만으로는 사태를 해결할 수 없다는 것을 느끼기 시작했어요.",
286
  "action_june_t6_opt1_text": "서울 도심 평화대행진 행렬에 참여해서 시민들과 함께 걷기",
 
289
  "info_june_t6_opt1_got": "새로운 사실: 정말 많은 사람들이 거리로 나왔어요! 아이 손을 잡고 나온 가족, 나이 드신 할아버지 할머니까지 모두 함께 '민주주의'를 외치며 걷고 있어요. (힌트: 6.26 평화대행진, 엄청난 인파, 다양한 시민 참여)",
290
  "info_june_t6_opt2_got": "새로운 사실: 신기하게도 오늘은 경찰이 최루탄을 쏘지 않아요! 시위는 아주 평화롭고 질서있게 진행되고 있어요. 마치 축제 같아요. 사람들은 노래도 부르고 춤도 춰요. (힌트: 최루탄 없는 날, 평화 시위, 축제 분위기)",
291
  "info_june_t6_opt3_got": "새로운 사실: 한 초등학생이 아빠 목마를 타고 말했어요. '우리나라가 더 좋은 나라가 됐으면 좋겠어요!' 어른들은 이 모습을 보며 눈물을 글썽였어요. (힌트: 미래세대 희망, 감동적인 모습, 좋은 나라 염원)",
 
292
  "event_june_t7_assignment": "오늘, 정부 여당의 노태우 대표가 갑자기 '6.29 선언'이라는 것을 발표했어요! 대통령 직선제를 받아들이고, 김대중 씨도 풀어주겠다는 등 놀라운 내용이 많다고 해요. 이 발표 내용과 사람들의 반응, 그리고 진짜로 민주주의가 올지 마지막으로 취재해주세요. (이번엔 취재 활동 없이 바로 기사 쓰기로 가요.)",
293
  "event_june_t7_source": "[긴급 뉴스] 6월 29일, 민정당 노태우 대표가 국민들의 민주화 요구를 받아들여 대통령 직선제 개헌, 김대중 사면복권 등 8개 항목의 시국 수습 방안을 발표했어요. 이것은 사실상 국민들의 승리를 의미해요!",
294
  "action_june_t7_opt1_text": "6.29 선언 내용 자세히 살펴보고 중요한 점 정리하기",
 
549
  status['reporter_safety'] = max(0, min(100, status['reporter_safety']))
550
 
551
  st.session_state['actions_taken_this_turn'] += 1
 
552
 
553
  # --- 기사 작성 인터페이스 생성 ---
554
  def generate_article_interface(game_state):
 
559
  for idx, note in enumerate(game_state['reporter_notebook']):
560
  st.markdown(f"- {note}")
561
  else:
562
+ st.caption("아직 취재한 내용이 없어요.")
563
 
564
  st.markdown("---")
565
 
566
  with st.form(key="article_form"):
567
  article_headline = st.text_input(get_text_func("article_headline_label"), placeholder="예: 나쁜 선거, 그 비밀을 밝힌다!")
568
+ article_body_summary = st.text_area(get_text_func("article_body_label"), height=150, placeholder="예: 오늘 대통령 뽑는 날, 나쁜 사람들이 몰래 표를 바꿨어요...")
569
 
570
  article_tones = {
571
  "fact_based": get_text_func("article_tone_fact_based"),
 
585
  if not article_headline or not article_body_summary:
586
  st.warning(get_text_func("warning_empty_article"))
587
  return None
 
588
  if not game_state['reporter_notebook']:
589
+ st.warning("취재 노트에 내용이 없어요. 기사를 쓸 수 없어요.")
590
  return None
 
591
  return {
592
+ "turn": game_state['current_turn'], "headline": article_headline, "body_summary": article_body_summary,
593
+ "tone": selected_tone_key, "raw_notes": list(game_state['reporter_notebook']), "ai_score": 0
 
 
 
 
594
  }
595
  return None
596
 
 
598
  def evaluate_article_and_get_feedback_openai(article, game_state, assignment_data):
599
  status = game_state['status']
600
  get_text_func = lambda k: get_text(k)
 
601
  current_assignment_text = assignment_data["assignment_text"]
602
  reporter_notes_str = "\n".join([f"- {note}" for note in article['raw_notes']])
603
  article_tone_text = get_text_func(f"article_tone_{article['tone']}")
604
 
605
  prompt = f"""
606
+ 당신은 어린이 신문사의 따뜻하면서도 명철한 편집장입니다. 당신의 목표는 새내기 기자가 최고의 기사를 쓸 수 있도록 돕는 것입니다.
607
+ 이 기자는 초등학생 독자들도 이해할 수 있는 글을 쓰려고 노력하고 있습니다. 칭찬할 부분은 구체적으로 언급하여 격려하고, 개선이 필요한 부분은 명확한 근거와 함께 친절하게 설명해주세요.
608
+ 피드백은 기자가 **어떤 부분을 잘했고, 어떤 부분을 왜, 어떻게 개선해야 하는지** 명확히 이해하도록 돕는 데 초점을 맞춥니다.
609
+
610
+ [오늘의 할 일 (취재 지시)]
611
+ {current_assignment_text}
612
+
613
+ [기자가 적은 내용 (취재 노트)]
614
+ {reporter_notes_str}
615
+
616
+ [기자가 쓴 기사]
617
+ - 제목: {article['headline']}
618
+ - 내용 요약: {article['body_summary']}
619
+ - 선택한 분위기: {article_tone_text}
620
+
621
+ [피드백 작성 가이드]
622
+ 1. **칭찬과 개선점의 조화:** 잘한 점과 아쉬운 점을 균형 있게 언급해주세요.
623
+ 2. **구체적인 인용:** 피드백 시, **기자가 작성한 제목, 내용 요약, 또는 취재 노트의 특정 부분을 직접 인용**하며 설명해주세요.
624
+ 예: "제목에서 'OOO'라는 표현은 독자들의 호기심을 자극하는 좋은 시도예요." 또는 "내용 요약 중 'XXX' 부분은 YY라는 점에서 조금 아쉬워요. ZZZ처럼 바꿔보면 어떨까요?"
625
+ 3. **초등학생 눈높이 고려:** 모든 설명은 초등학생 기자가 이해할 수 있도록 쉽고 명확해야 합니다.
626
+
627
+ [총평최종 조언]
628
+ 항목별 점수와 피드백을 바탕으로 총점(100점 만점)을 계산하고, "overall_feedback"에는 기사의 전반적인 강점과 개선점을 균형 있게 요약하여 전달합니다.
629
+ **칭찬할 부분은 구체적으로 언급하고, 개선이 필요한 부분은 기자가 다음 기사에서 더욱 발전할 수 있도록 명확하고 건설적인 조언을 담아주세요.**
630
+ 예시: "이번 ��사는 [구체적인 칭찬 내용, 예: '제목의 OOO 표현' 또는 '내용 요약의 XXX 부분']에서 기자님의 고민과 성장이 엿보여 정말 좋았어요. 다만, [가장 개선이 필요한 부분, 예: '논리적 연결' 또는 '어휘 선택']에 대해서는 조금 더 신경 써주면 훨씬 훌륭한 기사가 될 거예요. 특히 [가장 중요한 개선점 한 가지]를 다음 취재 때 꼭 기억해주세요!"
631
+
632
+ 반드시 아래 JSON 형식으로 응답해주세요:
633
+ {{
634
+ "total_score": 총점(숫자),
635
+ "overall_feedback": "기사의 전반적인 강점과 개선 방향에 대한 따뜻하지만 명확한 조언 (문자열, 칭찬과 개선점 균형있게)"
636
+ }}
637
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
  try:
639
  with st.spinner("AI 편집장님이 기사를 꼼꼼히 검토하고 있습니다..."):
640
  response = client.chat.completions.create(
641
  model="gpt-4o-mini",
642
  messages=[{"role": "user", "content": prompt}],
643
  response_format={"type": "json_object"},
644
+ temperature=0.1, max_tokens=1000
 
645
  )
646
+ ai_evaluation = json.loads(response.choices[0].message.content)
 
647
  total_score = ai_evaluation.get("total_score", 0)
648
  overall_feedback = ai_evaluation.get("overall_feedback", "AI 편집장 연결 오류로 자동 평가되었습니다.")
649
  except Exception as e:
 
680
 
681
  # --- UI 표시 함수들 ---
682
  def display_reporter_dashboard(game_state):
 
683
  status = game_state['status']
684
  avg_score = (status['article_score_total'] / status['article_count']) if status['article_count'] > 0 else 0
685
+ col1, col2, col3, col4 = st.columns(4)
686
+ with col1: st.metric(get_text("term_public_trust"), f"{status['public_trust']}%")
687
+ with col2: st.metric(get_text("term_press_freedom"), f"{status['press_freedom']}%")
688
+ with col3: st.metric(get_text("term_reporter_safety"), f"{status['reporter_safety']}%")
689
+ with col4: st.metric(get_text("term_article_score_avg"), f"{avg_score:.1f}")
690
+
691
+ def display_historical_glossary(scenario_key):
 
 
 
 
 
 
692
  prefix_key = scenario_key.replace('.', '_')
693
  glossary_prefix = f'glossary_{prefix_key}_'
694
+ glossary_keys = sorted([k for k in ALL_TEXTS if k.startswith(glossary_prefix)])
695
+ if not glossary_keys:
696
+ st.caption("이 시대의 용어 정보가 아직 없어요.")
 
 
697
  else:
698
+ for key in glossary_keys:
699
+ st.markdown(get_text(key))
 
700
 
701
  def display_final_results(game_state):
 
702
  st.balloons()
703
+ st.header(get_text("assignment_over_title"))
 
704
 
705
  with st.container(border=True):
706
+ st.subheader(get_text("assignment_over_subtitle"))
707
  display_reporter_dashboard(game_state)
708
 
709
+ st.divider()
710
  with st.container(border=True):
711
+ st.subheader("🗞️ 내가 보낸 주요 기사들")
712
  if game_state['submitted_articles']:
713
  for article in game_state['submitted_articles']:
714
+ tone_display = get_text(f"article_tone_{article['tone']}")
715
+ score = article.get('ai_score', 'N/A')
716
+ st.markdown(f"**{article['turn']}일차:** \"{article['headline']}\" (분위기: {tone_display}, 점수: **{score}점**)")
 
717
  else:
718
  st.caption("이번 취재 동안 보낸 기사가 없어요.")
719
 
 
 
 
 
720
  # --- 세션 상태 초기화 ---
721
+ if 'game_mode' not in st.session_state:
722
+ st.session_state.game_mode = 'scenario_select'
723
+ st.session_state.game_state = None
724
+ st.session_state.current_assignment_data = None
725
+ st.session_state.actions_taken_this_turn = 0
726
+ st.session_state.desk_feedback_message = None
 
727
 
728
  # --- 메인 게임 로직 ---
729
  def reporter_simulation_main():
730
+ st.title(get_text("game_title"))
 
731
 
732
  # --- 시나리오 선택 화면 ---
733
  if st.session_state.game_mode == 'scenario_select':
734
+ st.header(get_text("scenario_select_title"))
735
  st.write("기자가 되어 우리나라의 중요한 역사적 순간으로 시간 여행을 떠나보세요!")
736
  st.divider()
737
  scenario_descriptions = {
 
739
  "5.18_gwangju": "1980년 5월, 광주라는 도시에서 아주 슬픈 일이 있었어요. 용감한 기자가 되어서 그곳 사람들의 이야기를 듣고 진실을 알려야 해요. (조금 무섭거나 슬픈 내용이 나올 수 있어요.)",
740
  "june_struggle": "1987년, 우리나라 사람들이 '우리 손으로 대통령을 뽑고 싶다!'고 외쳤던 때예요. 사회부 기자가 되어서 뜨거운 현장의 목소리를 담아보세요."
741
  }
742
+ for key, info in SCENARIOS.items():
743
  with st.container(border=True):
744
+ st.subheader(get_text(info["display_name"]))
745
+ st.caption(f"🕰️ **언제:** {info['start_year']}년 | 🧑‍💼 **나는 누구?:** {info['player_role']}")
746
+ st.markdown(scenario_descriptions.get(key, ""))
747
+ if st.button(get_text("scenario_select_button"), key=f"select_{key}", use_container_width=True):
 
748
  st.session_state.game_state = initialize_reporter_scenario_state(key)
749
+ st.session_state.game_mode = 'assignment_loading'
750
  st.rerun()
751
  st.stop()
752
 
753
+ # --- 게임 진행 화면 ---
754
+ game_state = st.session_state.game_state
755
+ if not game_state:
756
+ st.warning("게임 상태 정보가 없습니다. 시나리오 선택 화면으로 돌아갑니다.")
757
+ st.session_state.game_mode = 'scenario_select'
758
+ st.rerun()
759
+
760
+ scenario_key = game_state['scenario_key']
761
+
762
+ # --- 취재 종료 화면 ---
763
+ if st.session_state.game_mode == 'assignment_over':
764
+ display_final_results(game_state)
765
+ c1, c2 = st.columns(2)
766
+ if c1.button(get_text("button_restart_assignment"), use_container_width=True):
767
+ st.session_state.game_state = initialize_reporter_scenario_state(scenario_key)
768
+ st.session_state.game_mode = 'assignment_loading'
769
+ st.rerun()
770
+ if c2.button(get_text("button_back_to_scenario_select"), use_container_width=True):
771
+ st.session_state.game_mode = 'scenario_select'
772
+ st.rerun()
773
+ st.stop()
774
+
775
+ # --- 새 턴 데이터 로딩 ---
776
+ if st.session_state.game_mode == 'assignment_loading':
777
+ spinner_text = get_text('status_loading_assignment').format(year=game_state['game_year'], turn=game_state['current_turn'])
778
+ with st.spinner(spinner_text):
779
+ time.sleep(0.5)
780
+ assignment = get_next_assignment(scenario_key, game_state['current_turn'], game_state)
781
+ if assignment:
782
+ st.session_state.current_assignment_data = assignment
783
+ st.session_state.actions_taken_this_turn = 0
784
+ st.session_state.desk_feedback_message = None
785
+ st.session_state.game_mode = 'in_progress'
786
+ else:
787
+ st.session_state.game_mode = 'assignment_over'
788
+ st.rerun()
789
+
790
+ # --- 게임 진행 중 화면 ---
791
+ assignment_data = st.session_state.current_assignment_data
792
+ if st.session_state.game_mode == 'in_progress' and assignment_data:
793
+ # --- 상단 고정 정보: 상태 대시보드 ---
794
+ with st.expander(f"**{get_text('dashboard_term').format(year=game_state['game_year'], turn=game_state['current_turn'])} - {get_text('dashboard_title')}**"):
795
+ display_reporter_dashboard(game_state)
796
+ if st.button("다른 시대로 가기", key="quit_ingame", use_container_width=True):
797
+ st.session_state.game_mode = 'scenario_select'
798
  st.rerun()
799
 
800
+ st.divider()
 
801
 
802
+ # --- 중앙 메인 화면: 단계별 진행 ---
803
+ actions_done = st.session_state.actions_taken_this_turn >= ACTIONS_PER_TURN_LIMIT
804
+ article_submitted = st.session_state.desk_feedback_message is not None
805
+
806
+ # 1. 오늘의 할 일 (브리핑)
807
+ st.info(f"**{get_text('current_assignment_title')}:** {assignment_data['assignment_text']}")
808
+ st.divider()
809
+
810
+ # 2. 취재 활동 또는 기사 작성/피드백
811
+ if not actions_done:
812
+ st.subheader(get_text("reporter_actions_title"))
813
+ st.caption(f"남은 활동 횟수: **{ACTIONS_PER_TURN_LIMIT - st.session_state.actions_taken_this_turn}번**")
814
+ for i, opt in enumerate(assignment_data['options']):
815
+ risk_score = opt.get('cost_freedom_risk',0) + opt.get('safety_risk',0)
816
+ risk_str = "🚨 매우 위험!" if risk_score > 40 else "⚠️ 조금 위험" if risk_score > 0 else "👍 안전함"
817
+ if st.button(get_text("action_button_label").format(action=opt['action_text'], risk_str=risk_str), key=f"action_{i}", use_container_width=True):
818
+ process_reporter_action(opt, game_state)
819
+ st.rerun()
820
+ elif assignment_data['article_writing_phase'] and not article_submitted:
821
+ st.subheader(get_text("article_writing_title"))
822
+ submitted_article = generate_article_interface(game_state)
823
+ if submitted_article:
824
+ feedback = evaluate_article_and_get_feedback_openai(submitted_article, game_state, assignment_data)
825
+ st.session_state.desk_feedback_message = feedback
826
+ st.rerun()
827
+ else:
828
+ if st.session_state.desk_feedback_message:
829
+ st.subheader(get_text("desk_feedback_title"))
830
+ st.success(f"**AI 편집장님:** {st.session_state.desk_feedback_message}")
831
+ else: # 기사 작성 단계가 없는 턴
832
+ st.success(get_text("status_actions_taken"))
833
 
834
+ if st.button(get_text("button_next_day"), use_container_width=True, type="primary"):
 
835
  if game_state['current_turn'] >= game_state['max_turns']:
836
  st.session_state.game_mode = 'assignment_over'
837
  else:
838
  game_state['current_turn'] += 1
839
+ st.session_state.game_mode = 'assignment_loading'
840
  st.rerun()
841
 
842
+ st.divider()
843
+ # --- 하단 정보 탭 ---
844
+ tab1, tab2, tab3 = st.tabs([get_text("historical_source_title"), get_text("sidebar_glossary_title"), "💡 FAQ & 게임 팁"])
845
+ with tab1:
846
+ st.write(assignment_data['source_text'])
847
+ with tab2:
848
+ display_historical_glossary(scenario_key)
849
+ with tab3:
850
+ st.markdown("""
851
+ **Q. 이 게임은 무엇인가요?**
852
+ A. 옛날 신문 기자가 되어서, 우리나라의 중요한 역사 속으로 들어가 직접 취재하고 기사를 써보는 게임이에요.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
 
854
+ **Q. 점수는 왜 자꾸 바뀌나요?**
855
+ A. 위험한 곳을 취재하거나, 정부가 싫어하는 기사를 쓰면 '자유'나 '안전' 점수가 낮아질 수 있어요. 옛날 기자들의 어려움을 체험해보는 거예요.
856
 
857
+ **Q. 기사는 어떻게 써야 점수가 높나요?**
858
+ A. '내가 적은 내용'에 있는 힌트를 잘 활용하고, '오늘 할 일'에서 시킨 내용을 빠짐없이 담아보세요.
859
+
860
+ **Q. 문제가 생기면 어떻게 해요?**
861
+ A. **ll7098ll@bonggokcho.com (구미봉곡초 교사 이병민)** 으로 이메일을 보내주세요.
862
+ """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
 
864
  if __name__ == "__main__":
865
  reporter_simulation_main()