KLingo Project Documentation 1.0.0
Unreal Engine 5.6 C++ Project Documentation
로딩중...
검색중...
일치하는것 없음
ADailyKiosk.cpp
이 파일의 문서화 페이지로 가기
1// Copyright (c) 2025 Doppleddiggong. All rights reserved. Unauthorized copying, modification, or distribution of this file, via any medium is strictly prohibited. Proprietary and confidential.
2
3#include "ADailyKiosk.h"
4
5#include "GameLogging.h"
6#include "UInteractWidget.h"
9#include "UPopupManager.h"
10#include "UPopup_DailyStudy.h"
11#include "UGameDataManager.h"
13#include "Components/BoxComponent.h"
14#include "Components/WidgetComponent.h"
15#include "Onepiece/Onepiece.h"
16
17#define DAILYKIOSK_INTERACT_WIDGET_PATH TEXT("/Game/CustomContents/UI/Widgets/WBP_InteractWidget_Daily.WBP_InteractWidget_Daily_C")
18
20{
21 PrimaryActorTick.bCanEverTick = false;
22
23 RootSceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("RootSceneComp"));
24 SetRootComponent(RootSceneComp);
25
26 MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
27 MeshComp->SetupAttachment(RootComponent);
28
29 InteractableComp = CreateDefaultSubobject<UInteractableComponent>(TEXT("Interactable"));
30 InteractableComp->InteractionType = EInteractionType::Kiosk;
31 InteractableComp->InteractionPrompt = TEXT("Activate");
32
33 BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
34 BoxComp->SetupAttachment(GetRootComponent());
35 BoxComp->SetRelativeLocation(FVector(0, 36, 75));
36 BoxComp->SetBoxExtent(FVector(60, 65, 92));
37
38 WidgetComp = CreateDefaultSubobject<UWidgetComponent>(TEXT("WidgetComp"));
39 ConstructorHelpers::FClassFinder<UInteractWidget> WidgetRef(DAILYKIOSK_INTERACT_WIDGET_PATH);
40 if (WidgetRef.Succeeded())
41 {
42 WidgetComp->SetWidgetClass(WidgetRef.Class);
43 WidgetComp->SetupAttachment(GetRootComponent());
44 WidgetComp->SetWidgetSpace(EWidgetSpace::Screen);
45 WidgetComp->SetDrawSize(FVector2D(2048.0f, 1024.0f));
46 }
47}
48
50{
51 Super::BeginPlay();
52
53 // 델리게이트 바인딩
54 InteractableComp->InitWidget(WidgetComp);
55 InteractableComp->OnInteractionTriggered.AddDynamic(this, &ADailyKiosk::OnInteractionTriggered);
56 InteractableComp->OnOutlineStateChanged.AddDynamic(this, &ADailyKiosk::OnOutlineStateChanged);
57}
58
60{
61 // ChatDaily API 요청
62 if (auto KLingoNetwork = UKLingoNetworkSystem::Get(GetWorld()))
63 {
64 PRINTLOG(TEXT("[DailyKiosk] Requesting daily question..."));
65 KLingoNetwork->RequestDailyQuestion(
68 FResponseChatDailysDelegate::CreateUObject(this, &ADailyKiosk::OnResponseDailyQuestion)
69 );
70 }
71}
72
73void ADailyKiosk::OnResponseDailyQuestion(FResponseChatDailys& InResponseData, bool bWasSuccessful)
74{
75 if (!bWasSuccessful)
76 {
77 PRINTLOG(TEXT("[DailyKiosk] Network request failed. Using fallback word data."));
78
79 // 네트워크 실패 시 랜덤 단어 데이터로 대체
80 TArray<FWordData> FallbackWordData = GetRandomKoreanWords(DefineData::MIN_REQUIRED_WORDS);
81
82 if (FallbackWordData.Num() > 0)
83 {
84 if (UPopup_DailyStudy* DailyStudyPopup = UPopupManager::Get(GetWorld())->ShowPopupAs<UPopup_DailyStudy>(EPopupType::DailyStudy))
85 {
86 DailyStudyPopup->InitPopup(FallbackWordData);
87 }
88 }
89 else
90 {
91 PRINTLOG(TEXT("[DailyKiosk] ERROR: No fallback data available!"));
92 }
93
94 return;
95 }
96
97 // AI 응답을 | 구분자로 파싱 (형식: "개|DOG|Gae|고양이|CAT|Go-yang-i")
98 TArray<FString> RawTokens;
99 InResponseData.answer.ParseIntoArray(RawTokens, TEXT("|"), true);
100
101 // 3개씩 묶어서 FWordData로 변환 (Kor|Eng|Pronunciation)
102 TArray<FWordData> ValidWordDataArray;
103 for (int32 i = 0; i + 2 < RawTokens.Num(); i += 3)
104 {
105 FString Kor = RawTokens[i].TrimStartAndEnd();
106 FString Eng = RawTokens[i + 1].TrimStartAndEnd();
107 FString Pronunciation = RawTokens[i + 2].TrimStartAndEnd();
108
109 // 빈 문자열 체크
110 if (Kor.IsEmpty() || Eng.IsEmpty() || Pronunciation.IsEmpty())
111 {
112 PRINTLOG(TEXT("[DailyKiosk] Skipped: Empty field (Kor: '%s', Eng: '%s', Phon: '%s')"), *Kor, *Eng, *Pronunciation);
113 continue;
114 }
115
116 // 한국어 검증 (Kor 필드만)
118 {
119 PRINTLOG(TEXT("[DailyKiosk] Skipped: Invalid Korean word '%s'"), *Kor);
120 continue;
121 }
122
123 // FWordData 생성
124 FWordData WordData;
125 WordData.Kor = Kor;
126 WordData.Eng = Eng;
127 WordData.Pronunciation = Pronunciation;
128
129 ValidWordDataArray.Add(WordData);
130 PRINTLOG(TEXT("[DailyKiosk] Parsed Word: Kor='%s', Eng='%s', Phon='%s'"), *Kor, *Eng, *Pronunciation);
131 }
132
133 // 유효한 단어가 부족하면 GameDataManager에서 보충
134 if (ValidWordDataArray.Num() < DefineData::MIN_REQUIRED_WORDS)
135 {
136 int32 WordsNeeded = DefineData::MIN_REQUIRED_WORDS - ValidWordDataArray.Num();
137
138 TArray<FWordData> AdditionalWordData = GetRandomKoreanWords(WordsNeeded);
139 ValidWordDataArray.Append(AdditionalWordData);
140 }
141
142 // 최종 검증 및 팝업 표시
143 if (ValidWordDataArray.Num() > 0)
144 {
145 if (UPopup_DailyStudy* DailyStudyPopup = UPopupManager::Get(GetWorld())->ShowPopupAs<UPopup_DailyStudy>(EPopupType::DailyStudy))
146 {
147 DailyStudyPopup->InitPopup(ValidWordDataArray);
148 PRINTLOG(TEXT("[DailyKiosk] Initialized DailyStudy popup with %d words"), ValidWordDataArray.Num());
149 }
150 }
151 else
152 {
153 PRINTLOG(TEXT("[DailyKiosk] ERROR: No valid word data!"));
154 }
155}
156
157void ADailyKiosk::OnOutlineStateChanged(bool bShouldShowOutline)
158{
159 if (MeshComp)
160 {
161 MeshComp->SetRenderCustomDepth(bShouldShowOutline);
162 }
163}
164
165TArray<FWordData> ADailyKiosk::GetRandomKoreanWords(int32 Count)
166{
167 TArray<FWordData> RandomWordDataArray;
168
169 UGameDataManager* DataManager = UGameDataManager::Get(GetWorld());
170 if (!DataManager)
171 {
172 PRINTLOG(TEXT("[DailyKiosk] Error: GameDataManager not found"));
173 return RandomWordDataArray;
174 }
175
176 // ReadData에서 모든 키 가져오기
177 TArray<int32> AllKeys = DataManager->GetAllReadDataKeys();
178
179 if (AllKeys.Num() == 0)
180 {
181 PRINTLOG(TEXT("[DailyKiosk] Error: No ReadData available"));
182 return RandomWordDataArray;
183 }
184
185 // 요청한 개수만큼 랜덤 단어 선택
186 int32 WordsToGenerate = FMath::Min(Count, AllKeys.Num());
187
188 for (int32 i = 0; i < WordsToGenerate; ++i)
189 {
190 // 랜덤 인덱스 선택
191 int32 RandomIndex = FMath::RandRange(0, AllKeys.Num() - 1);
192 int32 RandomKey = AllKeys[RandomIndex];
193 AllKeys.RemoveAt(RandomIndex); // 중복 방지
194
195 // 데이터 로드
196 FReadData ReadData;
197 if (DataManager->GetReadData(RandomKey, ReadData))
198 {
199 // FWordData 생성
200 FWordData WordData;
201 WordData.Kor = ReadData.Word;
202 WordData.Eng = ReadData.Eng;
203 WordData.Pronunciation = ReadData.Eng; // TODO: 나중에 실제 발음 데이터로 교체
204
205 RandomWordDataArray.Add(WordData);
206 }
207 }
208
209 PRINTLOG(TEXT("[DailyKiosk] Generated %d random word data from ReadData"), RandomWordDataArray.Num());
210 return RandomWordDataArray;
211}
#define DAILYKIOSK_INTERACT_WIDGET_PATH
YiSan 전반에서 사용하는 공용 인터페이스를 선언합니다.
#define PRINTLOG(fmt,...)
Definition GameLogging.h:30
UCommonFunctionLibrary 클래스를 선언합니다.
UGameDataManager 클래스를 선언합니다.
KLingo API 요청을 담당하는 서브시스템을 선언합니다.
void OnInteractionTriggered(AActor *Interactor)
TObjectPtr< class UBoxComponent > BoxComp
Definition ADailyKiosk.h:56
void OnOutlineStateChanged(bool bShouldShowOutline)
TArray< FWordData > GetRandomKoreanWords(int32 Count)
랜덤 한국어 단어 데이터 가져오기 (Fallback용)
TObjectPtr< class UWidgetComponent > WidgetComp
Definition ADailyKiosk.h:59
virtual void BeginPlay() override
TObjectPtr< class USceneComponent > RootSceneComp
Definition ADailyKiosk.h:44
TObjectPtr< class UStaticMeshComponent > MeshComp
Definition ADailyKiosk.h:47
void OnResponseDailyQuestion(FResponseChatDailys &InResponseData, bool bWasSuccessful)
TObjectPtr< class UInteractableComponent > InteractableComp
Definition ADailyKiosk.h:53
static bool IsValidKoreanWord(const FString &Word)
한국어 단어 검증 (한글만 포함되어 있는지 확인)
데이터 테이블(.csv)에서 게임 데이터를 로드하고 캐시하여 런타임에 빠르게 접근할 수 있도록 제공하는 데이터 관리 서브시스템입니다.
bool GetReadData(int32 Index, FReadData &Out) const
TArray< int32 > GetAllReadDataKeys() const
Daily Study 팝업
static const int32 MIN_REQUIRED_WORDS
Definition Onepiece.h:65
static const FString DailySystemPrompt
Definition Onepiece.h:70
static const FString DailyUserPrompt
Definition Onepiece.h:68
읽기 학습 데이터를 정의하는 구조체
Definition FReadData.h:19
FString Eng
학습 단어
Definition FReadData.h:39
FString Word
학습 단어
Definition FReadData.h:32
Chat Dailys 응답 구조체입니다.
단어 데이터 구조체입니다.
FString Kor
FString Pronunciation
FString Eng