Dev Log - dopple

  • 20251212

Compact Log 1

  • 20251212 14:30

SpeakQuest 평가 결과 표시 시스템 구현 완료

RequestSpeakingJudges 평가 결과를 UToastWidget을 통해 표시하고 PlayerState에 저장하는 시스템을 구현했습니다.

변경 파일:

  • NetworkData.h/cpp: FSpeakStageQuestion 구조를 실제 API 형식에 맞춰 정리 (kor/eng/pronunciation/voice_data)
  • ALingoPlayerState.h/cpp: speakEvaluationResults 배열 추가, Server_AddSpeakEvaluationResult RPC 구현
  • AWheatly.h/cpp: BeginSpeakQuest/CompleteSpeakQuest 함수 구현, UBroadcastManager 연동
  • UVoiceConversationSystem.cpp: OnResponseSpeakingsJudges에서 평가 결과 PlayerState 저장 로직 추가
  • UKLingoNetworkSystem.cpp: 헤더 포함 추가

주요 작업:

  1. 평가 결과 저장 시스템

    • ALingoPlayerState에 speakEvaluationResults 배열 추가 (Replicated)
    • Server_AddSpeakEvaluationResult RPC로 서버 측 평가 결과 저장
  2. AWheatly SpeakQuest 워크플로우

    • BeginSpeakQuest: RequestSpeakScenario 호출하여 질문 데이터 로드, PlayerState에 저장
    • CompleteSpeakQuest: UBroadcastManager를 통해 축적된 모든 평가 결과를 UToastWidget으로 표시
    • OnInteractionTriggered: bIsBusy 플래그로 턴 기반 NPC 접근 제어
  3. UToastWidget 연동

    • SendTutorMessage: final_feedback 메시지 표시
    • SendAddItemToBoxList: grammar_score/context_score/final_overall_score를 FResultStatData로 변환하여 아이템 박스 표시
  4. 네트워크 데이터 구조 정리

    • FSpeakStageQuestion을 실제 API 응답 형식에 맞춰 수정
    • FResponseSpeakScenario의 audio 배열 파싱 로직 구현
    • 불필요한 구조체 제거 (FResponseSpeakQuest, FResponseEvaluation 등)
  5. 평가 결과 표시 흐름

    • 즉시 표시: 각 질문 평가 완료 시 UToastWidget으로 즉시 표시 (기존 동작 유지)
    • 요약 표시: SpeakQuest 완료 시 모든 축적된 평가 결과를 다시 표시
    • 결과 초기화: 표시 후 다음 퀘스트를 위해 배열 클리어

Commit 정보

Summary (EN): feat: implement SpeakQuest evaluation result display system

세부 내역:

  1. "Add evaluation result tracking in PlayerState"

    • speakEvaluationResults 배열 추가 (Replicated)
    • Server_AddSpeakEvaluationResult RPC 구현
  2. "Implement SpeakQuest workflow in AWheatly"

    • BeginSpeakQuest: RequestSpeakScenario API 호출, 질문 데이터 로드
    • CompleteSpeakQuest: 축적된 평가 결과를 UToastWidget으로 표시
    • 턴 기반 NPC 접근 제어 (bIsBusy 플래그)
  3. "Integrate UToastWidget for evaluation display"

    • UBroadcastManager를 통한 SendTutorMessage/SendAddItemToBoxList 호출
    • FResponseSpeakingJudes::GetResultStatData()를 활용한 데이터 변환
  4. "Connect VoiceConversationSystem to PlayerState"

    • OnResponseSpeakingsJudges에서 Server_AddSpeakEvaluationResult 호출
    • 평가 결과 서버 저장 및 복제
  5. "Align network data structures with actual API"

    • FSpeakStageQuestion 구조 변경 (kor/eng/pronunciation/voice_data)
    • FResponseSpeakScenario audio 배열 파싱
    • 미사용 구조체 제거

