ll7098ll commited on
Commit
34cc154
·
verified ·
1 Parent(s): 0e123e0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -131
app.py CHANGED
@@ -613,13 +613,20 @@ def display_historical_glossary_for_reporter(scenario_key, vocab_level):
613
  st.sidebar.markdown(f"**{term}:** {definition}")
614
  st.sidebar.markdown("---")
615
 
616
- # --- 세션 상태 초기화 ---
 
 
 
 
 
 
617
  if 'game_mode' not in st.session_state: st.session_state.game_mode = 'scenario_select'
618
  if 'current_scenario_key' not in st.session_state: st.session_state.current_scenario_key = None
619
  if 'game_state' not in st.session_state: st.session_state.game_state = None
620
  if 'current_assignment_data' not in st.session_state: st.session_state.current_assignment_data = None
621
  if 'actions_taken_this_turn' not in st.session_state: st.session_state.actions_taken_this_turn = 0
622
  if 'desk_feedback_message' not in st.session_state: st.session_state.desk_feedback_message = None
 
623
 
624
  # --- 메인 게임 로직 (기자 컨셉) ---
625
  def reporter_simulation_main():
@@ -630,6 +637,7 @@ def reporter_simulation_main():
630
 
631
  st.title(get_text_main("game_title"))
632
 
 
633
  if st.session_state.game_mode == 'scenario_select':
634
  st.header(get_text_main("scenario_select_title"))