기술적 특징

  • 서버 권한 관리: HasAuthority() 검증으로 모든 SpeakQuest 로직은 서버에서만 실행
  • 네트워크 복제: DOREPLIFETIME으로 speakEvaluationResults, speakQuestData 복제
  • 턴 기반 멀티플레이: bIsBusy 플래그로 동시 접근 방지, busyPlayerName으로 현재 사용자 표시
  • 델리게이트 기반 비동기 처리: FResponseSpeakScenarioDelegate, FResponseSpeakingJudesDelegate 활용
  • 브로드캐스트 패턴: UBroadcastManager를 통한 느슨한 결합

KLingo SpeakQuest 개발 Phase 진행 상황

참고: Documents/DevLog/AgentLog/KLingo_Speak_Prompt.md

Phase 1: 기반 구조 (High Priority) - ✅ 부분 완료

완료 항목:

  • FSpeakStageQuestion 구조체 정의 (실제 API 형식 반영)
  • AWheatly (NPC) InteractComponent 기반 상호작용 구현
  • ALingoPlayerState SpeakQuest 데이터 추가
    • SpeakScenarioData: FResponseSpeakScenario (질문 데이터)
    • CurSpeakQuestStep: 현재 진행 단계
    • SpeakJudesResults: 평가 결과 배열

미완료 항목:

  • ASpeakStageActor 턴 기반 대화 관리자 구현
    • 플레이어 큐 관리 (PlayerQueue)
    • 턴 전환 로직 (AdvanceToNextPlayer)
    • 현재 발화자 추적 (GetCurrentSpeaker)
    • 대화 참가 요청 처리 (RequestJoinConversation)

Phase 2: 네트워크 통합 (High Priority) - ✅ 완료

  • FResponseSpeakScenario 응답 구조체 추가 및 파싱
  • FResponseSpeakingJudes 평가 결과 구조체 활용
  • UKLingoNetworkSystem::RequestSpeakScenario API 연동
  • UKLingoNetworkSystem::RequestSpeakingJudges 기존 시스템 활용
  • ✅ 네트워크 로깅 통합 (PRINTLOG, NETWORK_LOG)
  • ✅ Server RPC: Server_AddSpeakJudes 평가 결과 저장

Phase 3: 음성 시스템 (Medium Priority) - 🔄 진행 중

완료 항목:

  • UVoiceConversationSystem::OnResponseSpeakingsJudges 평가 결과 처리
  • ✅ 평가 결과를 PlayerState에 저장하는 로직 연동
  • ✅ 기존 녹음 시스템 (IA_Record) 활용

미완료 항목:

  • APlayerControl 녹음 입력 핸들러 확장
    • OnRecordPressed/OnRecordReleased SpeakQuest 모드 처리
    • 녹음 시작/종료 시 UI 업데이트
  • ⬜ 질문 음성 재생 로직 (PlayQuestionAudio)
  • ⬜ STT 통합 및 음성 데이터 제출 (ServerRPC_SubmitAnswer)

Phase 4: UI 및 피드백 (Medium Priority) - 🔄 진행 중

완료 항목:

  • UToastWidget 연동 (UBroadcastManager 활용)
    • SendTutorMessage: 피드백 메시지 표시
    • SendAddItemToBoxList: 평가 점수 아이템 박스 표시
  • AWheatly::CompleteSpeakQuest 완료 화면 표시

미완료 항목:

  • UMainWidget SpeakQuest 전용 UI 추가
    • 질문 텍스트 표시 (ShowSpeakQuestion)
    • 진행률 표시 위젯
    • 녹음 상태 인디케이터
  • ⬜ 최종 결과 화면 (ShowSpeakQuestResult)
  • ⬜ 질문 다시 듣기 버튼 (IA_Replay InputAction)
  • ⬜ 답변 제출 후 피드백 표시 (ClientRPC_ShowAnswerFeedback)