635
  scenario_descriptions = {
@@ -649,94 +657,161 @@ def reporter_simulation_main():
649
  st.session_state.actions_taken_this_turn = 0
650
  st.session_state.desk_feedback_message = None
651
  st.session_state.game_mode = 'assignment_briefing'
 
652
  st.rerun()
653
  st.stop()
654
 
 
655
  if st.session_state.game_mode != 'scenario_select' and st.session_state.game_state:
656
  game_state = st.session_state.game_state
657
  scenario_key = st.session_state.current_scenario_key
658
  vocab_level = SCENARIOS[scenario_key]["vocab_level"]
659
  get_text_main = lambda key: get_text(key, vocab_level)
660
 
661
- st.caption(f"취재 중: {SCENARIOS[scenario_key]['display_name']} | 기자: {game_state['player_role']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
 
 
 
 
 
 
 
 
 
 
663
  if st.session_state.game_mode == 'assignment_over':
664
  st.balloons()
665
  st.header(get_text_main("assignment_over_title"))
666
  st.subheader(get_text_main("assignment_over_subtitle"))
667
- display_reporter_dashboard(game_state)
668
-
669
  st.subheader("송고한 주요 기사 목록")
670
  if game_state['submitted_articles']:
671
- for article in game_state['submitted_articles']:
672
  tone_text_key = f"article_tone_{article['tone']}"
673
  tone_display_text = get_text_main(tone_text_key)
674
- st.markdown(f"- **{article['headline']}** (논조: {tone_display_text}) - {article['turn']}일차 송고 (AI 점수: {game_state['submitted_articles'][-1].get('ai_score', 'N/A')}점)") # 마지막 기사 점수 표시 (개선 필요)
 
 
675
  else:
676
  st.caption("이번 취재 기간 동안 송고한 기사가 없습니다.")
677
 
678
- st.subheader(get_text_main("term_event_log"))
679
- log_text = "\n".join(game_state.get('event_log', [])[::-1])
680
- st.text_area(get_text_main("term_event_log"), log_text, height=250, disabled=True, key="final_log_reporter")
681
-
682
- col_btn1, col_btn2 = st.columns(2)
683
- with col_btn1:
684
- if st.button(get_text_main("button_restart_assignment"), use_container_width=True):
685
- st.session_state.game_state = initialize_reporter_scenario_state(scenario_key)
686
- st.session_state.current_assignment_data = None
687
- st.session_state.actions_taken_this_turn = 0
688
- st.session_state.desk_feedback_message = None
689
- st.session_state.game_mode = 'assignment_briefing'
690
- st.rerun()
691
- with col_btn2:
692
- if st.button(get_text_main("button_back_to_scenario_select"), use_container_width=True):
693
- st.session_state.game_mode = 'scenario_select'
694
- keys_to_clear = ['current_scenario_key', 'game_state', 'current_assignment_data', 'actions_taken_this_turn', 'desk_feedback_message']
695
- for k_to_clear in keys_to_clear:
696
- if k_to_clear in st.session_state: del st.session_state[k_to_clear]
697
- st.rerun()
698
  st.stop()
699
 
700
- col_dashboard, col_main_content, col_actions_notebook = st.columns([1.2, 1.8, 1.5])
701
 
702
- with col_dashboard:
703
- st.header(get_text_main("dashboard_title"))
704
- st.markdown(f"**{get_text_main('dashboard_term').format(year=game_state['game_year'], turn=game_state['current_turn'])}**")
705
- display_reporter_dashboard(game_state)
706
- st.divider()
707
- display_reporter_notebook(game_state, vocab_level)
708
-
709
- with col_main_content:
710
- if st.session_state.game_mode == 'assignment_briefing':
711
- st.header(get_text_main("current_assignment_title"))
712
- if st.session_state.current_assignment_data is None:
713
- spinner_text = get_text_main('status_loading_assignment').format(year=game_state['game_year'], turn=game_state['current_turn'])
714
- with st.spinner(spinner_text):
715
- time.sleep(0.5)
716
- assignment = get_next_assignment(scenario_key, game_state['current_turn'], game_state)
717
- if assignment:
718
- st.session_state.current_assignment_data = assignment
719
- st.session_state.actions_taken_this_turn = 0
720
- st.session_state.desk_feedback_message = None
721
- st.session_state.game_mode = 'reporter_action'
722
- st.rerun()
723
- else: # 모든 턴 종료
724
- st.session_state.game_mode = 'assignment_over'
725
- if game_state.get('event_log') is not None:
726
- game_state['event_log'].append(get_text_main("log_assignment_over").format(scenario_name=SCENARIOS[scenario_key]['display_name']))
727
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
728
 
 
 
729
  if st.session_state.game_mode == 'reporter_action' and st.session_state.current_assignment_data:
730
  assignment_data = st.session_state.current_assignment_data
731
- st.header(get_text_main("current_assignment_title"))
732
- st.subheader(assignment_data['assignment_text'])
733
- if assignment_data.get('source_text'):
734
- st.info(f"**{get_text_main('historical_source_title')}:** {assignment_data['source_text']}")
735
-
736
- st.divider()
737
- st.subheader(get_text_main("reporter_actions_title"))
738
-
739
  if st.session_state.actions_taken_this_turn < ACTIONS_PER_TURN_LIMIT:
 
740
  for i, opt in enumerate(assignment_data['options']):
741
  risk_info = []
742
  if opt.get('cost_freedom_risk',0) > 0: risk_info.append(f"자유도↓{opt['cost_freedom_risk']}%")
@@ -746,89 +821,69 @@ def reporter_simulation_main():
746
 
747
  if st.button(button_label, key=f"rep_action_{game_state['current_turn']}_{i}_{scenario_key}", use_container_width=True):
748
  process_reporter_action(opt, game_state)
 
 
749
  st.rerun()
750
  else:
751
  st.info(get_text_main("status_actions_taken"))
752
- if assignment_data.get("article_writing_phase"):
753
- if st.button(get_text_main("button_go_to_article_writing"), key="go_to_article_writing"):
754
- st.session_state.game_mode = 'article_writing'
755
- st.rerun()
 
756
 
757
- if st.session_state.game_mode == 'article_writing' and st.session_state.current_assignment_data:
758
- assignment_data = st.session_state.current_assignment_data
759
- submitted_article = generate_article_interface(game_state, vocab_level)
760
- if submitted_article:
761
- feedback = evaluate_article_and_get_feedback_openai(submitted_article, game_state, assignment_data)
762
- st.session_state.desk_feedback_message = feedback
763
- st.session_state.game_mode = 'reporter_action' # 피드백 표시 후 다음날로 넘어갈 수 있도록
764
- st.rerun()
765
-
766
- if st.session_state.desk_feedback_message and st.session_state.game_mode == 'reporter_action':
767
- st.divider()
768
- st.subheader(get_text_main("desk_feedback_title"))
769
- st.warning(st.session_state.desk_feedback_message) # AI 피드백 표시
770
-
771
- with col_actions_notebook: # 오른쪽 컬럼
772
- st.header("활동 기록 및 다음 단계")
773
- can_proceed_to_next_day = False
774
- if st.session_state.game_mode == 'reporter_action' and st.session_state.current_assignment_data:
775
- assignment_data = st.session_state.current_assignment_data
776
- if st.session_state.actions_taken_this_turn >= ACTIONS_PER_TURN_LIMIT:
777
- if not assignment_data.get("article_writing_phase"): # 기사 작성 없는 턴
778
- can_proceed_to_next_day = True
779
- elif st.session_state.desk_feedback_message: # 기사 작성 후 피드백까지 받은 상태
780
- can_proceed_to_next_day = True
781
-
782
- if can_proceed_to_next_day:
783
- if st.button(get_text_main("button_next_day"), use_container_width=True, key="next_day_button"):
784
- current_turn = game_state['current_turn']
785
- max_turns_for_scenario = SCENARIOS[scenario_key]['max_turns']
786
 
787
- if current_turn >= max_turns_for_scenario or st.session_state.current_assignment_data.get("is_final_turn_event", False):
788
- st.session_state.game_mode = 'assignment_over'
789
- if game_state.get('event_log') is not None:
790
- game_state['event_log'].append(get_text_main("log_assignment_over").format(scenario_name=SCENARIOS[scenario_key]['display_name']))
791
- else:
792
- game_state['current_turn'] += 1
793
- if game_state.get('event_log') is not None:
794
- game_state['event_log'].append(get_text_main("log_next_day_start").format(year=game_state['game_year'], turn=game_state['current_turn']))
795
- st.session_state.game_mode = 'assignment_briefing'
796
-
797
- st.session_state.current_assignment_data = None
798
- st.session_state.actions_taken_this_turn = 0
799
- # desk_feedback_message는 다음 턴 시작 시 assignment_briefing에서 초기화
800
- st.rerun()
801
-
802
- st.divider()
803
- st.subheader(get_text_main("term_event_log"))
804
- log_text = "\n".join(game_state.get('event_log', [])[::-1])
805
- st.text_area(get_text_main("term_event_log"), log_text, height=300, disabled=True, key="event_log_area_reporter")
806
 
807
- with st.sidebar:
808
- st.header(get_text_main("sidebar_title"))
809
- display_historical_glossary_for_reporter(scenario_key, vocab_level)
810
-
811
- st.subheader(get_text_main("sidebar_current_source_title"))
812
- if st.session_state.current_assignment_data and st.session_state.current_assignment_data.get('source_text'):
813
- st.sidebar.info(st.session_state.current_assignment_data.get('source_text'))
814
- else:
815
- st.sidebar.caption(get_text_main("sidebar_no_source"))
816
 
817
- st.divider()
818
- if st.button(get_text_main("button_back_to_scenario_select") + " (다른 시대 취재)", use_container_width=True):
819
- st.session_state.game_mode = 'scenario_select'
820
- keys_to_clear = ['current_scenario_key', 'game_state', 'current_assignment_data', 'actions_taken_this_turn', 'desk_feedback_message']
821
- for k_to_clear in keys_to_clear:
822
- if k_to_clear in st.session_state: del st.session_state[k_to_clear]
823
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
824
 
825
  elif st.session_state.game_mode != 'scenario_select' and not st.session_state.game_state:
826
  st.warning("게임 상태 정보가 유실되었습니다. 시나리오 선택 화면으로 돌아갑니다.")
827
  st.session_state.game_mode = 'scenario_select'
828
- keys_to_clear = ['current_scenario_key', 'game_state', 'current_assignment_data', 'actions_taken_this_turn', 'desk_feedback_message']
829
  for k_to_clear in keys_to_clear:
830
  if k_to_clear in st.session_state: del st.session_state[k_to_clear]
831
- time.sleep(1) # 메시지 확인 시간
832
  st.rerun()
833
 
834
  if __name__ == "__main__":
 
613
  st.sidebar.markdown(f"**{term}:** {definition}")
614
  st.sidebar.markdown("---")
615
 
616
+ # (상단 import 설정, 함수 정의 등은 기존 코드 유지)
617
+ # ... (initialize_reporter_scenario_state, get_next_assignment, process_reporter_action,
618
+ # generate_article_interface, evaluate_article_and_get_feedback_openai,
619
+ # display_reporter_dashboard, display_reporter_notebook,
620
+ # display_historical_glossary_for_reporter 등 함수 정의는 그대로 사용) ...
621
+
622
+ # --- 세션 상태 초기화 (기존과 동일) ---
623
  if 'game_mode' not in st.session_state: st.session_state.game_mode = 'scenario_select'
624
  if 'current_scenario_key' not in st.session_state: st.session_state.current_scenario_key = None
625
  if 'game_state' not in st.session_state: st.session_state.game_state = None
626
  if 'current_assignment_data' not in st.session_state: st.session_state.current_assignment_data = None
627
  if 'actions_taken_this_turn' not in st.session_state: st.session_state.actions_taken_this_turn = 0
628
  if 'desk_feedback_message' not in st.session_state: st.session_state.desk_feedback_message = None
629
+ if 'active_main_tab' not in st.session_state: st.session_state.active_main_tab = "취재 브리핑" # 기본 활성 탭
630
 
631
  # --- 메인 게임 로직 (기자 컨셉) ---
632
  def reporter_simulation_main():
 
637
 
638
  st.title(get_text_main("game_title"))
639
 
640
+ # --- 시나리오 선택 (기존과 동일) ---
641
  if st.session_state.game_mode == 'scenario_select':
642
  st.header(get_text_main("scenario_select_title"))
643
  scenario_descriptions = {
 
657
  st.session_state.actions_taken_this_turn = 0
658
  st.session_state.desk_feedback_message = None
659
  st.session_state.game_mode = 'assignment_briefing'
660
+ st.session_state.active_main_tab = "취재 브리핑" # 탭 초기화
661
  st.rerun()
662
  st.stop()
663
 
664
+ # --- 게임 진행 ---
665
  if st.session_state.game_mode != 'scenario_select' and st.session_state.game_state:
666
  game_state = st.session_state.game_state
667
  scenario_key = st.session_state.current_scenario_key
668
  vocab_level = SCENARIOS[scenario_key]["vocab_level"]
669
  get_text_main = lambda key: get_text(key, vocab_level)
670
 
671
+ # --- 사이드바 구성 ---
672
+ with st.sidebar:
673
+ st.header(get_text_main("dashboard_title"))
674
+ st.caption(f"시나리오: {SCENARIOS[scenario_key]['display_name']}")
675
+ st.caption(f"역할: {game_state['player_role']}")
676
+ st.markdown(f"**{get_text_main('dashboard_term').format(year=game_state['game_year'], turn=game_state['current_turn'])}**")
677
+ display_reporter_dashboard(game_state) # 핵심 지표 표시
678
+ st.markdown("---")
679
+
680
+ if st.button(get_text_main("button_next_day"), use_container_width=True, key="next_day_button_sidebar",
681
+ disabled=(st.session_state.game_mode == 'article_writing' or
682
+ (st.session_state.game_mode == 'reporter_action' and
683
+ st.session_state.actions_taken_this_turn < ACTIONS_PER_TURN_LIMIT and
684
+ st.session_state.current_assignment_data and
685
+ len(st.session_state.current_assignment_data.get("options", [])) > 0
686
+ ) # 아직 할 수 있는 액션이 남았거나 기사 작성 중이면 비활성화
687
+ )
688
+ ):
689
+ current_turn = game_state['current_turn']
690
+ max_turns_for_scenario = SCENARIOS[scenario_key]['max_turns']
691
+
692
+ if current_turn >= max_turns_for_scenario or \
693
+ (st.session_state.current_assignment_data and st.session_state.current_assignment_data.get("is_final_turn_event", False)):
694
+ st.session_state.game_mode = 'assignment_over'
695
+ if game_state.get('event_log') is not None:
696
+ game_state['event_log'].append(get_text_main("log_assignment_over").format(scenario_name=SCENARIOS[scenario_key]['display_name']))
697
+ else:
698
+ game_state['current_turn'] += 1
699
+ if game_state.get('event_log') is not None:
700
+ game_state['event_log'].append(get_text_main("log_next_day_start").format(year=game_state['game_year'], turn=game_state['current_turn']))
701
+ st.session_state.game_mode = 'assignment_briefing'
702
+
703
+ st.session_state.current_assignment_data = None
704
+ st.session_state.actions_taken_this_turn = 0
705
+ st.session_state.desk_feedback_message = None # 피드백 초기화
706
+ st.session_state.active_main_tab = "취재 브리핑" # 탭 초기화
707
+ st.rerun()
708
+
709
+ st.markdown("---")
710
+ display_historical_glossary_for_reporter(scenario_key, vocab_level)
711
+
712
+ st.subheader(get_text_main("sidebar_current_source_title"))
713
+ if st.session_state.current_assignment_data and st.session_state.current_assignment_data.get('source_text'):
714
+ st.sidebar.info(st.session_state.current_assignment_data.get('source_text'))
715
+ else:
716
+ st.sidebar.caption(get_text_main("sidebar_no_source"))
717
 
718
+ st.markdown("---")
719
+ if st.button(get_text_main("button_back_to_scenario_select") + " (다른 시대 취재)", use_container_width=True):
720
+ st.session_state.game_mode = 'scenario_select'
721
+ keys_to_clear = ['current_scenario_key', 'game_state', 'current_assignment_data', 'actions_taken_this_turn', 'desk_feedback_message', 'active_main_tab']
722
+ for k_to_clear in keys_to_clear:
723
+ if k_to_clear in st.session_state: del st.session_state[k_to_clear]
724
+ st.rerun()
725
+
726
+ # --- 취재 기간 종료 처리 ---
727
  if st.session_state.game_mode == 'assignment_over':
728
  st.balloons()
729
  st.header(get_text_main("assignment_over_title"))
730
  st.subheader(get_text_main("assignment_over_subtitle"))
731
+ # 최종 대시보드는 사이드바에 이미 표시됨
732
+
733
  st.subheader("송고한 주요 기사 목록")
734
  if game_state['submitted_articles']:
735
+ for article_idx, article in enumerate(game_state['submitted_articles']):
736
  tone_text_key = f"article_tone_{article['tone']}"
737
  tone_display_text = get_text_main(tone_text_key)
738
+ # AI 점수는 article 딕셔너리에 저장해야 (evaluate 함수에서)
739
+ ai_score = article.get('ai_score', 'N/A') # 'ai_score' 키로 저장했다고 가정
740
+ st.markdown(f"- **{article['headline']}** (논조: {tone_display_text}) - {article['turn']}일차 송고 (AI 점수: {ai_score}점)")
741
  else:
742
  st.caption("이번 취재 기간 동안 송고한 기사가 없습니다.")
743
 
744
+ with st.expander(get_text_main("term_event_log"), expanded=False):
745
+ log_text = "\n".join(game_state.get('event_log', [])[::-1])
746
+ st.text_area("로그 내용", log_text, height=250, disabled=True, key="final_log_reporter_main")
747
+
748
+ if st.button(get_text_main("button_restart_assignment"), key="restart_assignment_main_btn"):
749
+ st.session_state.game_state = initialize_reporter_scenario_state(scenario_key)
750
+ st.session_state.current_assignment_data = None
751
+ st.session_state.actions_taken_this_turn = 0
752
+ st.session_state.desk_feedback_message = None
753
+ st.session_state.game_mode = 'assignment_briefing'
754
+ st.session_state.active_main_tab = "취재 브리핑"
755
+ st.rerun()
 
 
 
 
 
 
 
 
756
  st.stop()
757
 
 
758
 
759
+ # --- 메인 콘텐츠 영역 ---
760
+ # 탭 대신 단계별 UI 전환 또는 주요 정보만 표시하는 방식으로 변경 가능
761
+ # 여기서는 주요 정보를 먼저 표시하고, 액션은 버튼으로 유도
762
+
763
+ # 1. 오늘의 취재 지시 로드 (assignment_briefing 모드에서 처리)
764
+ if st.session_state.game_mode == 'assignment_briefing':
765
+ if st.session_state.current_assignment_data is None:
766
+ spinner_text = get_text_main('status_loading_assignment').format(year=game_state['game_year'], turn=game_state['current_turn'])
767
+ with st.spinner(spinner_text):
768
+ time.sleep(0.5)
769
+ assignment = get_next_assignment(scenario_key, game_state['current_turn'], game_state)
770
+ if assignment:
771
+ st.session_state.current_assignment_data = assignment
772
+ st.session_state.actions_taken_this_turn = 0
773
+ st.session_state.desk_feedback_message = None # 이전 피드백 초기화
774
+ st.session_state.game_mode = 'reporter_action' # 바로 취재 활동으로
775
+ st.session_state.active_main_tab = "취재 활동" # 탭 전환
776
+ st.rerun()
777
+ else:
778
+ st.session_state.game_mode = 'assignment_over'
779
+ if game_state.get('event_log') is not None:
780
+ game_state['event_log'].append(get_text_main("log_assignment_over").format(scenario_name=SCENARIOS[scenario_key]['display_name']))
781
+ st.rerun()
782
+
783
+ # 메인 화면에 현재 취재 지시 표시
784
+ if st.session_state.current_assignment_data:
785
+ assignment_data = st.session_state.current_assignment_data
786
+ st.header(get_text_main("current_assignment_title"))
787
+ st.subheader(f"{assignment_data['assignment_text']}")
788
+ # 배경 정보는 사이드바로 이동했으므로 여기서는 생략 가능
789
+ st.markdown("---")
790
+
791
+ # 탭으로 주요 활동 구분
792
+ tab_titles = ["🎤 취재 활동"]
793
+ if st.session_state.current_assignment_data and st.session_state.current_assignment_data.get("article_writing_phase"):
794
+ tab_titles.append("🖋️ 기사 작성")
795
+ if st.session_state.desk_feedback_message:
796
+ tab_titles.append("📢 AI 편집장 평가")
797
+
798
+ # 탭 상태 관리 (선택된 탭 유지)
799
+ if 'active_main_tab' not in st.session_state or st.session_state.active_main_tab not in tab_titles:
800
+ st.session_state.active_main_tab = tab_titles[0] # 기본값 또는 유효한 값으로 설정
801
+
802
+ # 현재 활성화된 탭을 selected_tab으로 사용
803
+ # selected_tab = st.radio("메인 활동 선택:", tab_titles, horizontal=True, key="main_activity_radio", index=tab_titles.index(st.session_state.active_main_tab))
804
+ # st.session_state.active_main_tab = selected_tab # 선택된 탭 업데이트
805
+ # radio 대신 st.tabs 사용
806
+
807
+ tabs_ui = st.tabs(tab_titles)
808
 
809
+ with tabs_ui[0]: # 취재 활동 탭
810
+ # st.header(get_text_main("reporter_actions_title")) # 탭 이름으로 대체
811
  if st.session_state.game_mode == 'reporter_action' and st.session_state.current_assignment_data:
812
  assignment_data = st.session_state.current_assignment_data
 
 
 
 
 
 
 
 
813
  if st.session_state.actions_taken_this_turn < ACTIONS_PER_TURN_LIMIT:
814
+ st.write(f"남은 활동 횟수: {ACTIONS_PER_TURN_LIMIT - st.session_state.actions_taken_this_turn}")
815
  for i, opt in enumerate(assignment_data['options']):
816
  risk_info = []
817
  if opt.get('cost_freedom_risk',0) > 0: risk_info.append(f"자유도↓{opt['cost_freedom_risk']}%")
 
821
 
822
  if st.button(button_label, key=f"rep_action_{game_state['current_turn']}_{i}_{scenario_key}", use_container_width=True):
823
  process_reporter_action(opt, game_state)
824
+ # 취재 활동 후 바로 기사 작성 탭으로 이동할지, 아니면 현재 탭 유지할지 결정 필요
825
+ # 여기서는 현재 탭 유지하고, 모든 활동 끝나면 기사 작성 버튼 활성화
826
  st.rerun()
827
  else:
828
  st.info(get_text_main("status_actions_taken"))
829
+ if assignment_data.get("article_writing_phase") and "🖋️ 기사 작성" in tab_titles:
830
+ st.success("모든 취재 활동을 마쳤습니다. '기사 작성' 탭으로 이동하여 기사를 작성하세요.")
831
+ # 자동으로 탭 이동은 어려우므로 사용자에게 안내
832
+ elif not assignment_data.get("article_writing_phase"):
833
+ st.success("오늘의 모든 취재 활동을 마쳤습니다. 사이드바에서 '다음 날로' 버튼을 눌러 진행하세요.")
834
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
835
 
836
+ with st.expander("📝 나의 취재 노트 보기", expanded=False):
837
+ display_reporter_notebook(game_state, vocab_level)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
838
 
 
 
 
 
 
 
 
 
 
839
 
840
+ if "🖋️ 기사 작성" in tab_titles:
841
+ with tabs_ui[tab_titles.index("🖋️ 기사 작성")]:
842
+ if st.session_state.game_mode in ['reporter_action', 'article_writing'] and \
843
+ st.session_state.current_assignment_data and \
844
+ st.session_state.current_assignment_data.get("article_writing_phase") and \
845
+ st.session_state.actions_taken_this_turn >= ACTIONS_PER_TURN_LIMIT: # 모든 취재 활동을 마친 후
846
+
847
+ # 기사 작성 중이 아니면, 작성 모드로 변경
848
+ if st.session_state.game_mode != 'article_writing':
849
+ st.session_state.game_mode = 'article_writing'
850
+ # st.rerun() # generate_article_interface를 바로 호출하므로 rerun 불필요
851
+
852
+ assignment_data = st.session_state.current_assignment_data
853
+ submitted_article = generate_article_interface(game_state, vocab_level)
854
+ if submitted_article:
855
+ feedback = evaluate_article_and_get_feedback_openai(submitted_article, game_state, assignment_data)
856
+ st.session_state.desk_feedback_message = feedback
857
+ st.session_state.game_mode = 'reporter_action' # 피드백 표시 및 다음날로 진행 가능하도록
858
+ st.session_state.active_main_tab = "📢 AI 편집장 평가" if "📢 AI 편집장 평가" in tab_titles else "🎤 취재 활동"
859
+ st.rerun()
860
+ elif not (st.session_state.current_assignment_data and st.session_state.current_assignment_data.get("article_writing_phase")):
861
+ st.info("이번 턴에는 기사 작성이 예정되어 있지 않습니다.")
862
+ elif st.session_state.actions_taken_this_turn < ACTIONS_PER_TURN_LIMIT:
863
+ st.info(f"아직 오늘의 취재 활동이 남았습니다. (남은 활동: {ACTIONS_PER_TURN_LIMIT - st.session_state.actions_taken_this_turn}회)")
864
+
865
+
866
+ if "📢 AI 편집장 평가" in tab_titles:
867
+ with tabs_ui[tab_titles.index("📢 AI 편집장 평가")]:
868
+ if st.session_state.desk_feedback_message:
869
+ st.subheader(get_text_main("desk_feedback_title"))
870
+ st.warning(st.session_state.desk_feedback_message)
871
+ st.info("평가를 확인했으면 사이드바에서 '다음 날로' 버튼을 눌러 진행하세요.")
872
+ else:
873
+ st.info("아직 평가된 기사가 없습니다. 기사를 먼저 작성하고 송고해주세요.")
874
+
875
+ st.markdown("---")
876
+ with st.expander(get_text_main("term_event_log") + " (최근 10개)", expanded=False):
877
+ log_text = "\n".join(game_state.get('event_log', [])[-10:][::-1]) # 최근 10개만 표시
878
+ st.text_area("로그 내용", log_text, height=200, disabled=True, key="event_log_area_reporter_main")
879
 
880
  elif st.session_state.game_mode != 'scenario_select' and not st.session_state.game_state:
881
  st.warning("게임 상태 정보가 유실되었습니다. 시나리오 선택 화면으로 돌아갑니다.")
882
  st.session_state.game_mode = 'scenario_select'
883
+ keys_to_clear = ['current_scenario_key', 'game_state', 'current_assignment_data', 'actions_taken_this_turn', 'desk_feedback_message', 'active_main_tab']
884
  for k_to_clear in keys_to_clear:
885
  if k_to_clear in st.session_state: del st.session_state[k_to_clear]
886
+ time.sleep(1)
887
  st.rerun()
888
 
889
  if __name__ == "__main__":