Phase 5: 테스트 및 최적화 (Low Priority) - ⬜ 미착수

  • ⬜ 단일 플레이어 테스트
  • ⬜ 멀티플레이어 턴 전환 검증
  • ⬜ 네트워크 지연 시뮬레이션
  • ⬜ 디버그 시각화
    • NPC 시선 처리 (DrawDebugLine)
    • 배제 영역 시각화 (exclusionSphere)
  • ⬜ 성능 최적화

다음 작업 우선순위

🔥 High Priority (즉시 진행)

  1. ASpeakStageActor 턴 기반 아키텍처 구현

    • KLingo_SpeakScenario.md 명세 준수
    • PlayerQueue 관리
    • 턴 전환 로직
    • AWheatly와 연동
  2. 음성 녹음 및 답변 제출 로직

    • APlayerControl::ServerRPC_SubmitAnswer 구현
    • VoiceConversationSystem 녹음 데이터 가져오기
    • RequestSpeakingJudges API 호출

📌 Medium Priority (다음 단계)

  1. 질문 음성 재생 시스템

    • VoiceConversationSystem::PlayQuestionAudio 확장
    • voice_data Base64 디코딩 및 재생
  2. SpeakQuest 전용 UI 구현

    • UMainWidget::ShowSpeakQuestion 추가
    • 진행률 및 녹음 상태 표시

🔹 Low Priority (추후 진행)

  1. 테스트 및 디버깅
    • 멀티플레이어 턴 전환 테스트
    • 네트워크 동기화 검증

참고 문서

  • 개발 명세: Documents/DevLog/AgentLog/KLingo_Speak_Prompt.md
  • 아키텍처: Documents/DevLog/AgentLog/KLingo_SpeakScenario.md
  • 코딩 컨벤션: AgentRule/Project/Onepiece/CODING_CONVENTIONS.md

Compact Log 2

  • 20251212 15:30

SpeakQuest 아키텍처 리팩토링 및 버그 수정

요구사항 변경(플레이어 큐 불필요)에 따라 SpeakQuest의 아키텍처를 '단일 사용자 모델'로 리팩토링하고, 관련 버그를 수정했습니다.

변경 파일:

  • Source/Onepiece/Game/Public/ASpeakStageActor.h: 큐(Queue) 관련 로직 제거 및 함수명/변수명 컨벤션 수정
  • Source/Onepiece/Game/Private/ASpeakStageActor.cpp: 단일 사용자 모델에 맞게 로직 단순화 및 컨벤션 수정
  • Source/Onepiece/Character/Public/AWheatly.h: ASpeakStageActor로 상태 관리를 이전함에 따라 불필요해진 상태 변수 제거
  • Source/Onepiece/Character/Private/AWheatly.cpp: ASpeakStageActor를 유일한 정보 소스로 사용하도록 로직 변경 및 Tick을 이용한 시각적 상태 동기화
  • Source/Onepiece/Voice/Private/UVoiceConversationSystem.cpp: 녹음 시작 시, 퀘스트 상태에 따른 사용자 피드백 메시지 개선

주요 작업:

  1. SpeakQuest 아키텍처 단순화

    • ASpeakStageActor에서 플레이어 큐(Queue) 시스템을 제거하고, 한 번에 한 명의 플레이어만 관리하는 'Busy/Available' 모델로 변경했습니다.
    • PlayStart -> StartStageForPlayer, AdvanceToNextPlayer -> EndStage로 함수를 변경하여 역할을 명확히 했습니다.
  2. 상태 관리 책임 이전

    • AWheatly가 자체적으로 관리하던 bIsBusy, busyPlayerName 등의 중복 상태 변수를 모두 제거했습니다.
    • 이제 AWheatlyASpeakStageActorGetCurrentSpeaker()를 유일한 정보 소스(Single Source of Truth)로 사용하여 퀘스트의 진행 상태를 확인합니다.
  3. 버그 수정 및 사용자 피드백 개선

    • 퀘스트가 시작되지 않은 상태에서 녹음을 시도하면 CurrentSpeakernullptr이 되어 진행이 막히던 최초 버그를 해결했습니다.
    • UVoiceConversationSystem에서 녹음이 불가능할 경우, "NPC와 대화하여 심사를 시작하세요"와 같이 명확한 안내 메시지를 표시하도록 개선했습니다.
  4. 코딩 컨벤션 적용

    • ASpeakStageActor의 변수명을 camelCase로, RPC 함수명을 ServerRPC_ 접두사 규칙에 맞게 수정하여 코드 품질을 향상시켰습니다.

Commit 정보

Summary (EN): refactor: simplify SpeakQuest to single-user model and fix state management

세부 내역:

  1. "Refactor ASpeakStageActor to single-user model"

    • Removed PlayerQueue and related logic.
    • Renamed PlayStart to StartStageForPlayer for clarity.
    • Simplified stage completion logic with EndStage function.
    • Applied coding conventions (camelCase, RPC prefixes).
  2. "Centralize quest state management in ASpeakStageActor"

    • Removed redundant state variables (bIsBusy, busyPlayerName) from AWheatly.
    • AWheatly now relies on ASpeakStageActor::GetCurrentSpeaker() as the single source of truth.
    • Visual state (eye color) in AWheatly is now synced via Tick.
  3. "Improve user feedback for voice recording"

    • Updated UVoiceConversationSystem to show a clear message ("Start by talking to the NPC") when trying to record before the quest has started.

Next To Do

  1. 데이터 모델 일관성 확보: ASpeakStageActorTArray 대신 FSpeakStageQuestion 구조체를 사용하도록 리팩토링.
  2. 네트워크 연동: ASpeakStageActorCreateTestScenarioData 대신 UKLingoNetworkSystem을 통해 실제 퀘스트 데이터를 받아오도록 수정.
  3. UI 구현: UMainWidget에 SpeakQuest 전용 UI(질문 표시, 진행 상황 등) 추가.

Compact Log 3

  • 20251212 20:54

SpeakQuest 데이터 모델 통합 및 음성 재생 완성

Compact Log 2의 Next To Do #1, #2를 완료하고, SpeakQuest의 핵심 기능을 완성했습니다.

변경 파일:

  • Source/Onepiece/Game/Public/ASpeakStageActor.h: 하드코딩된 질문 데이터 제거 및 함수 시그니처 변경
  • Source/Onepiece/Game/Private/ASpeakStageActor.cpp: PlayerState 기반 데이터 모델로 전면 리팩토링, 음성 재생 로직 추가

주요 작업:

  1. 데이터 모델 일관성 확보 (Next To Do #1)

    • TArray questions 제거
    • TArray questions_Voice 제거
    • CreateTestScenarioData() 함수 완전 제거
    • 모든 질문 데이터를 PlayerState의 SpeakScenarioData.speak_quest_data (FSpeakStageQuestion 배열)에서 동적으로 가져오도록 변경
    • GetCurrentQuestion(), GetTotalQuestions(), AdvanceStep(), ShowCurrentQuestionToast() 모두 PlayerState 기반으로 리팩토링
  2. 네트워크 연동 완료 (Next To Do #2)

    • ASpeakStageActor는 이제 PlayerState의 데이터만 사용
    • AWheatly의 RequestSpeakScenario API 호출로 받아온 네트워크 데이터가 유일한 정보 소스(Single Source of Truth)
    • 테스트 데이터 의존성 완전 제거
  3. 다음 질문 음성 재생 로직 추가

    • AdvanceStep()에서 다음 질문으로 진행 시 자동으로 PlayTTSAudio() 호출
    • currentSpeaker의 Pawn을 통해 APlayerActor에 접근하여 음성 재생 요청
    • FSpeakStageQuestion의 voice_data (Base64 인코딩된 음성 데이터) 사용
  4. 전체 워크플로우 완성

    • ✅ NPC 상호작용 → API에서 질문 데이터 로드 (AWheatly)
    • ✅ 첫 질문 음성 재생 (AWheatly::OnResponseSpeakScenario)
    • ✅ 플레이어 녹음 및 답변 제출 (UVoiceConversationSystem)
    • ✅ 평가 결과 표시 및 저장 (UVoiceConversationSystem::OnResponseSpeakingsJudges)
    • 다음 질문으로 자동 진행 + 음성 재생 (ASpeakStageActor::AdvanceStep) ← 신규
    • ✅ 모든 질문 완료 시 종료 처리 (ASpeakStageActor::EndStage)

기술적 세부사항

데이터 흐름:

1. AWheatly::RequestSpeakScenario
   → API 호출
   → PlayerState->SpeakScenarioData 저장

2. ASpeakStageActor::StartStageForPlayer
   → currentSpeaker 설정
   → ShowCurrentQuestionToast (첫 질문)

3. AWheatly::OnResponseSpeakScenario
   → PlayTTSAudio(speak_quest_data[0].voice_data) (첫 질문 음성)

4. 플레이어 녹음 → 평가 → ServerRPC_NotifyAnswerComplete

5. ASpeakStageActor::AdvanceStep
   → currentStepIndex++
   → PlayTTSAudio(speak_quest_data[currentStepIndex].voice_data) (다음 질문 음성)
   → ShowCurrentQuestionToast (다음 질문 Toast)

PlayerState 의존성:

  • GetCurrentQuestion(): PS->SpeakScenarioData.speak_quest_data[currentStepIndex].GetQuestionMessage()
  • GetTotalQuestions(): PS->SpeakScenarioData.speak_quest_data.Num()
  • AdvanceStep(): PS->SpeakScenarioData.speak_quest_data.IsValidIndex(currentStepIndex)
  • ShowCurrentQuestionToast(): 전체 질문 수를 PlayerState에서 동적으로 계산

Commit 정보

Summary (EN): refactor: integrate PlayerState data model and complete audio playback for SpeakQuest

세부 내역:

  1. "Remove hardcoded test data from ASpeakStageActor"

    • Removed TArray questions, TArray questions_Voice
    • Removed CreateTestScenarioData() function
    • Changed BeginPlay() to skip test data generation
  2. "Refactor all data access to use PlayerState"

    • GetCurrentQuestion() now retrieves data from PlayerState->SpeakScenarioData
    • GetTotalQuestions() dynamically calculates from PlayerState
    • AdvanceStep() and ShowCurrentQuestionToast() use PlayerState as single source of truth
  3. "Add automatic audio playback for next questions"

    • AdvanceStep() now calls PlayTTSAudio() with current question's voice_data
    • Audio playback triggered for all questions (not just the first one)
    • Added include for APlayerActor.h
  4. "Complete end-to-end SpeakQuest workflow"

    • All questions now have proper audio playback
    • Seamless progression from question to question
    • Network data integration complete

검증 완료 항목

Phase 3: 음성 시스템 - ✅ 완료

  • ✅ 첫 질문 음성 재생 (AWheatly)
  • ✅ 다음 질문 음성 재생 (ASpeakStageActor::AdvanceStep)
  • ✅ 음성 녹음 시스템 (UVoiceConversationSystem::StartRecording)
  • ✅ 턴 기반 녹음 제어 (StartRecording의 턴 체크 로직)
  • ✅ STT 통합 (UVoiceConversationSystem::StopRecording → RequestSpeakingJudges)
  • ✅ 평가 결과 처리 (OnResponseSpeakingsJudges)

남은 작업 (선택적):

  • ⬜ UMainWidget SpeakQuest 전용 UI (현재는 Toast로 충분히 작동)
  • ⬜ 질문 다시 듣기 버튼 (IA_Replay InputAction)
  • ⬜ 진행률 표시 위젯 (선택적 개선사항)

결론

SpeakQuest의 핵심 기능(네트워크 데이터 연동, 음성 재생, 녹음 및 평가)이 모두 완성되었습니다. PlayerState를 Single Source of Truth로 사용하는 깔끔한 아키텍처로 리팩토링되었으며, 전체 워크플로우가 원활하게 동작합니다.

results matching ""

    No results matching ""