KLingo Project Documentation 1.0.0
Unreal Engine 5.6 C++ Project Documentation
로딩중...
검색중...
일치하는것 없음
NetworkData.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
7#include "NetworkData.h"
8
9#include "GameLogging.h"
10#include "JsonObjectConverter.h"
11#include "NetworkLog.h"
12#include "FResultStatData.h"
13#include "ULingoGameHelper.h"
14
15#include "Misc/Base64.h"
16#include "Interfaces/IHttpResponse.h"
17#include "Dom/JsonObject.h"
18#include "Dom/JsonValue.h"
19#include "Onepiece/Onepiece.h"
20#include "Serialization/JsonReader.h"
21#include "Serialization/JsonSerializer.h"
22#include "Serialization/JsonWriter.h"
23
24
25FString FPhonemeData::ToRichTextString(int32 Index) const
26{
27 return FString::Printf(TEXT("<a id=\"%d\" content=\"link\">%s</> "), Index, *Kor);
28}
29
30TArray<FPhonemeData> FWordData::GetPhonemeData() const
31{
32 TArray<FString> KorWords;
33 Kor.ParseIntoArray(KorWords, TEXT(" "), true);
34
35 TArray<FString> PronWords;
36 Pronunciation.ParseIntoArray(PronWords, TEXT(" "), true);
37
38 TArray<FPhonemeData> WordDataArray;
39
40 for (int32 i = 0; i < KorWords.Num(); ++i)
41 {
42 FPhonemeData Data;
43 Data.Kor = i < KorWords.Num() ? KorWords[i] : TEXT("");
44 Data.Pronunciation = i < PronWords.Num() ? PronWords[i] : TEXT("");
45
46 WordDataArray.Add(Data);
47 }
48
49 return WordDataArray;
50}
51
52void FQuestWriteInfo::SetFromHttpResponse(const TSharedPtr<class IHttpResponse, ESPMode::ThreadSafe>& Response)
53{
54 if (!Response.IsValid())
55 {
56 return;
57 }
58
59 FString JsonString = Response->GetContentAsString();
60 TSharedPtr<FJsonObject> JsonObject;
61 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
62
63 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
64 {
65 user_id = JsonObject->GetIntegerField(TEXT("user_id"));
66
67 TArray<TSharedPtr<FJsonValue>> questionArray = JsonObject->GetArrayField(TEXT("question"));
68
69 for (const auto& data : questionArray)
70 {
72 TSharedPtr<FJsonObject> dataObject = data->AsObject();
73 if (!dataObject.IsValid())
74 {
75 continue;
76 }
77
78 if (dataObject->HasTypedField<EJson::Object>(TEXT("word_data")))
79 {
80 const TSharedPtr<FJsonObject> DisplayObj = dataObject->GetObjectField(TEXT("word_data"));
81 temp.word_data.kor = DisplayObj->GetStringField(TEXT("kor"));
82 temp.word_data.eng = DisplayObj->GetStringField(TEXT("eng"));
83 temp.word_data.pronunciation = DisplayObj->GetStringField(TEXT("pronunciation"));
84 }
85
86 temp.answer = dataObject->GetStringField(TEXT("answer"));
87 temp.answer_kor = dataObject->GetStringField(TEXT("answer_kor"));
88 question.Add(temp);
89 }
90 }
91 bIsValid = true;
92}
93
95{
96
97}
98
100{
101 return bIsValid;
102}
103
104void FResponseHealth::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
105{
106 if (Response.IsValid())
107 {
108 status = Response->GetResponseCode();
109 }
110}
111
113{
114 FString OutputString;
115 FJsonObjectConverter::UStructToJsonObjectString(
116 *this,
117 OutputString,
118 0,
119 0
120 );
121 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
122}
123
124void FResponseUserRegister::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
125{
126 if (!Response.IsValid())
127 {
128 return;
129 }
130
131 FString JsonString = Response->GetContentAsString();
132 TSharedPtr<FJsonObject> JsonObject;
133 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
134
135 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
136 {
137 id = JsonObject->GetIntegerField(TEXT("id"));
138 username = JsonObject->GetStringField(TEXT("username"));
139 email = JsonObject->GetStringField(TEXT("email"));
140 is_active = JsonObject->GetBoolField(TEXT("is_active"));
141 }
142}
143
145{
146 FString OutputString;
147 FJsonObjectConverter::UStructToJsonObjectString(
148 *this,
149 OutputString,
150 0,
151 0
152 );
153 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
154}
155
156
157void FResponseUserToken::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
158{
159 if (!Response.IsValid())
160 {
161 return;
162 }
163
164 FString JsonString = Response->GetContentAsString();
165 TSharedPtr<FJsonObject> JsonObject;
166 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
167
168 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
169 {
170 access_token = JsonObject->GetStringField(TEXT("access_token"));
171 }
172}
173
175{
176 FString OutputString;
177 FJsonObjectConverter::UStructToJsonObjectString(
178 *this,
179 OutputString,
180 0,
181 0
182 );
183 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
184}
185
186
187
188void FResponseUserMe::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
189{
190 if (!Response.IsValid())
191 {
192 return;
193 }
194
195 FString JsonString = Response->GetContentAsString();
196 TSharedPtr<FJsonObject> JsonObject;
197 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
198
199 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
200 {
201 id = JsonObject->GetIntegerField(TEXT("id"));
202 username = JsonObject->GetStringField(TEXT("username"));
203 fullname = JsonObject->GetStringField(TEXT("fullname"));
204 is_active = JsonObject->GetBoolField(TEXT("is_active"));
205 my_avatar = JsonObject->GetStringField(TEXT("my_avatar"));
206 my_color = JsonObject->GetStringField(TEXT("my_color"));
207 }
208}
209
211{
212 FString OutputString;
213 FJsonObjectConverter::UStructToJsonObjectString(
214 *this,
215 OutputString,
216 0,
217 0
218 );
219 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
220}
221
223{
224 if ( id == DefineData::BotID)
225 {
227 }
228
229 if ( player_index == 0)
231 else if ( player_index == 1)
234}
235
236FLinearColor FResponseUserMe::GetChatProfileBg(int player_index) const
237{
238 if ( id == DefineData::BotID)
239 {
240 return FColor::FromHex(TEXT("007BE8FF"));
241 }
242
243 if ( player_index == 0)
244 return FColor::FromHex(TEXT("FFFFFF"));
245 if ( player_index == 1)
246 return FColor::FromHex(TEXT("FFFFFF"));
247 else
248 return FColor::FromHex(TEXT("E94C4CFF"));
249}
250
251
252void FResponseUserHost::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
253{
254 return;
255}
256
258{
259 FString OutputString;
260 FJsonObjectConverter::UStructToJsonObjectString(
261 *this,
262 OutputString,
263 0,
264 0
265 );
266 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
267}
268
269
270//
271// // =================================================================================
272// // FResponseScenario
273// // =================================================================================
274//
275// void FResponseScenario::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
276// {
277// if (!Response.IsValid())
278// {
279// return;
280// }
281//
282// FString JsonString = Response->GetContentAsString();
283// TSharedPtr<FJsonObject> JsonObject;
284// TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
285//
286// if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
287// {
288// index = JsonObject->GetIntegerField(TEXT("index"));
289// dificulity = JsonObject->GetIntegerField(TEXT("dificulity"));
290// correct_answer_index = JsonObject->GetIntegerField(TEXT("correct_answer_index"));
291//
292// // target_data 배열 파싱
293// const TArray<TSharedPtr<FJsonValue>>* TargetDataArray;
294// if (JsonObject->TryGetArrayField(TEXT("target_data"), TargetDataArray))
295// {
296// for (const auto& Item : *TargetDataArray)
297// {
298// TSharedPtr<FJsonObject> TargetObj = Item->AsObject();
299// if (TargetObj.IsValid())
300// {
301// FScenarioTargetData TargetItem;
302//
303// // word1 파싱
304// if (TargetObj->HasTypedField<EJson::Object>(TEXT("word1")))
305// {
306// TSharedPtr<FJsonObject> Word1Obj = TargetObj->GetObjectField(TEXT("word1"));
307// if (Word1Obj.IsValid())
308// {
309// TargetItem.word1.name = Word1Obj->GetStringField(TEXT("name"));
310// TargetItem.word1.code = Word1Obj->GetStringField(TEXT("code"));
311// }
312// }
313//
314// // word2 파싱
315// if (TargetObj->HasTypedField<EJson::Object>(TEXT("word2")))
316// {
317// TSharedPtr<FJsonObject> Word2Obj = TargetObj->GetObjectField(TEXT("word2"));
318// if (Word2Obj.IsValid())
319// {
320// TargetItem.word2.name = Word2Obj->GetStringField(TEXT("name"));
321// TargetItem.word2.code = Word2Obj->GetStringField(TEXT("code"));
322// }
323// }
324//
325// target_data.Add(TargetItem);
326// }
327// }
328// }
329//
330// // word_data1 파싱
331// if (JsonObject->HasTypedField<EJson::Object>(TEXT("word_data1")))
332// {
333// TSharedPtr<FJsonObject> WordData1Obj = JsonObject->GetObjectField(TEXT("word_data1"));
334// FJsonObjectConverter::JsonObjectToUStruct(WordData1Obj.ToSharedRef(), FWordData::StaticStruct(), &word_data1);
335// }
336//
337// // word_data2 파싱
338// if (JsonObject->HasTypedField<EJson::Object>(TEXT("word_data2")))
339// {
340// TSharedPtr<FJsonObject> WordData2Obj = JsonObject->GetObjectField(TEXT("word_data2"));
341// FJsonObjectConverter::JsonObjectToUStruct(WordData2Obj.ToSharedRef(), FWordData::StaticStruct(), &word_data2);
342// }
343//
344// // full_data 파싱
345// if (JsonObject->HasTypedField<EJson::Object>(TEXT("full_data")))
346// {
347// TSharedPtr<FJsonObject> FullDataObj = JsonObject->GetObjectField(TEXT("full_data"));
348// FJsonObjectConverter::JsonObjectToUStruct(FullDataObj.ToSharedRef(), FWordData::StaticStruct(), &full_data);
349// }
350//
351// // voice data 파싱
352// FString VoiceDataString;
353// if (JsonObject->TryGetStringField(TEXT("voice_data"), VoiceDataString))
354// {
355// FBase64::Decode(VoiceDataString, voice_data);
356// }
357// }
358// }
359//
360// void FResponseScenario::PrintData() const
361// {
362// FString OutputString;
363// FJsonObjectConverter::UStructToJsonObjectString(
364// *this,
365// OutputString,
366// 0,
367// 0
368// );
369// NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
370// }
371//
372// TArray<FString> FResponseScenario::GetWord1List() const
373// {
374// TSet<FString> UniqueSet;
375//
376// for (const FScenarioTargetData& TargetData : target_data)
377// {
378// if (!TargetData.word1.name.IsEmpty())
379// {
380// UniqueSet.Add(TargetData.word1.name);
381// }
382// }
383//
384// return UniqueSet.Array();
385// }
386//
387// TArray<FString> FResponseScenario::GetWord2List() const
388// {
389// TSet<FString> UniqueSet;
390//
391// for (const FScenarioTargetData& TargetData : target_data)
392// {
393// if (!TargetData.word2.name.IsEmpty())
394// {
395// UniqueSet.Add(TargetData.word2.name);
396// }
397// }
398//
399// return UniqueSet.Array();
400// }
401
402
403// =================================================================================
404// FResponseWriteSubmit
405// =================================================================================
406
407void FResponseWriteSubmit::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
408{
409 if (!Response.IsValid())
410 {
411 return;
412 }
413
414 FString JsonString = Response->GetContentAsString();
415
416 TArray<TSharedPtr<FJsonValue>> JsonArray;
417 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
418
419 if (FJsonSerializer::Deserialize(Reader, JsonArray))
420 {
421 for (const TSharedPtr<FJsonValue>& EntryValue : JsonArray)
422 {
423 if (EntryValue.IsValid())
424 {
425 TSharedPtr<FJsonObject> EntryObject = EntryValue->AsObject();
426 if (!EntryObject.IsValid())
427 {
428 continue;
429 }
430
431 FResponseWriteData Entry; // Display & Record를 포함하는 사용자 정의 구조체
432
433 if (EntryObject->HasTypedField<EJson::Object>(TEXT("display")))
434 {
435 const TSharedPtr<FJsonObject> DisplayObj = EntryObject->GetObjectField(TEXT("display"));
436 Entry.display.is_pass = DisplayObj->GetBoolField(TEXT("is_pass"));
437 Entry.display.message = DisplayObj->GetStringField(TEXT("message"));
438 Entry.display.correction = DisplayObj->GetStringField(TEXT("correction"));
439 }
440
441 if (EntryObject->HasTypedField<EJson::Object>(TEXT("record")))
442 {
443 const TSharedPtr<FJsonObject> RecordObj = EntryObject->GetObjectField(TEXT("record"));
444 Entry.record.score = RecordObj->GetIntegerField(TEXT("score"));
445 Entry.record.target = RecordObj->GetStringField(TEXT("target"));
446 Entry.record.input = RecordObj->GetStringField(TEXT("input"));
447 Entry.record.stage = RecordObj->GetStringField(TEXT("stage"));
448 }
449
450 ResponseWriteDataArray.Add(Entry);
451 }
452 }
453 }
454}
455
457{
459 {
460 NETWORK_LOG( TEXT("[OCR Extract] Response - Is_Pass: %d, Text: %s"), data.display.is_pass, *(data.display.message));
461 }
462}
463
464bool FRequestWriteResult::ToJsonString(FString& OutJson) const
465{
466 TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
467
468 JsonObject->SetNumberField(TEXT("room_id"), room_id);
469 JsonObject->SetNumberField(TEXT("user_id"), user_id);
470 JsonObject->SetNumberField(TEXT("scenario_id"), scenario_id);
471 JsonObject->SetNumberField(TEXT("stage_type"), stage_type);
472 JsonObject->SetNumberField(TEXT("state_type"), state_type);
473 JsonObject->SetNumberField(TEXT("result_time"), result_time);
474
475 TArray<TSharedPtr<FJsonValue>> WrongIdxArray;
476 for (int32 Idx : wrong_idx)
477 {
478 WrongIdxArray.Add(MakeShared<FJsonValueNumber>(Idx));
479 }
480 JsonObject->SetArrayField(TEXT("wrong_idx"), WrongIdxArray);
481
482 TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutJson);
483 return FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
484}
485
486void FResponseWriteResult::SetFromHttpResponse(const TSharedPtr<class IHttpResponse, ESPMode::ThreadSafe>& Response)
487{
488 if (!Response.IsValid())
489 {
490 return;
491 }
492
493 FString JsonString = Response->GetContentAsString();
494
495 TSharedPtr<FJsonObject> JsonObject;
496 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
497
498 if (FJsonSerializer::Deserialize(Reader, JsonObject))
499 {
500 if (JsonObject.IsValid())
501 {
502 JsonObject->TryGetStringField(TEXT("grade"), this->grade);
503 this->average_score = JsonObject->GetIntegerField(TEXT("average_score"));
504 this->top_percent = JsonObject->GetIntegerField(TEXT("top_percent"));
505
506 if (JsonObject->HasTypedField<EJson::Object>(TEXT("scores")))
507 {
508 TArray<TSharedPtr<FJsonValue>> JsonArray = JsonObject->GetArrayField(TEXT("scores"));
509 for (const auto& score : JsonArray)
510 {
511 FResponseWriteScores Entry; // ResponseWriteScore를 포함하는 사용자 정의 구조체
512 Entry.score = score->AsObject()->GetBoolField(TEXT("score"));
513 Entry.desc = score->AsObject()->GetStringField(TEXT("desc"));
514
515 scores.Add(Entry);
516 }
517 }
518 }
519 }
520}
521
522void FResponseListenAudio::SetFromHttpResponse(const TSharedPtr<class IHttpResponse, ESPMode::ThreadSafe>& Response)
523{
524 if (!Response.IsValid())
525 {
526 return;
527 }
528
529 FString ResponseBody = Response->GetContentAsString();
530
531 TSharedPtr<FJsonObject> JsonObject;
532 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(ResponseBody);
533
534 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
535 {
536 JsonObject->TryGetStringField(TEXT("audio_text"), audio_text);
537
538 FString audio_data;
539 JsonObject->TryGetStringField(TEXT("audio_base64"), audio_data);
540 FBase64::Decode(audio_data, audio_base64);
541 }
542}
543
545{
546 // FString OutputString;
547 // FJsonObjectConverter::UStructToJsonObjectString(
548 // *this,
549 // OutputString,
550 // 0,
551 // 0
552 // );
553 // NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
554
555 NETWORK_LOG( TEXT("[RES] audio_text: %s"), *audio_text );
556}
557
558// =================================================================================
559// FResponseSpeakingQuestions
560// =================================================================================
561
562void FResponseSpeakingJudes::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
563{
564 if (!Response.IsValid())
565 {
566 return;
567 }
568
569 FString JsonString = Response->GetContentAsString();
570 TSharedPtr<FJsonObject> JsonObject;
571 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
572
573 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
574 {
575 grammar_score = JsonObject->GetIntegerField(TEXT("grammar_score"));
576 context_score = JsonObject->GetIntegerField(TEXT("context_score"));
577 final_overall_score = JsonObject->GetIntegerField(TEXT("final_overall_score"));
578 final_feedback = JsonObject->GetStringField(TEXT("final_feedback"));
579 }
580}
581
583{
584 FString OutputString;
585 FJsonObjectConverter::UStructToJsonObjectString(
586 *this,
587 OutputString,
588 0,
589 0
590 );
591 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
592}
593
594TArray<FResultStatData> FResponseSpeakingJudes::GetResultStatData() const
595{
596 TArray<FResultStatData> StatDataList;
597
598 // Grammar Score
599 FResultStatData GrammarData;
601 GrammarData.ColorType = EColorStyleType::Gray;
602 GrammarData.TitleText = FText::FromString(TEXT("Grammer"));
603 GrammarData.ScoreValue = grammar_score;
605 StatDataList.Add(GrammarData);
606
607 // Context Score
608 FResultStatData ContextData;
610 ContextData.ColorType = EColorStyleType::Gray;
611 ContextData.TitleText = FText::FromString(TEXT("Context"));
612 ContextData.ScoreValue = context_score;
614 StatDataList.Add(ContextData);
615
616
617 FResultStatData OverallData;
619 OverallData.ColorType = EColorStyleType::Gray;
620 OverallData.TitleText = FText::FromString(TEXT("Score"));
621 OverallData.ScoreValue = final_overall_score;
623 StatDataList.Add(OverallData);
624
625 return StatDataList;
626}
627
628
629void FResponseInterviewHello::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
630{
631 if (!Response.IsValid())
632 {
633 return;
634 }
635
636 FString JsonString = Response->GetContentAsString();
637 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
638 TArray<TSharedPtr<FJsonValue>> JsonArray;
639
640 if (FJsonSerializer::Deserialize(Reader, JsonArray))
641 {
642 Questions.Empty();
643
644 for (const auto& JsonValue : JsonArray)
645 {
646 TSharedPtr<FJsonObject> JsonObject = JsonValue->AsObject();
647 if (JsonObject.IsValid())
648 {
649 FInterviewQuestionData QuestionData;
650 QuestionData.Id = JsonObject->GetIntegerField(TEXT("id"));
651 QuestionData.TypeCode = JsonObject->GetIntegerField(TEXT("type_code"));
652 QuestionData.Eng = JsonObject->GetStringField(TEXT("eng"));
653 QuestionData.Kor = JsonObject->GetStringField(TEXT("kor"));
654 QuestionData.EngKey = JsonObject->GetStringField(TEXT("eng_key"));
655 QuestionData.KorKey = JsonObject->GetStringField(TEXT("kor_key"));
656
657 // created_at 필드 파싱 (optional)
658 JsonObject->TryGetStringField(TEXT("created_at"), QuestionData.CreatedAt);
659
660 Questions.Add(QuestionData);
661 }
662 }
663
664 NETWORK_LOG(TEXT("[Interview Hello] Successfully parsed %d questions"), Questions.Num());
665 }
666 else
667 {
668 NETWORK_LOG(TEXT("[Interview Hello] Failed to parse JSON array"));
669 }
670}
671
673{
674 NETWORK_LOG(TEXT("[Interview Hello] Response - Questions Count: %d"), Questions.Num());
675 for (const auto& Question : Questions)
676 {
677 NETWORK_LOG(TEXT(" - ID: %d, TypeCode: %d, Eng: %s, Kor: %s"),
678 Question.Id, Question.TypeCode, *Question.Eng, *Question.Kor);
679 }
680}
681
682// =================================================================================
683// FRequestInterviewAnswer
684// =================================================================================
685
686bool FRequestInterviewAnswer::ToJsonString(FString& OutJson) const
687{
688 TArray<TSharedPtr<FJsonValue>> JsonArray;
689
690 for (const FInterviewAnswerData& AnswerData : answer)
691 {
692 TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
693 JsonObject->SetNumberField(TEXT("interview_id"), AnswerData.interview_id);
694 JsonObject->SetStringField(TEXT("answer"), AnswerData.answer);
695 JsonObject->SetNumberField(TEXT("user_id"), AnswerData.user_id);
696
697 JsonArray.Add(MakeShared<FJsonValueObject>(JsonObject));
698 }
699
700 TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutJson);
701 return FJsonSerializer::Serialize(JsonArray, Writer);
702}
703
704// =================================================================================
705// FResponseInterviewAnswer
706// =================================================================================
707
708void FResponseInterviewAnswer::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
709{
710 if (!Response.IsValid())
711 {
712 return;
713 }
714
715 FString JsonString = Response->GetContentAsString();
716 NETWORK_LOG(TEXT("[Interview Answer] Response: %s"), *JsonString);
717}
718
720{
721 NETWORK_LOG(TEXT("[Interview Answer] Response processed successfully"));
722}
723
724// =================================================================================
725// FResponseReadScenario
726// =================================================================================
727void FResponseReadScenario::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
728{
729 if (!Response.IsValid())
730 {
731 return;
732 }
733
734 FString JsonString = Response->GetContentAsString();
735 TSharedPtr<FJsonObject> JsonObject;
736 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
737
738 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
739 {
740 index = JsonObject->GetIntegerField(TEXT("index"));
741 dificulity = JsonObject->GetIntegerField(TEXT("dificulity"));
742 room_id = JsonObject->GetIntegerField(TEXT("room_id"));
743 correct_answer_index = JsonObject->GetIntegerField(TEXT("correct_answer_index"));
744
745 // target_data 배열 파싱
746 const TArray<TSharedPtr<FJsonValue>>* TargetDataArray;
747 if (JsonObject->TryGetArrayField(TEXT("target_data"), TargetDataArray))
748 {
749 for (const auto& Item : *TargetDataArray)
750 {
751 TSharedPtr<FJsonObject> TargetObj = Item->AsObject();
752 if (TargetObj.IsValid())
753 {
754 FScenarioTargetData TargetItem;
755
756 // word1 파싱
757 if (TargetObj->HasTypedField<EJson::Object>(TEXT("word1")))
758 {
759 TSharedPtr<FJsonObject> Word1Obj = TargetObj->GetObjectField(TEXT("word1"));
760 if (Word1Obj.IsValid())
761 {
762 TargetItem.word1.name = Word1Obj->GetStringField(TEXT("name"));
763 TargetItem.word1.code = Word1Obj->GetStringField(TEXT("code"));
764 }
765 }
766
767 // word2 파싱
768 if (TargetObj->HasTypedField<EJson::Object>(TEXT("word2")))
769 {
770 TSharedPtr<FJsonObject> Word2Obj = TargetObj->GetObjectField(TEXT("word2"));
771 if (Word2Obj.IsValid())
772 {
773 TargetItem.word2.name = Word2Obj->GetStringField(TEXT("name"));
774 TargetItem.word2.code = Word2Obj->GetStringField(TEXT("code"));
775 }
776 }
777
778 target_data.Add(TargetItem);
779 }
780 }
781 }
782
783 // word_data1 파싱
784 if (JsonObject->HasTypedField<EJson::Object>(TEXT("word_data1")))
785 {
786 TSharedPtr<FJsonObject> WordData1Obj = JsonObject->GetObjectField(TEXT("word_data1"));
787 FJsonObjectConverter::JsonObjectToUStruct(WordData1Obj.ToSharedRef(), FWordData::StaticStruct(), &word_data1);
788 }
789
790 // word_data2 파싱
791 if (JsonObject->HasTypedField<EJson::Object>(TEXT("word_data2")))
792 {
793 TSharedPtr<FJsonObject> WordData2Obj = JsonObject->GetObjectField(TEXT("word_data2"));
794 FJsonObjectConverter::JsonObjectToUStruct(WordData2Obj.ToSharedRef(), FWordData::StaticStruct(), &word_data2);
795 }
796
797 // full_data 파싱
798 if (JsonObject->HasTypedField<EJson::Object>(TEXT("full_data")))
799 {
800 TSharedPtr<FJsonObject> FullDataObj = JsonObject->GetObjectField(TEXT("full_data"));
801 FJsonObjectConverter::JsonObjectToUStruct(FullDataObj.ToSharedRef(), FWordData::StaticStruct(), &full_data);
802 }
803 }
804}
805
807{
808 FString OutputString;
809 FJsonObjectConverter::UStructToJsonObjectString(
810 *this,
811 OutputString,
812 0,
813 0
814 );
815 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
816}
817
819{
820 TSet<FString> UniqueSet;
821
822 for (const FScenarioTargetData& TargetData : target_data)
823 {
824 if (!TargetData.word1.name.IsEmpty())
825 {
826 UniqueSet.Add(TargetData.word1.name);
827 }
828 }
829
830 return UniqueSet.Array();
831}
832
834{
835 TSet<FString> UniqueSet;
836
837 for (const FScenarioTargetData& TargetData : target_data)
838 {
839 if (!TargetData.word2.name.IsEmpty())
840 {
841 UniqueSet.Add(TargetData.word2.name);
842 }
843 }
844
845 return UniqueSet.Array();
846}
847
852
853// =================================================================================
854// FResponseReadResult
855// =================================================================================
856bool FRequestReadResult::ToJsonString(FString& OutJson) const
857{
858 TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
859
860 JsonObject->SetNumberField(TEXT("room_id"), room_id);
861 JsonObject->SetNumberField(TEXT("user_id"), user_id);
862 JsonObject->SetNumberField(TEXT("scenario_id"), scenario_id);
863 JsonObject->SetNumberField(TEXT("stage_type"), stage_type);
864 JsonObject->SetNumberField(TEXT("state_type"), state_type);
865 JsonObject->SetNumberField(TEXT("result_time"), result_time);
866
867 TArray<TSharedPtr<FJsonValue>> WrongIdxArray;
868 for (int32 Idx : wrong_idx)
869 {
870 WrongIdxArray.Add(MakeShared<FJsonValueNumber>(Idx));
871 }
872 JsonObject->SetArrayField(TEXT("wrong_idx"), WrongIdxArray);
873
874 TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutJson);
875 return FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
876}
877
878void FResponseReadResult::SetFromHttpResponse(const TSharedPtr<class IHttpResponse, ESPMode::ThreadSafe>& Response)
879{
880 if (!Response.IsValid())
881 {
882 return;
883 }
884
885 FString JsonString = Response->GetContentAsString();
886 TSharedPtr<FJsonObject> JsonObject;
887 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
888
889 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
890 {
891 JsonObject->TryGetStringField(TEXT("grade"), grade);
892 JsonObject->TryGetNumberField(TEXT("average_score"), average_score);
893 JsonObject->TryGetNumberField(TEXT("top_percent"), top_percent);
894
895 // scores 배열 파싱
896 if (JsonObject->HasTypedField<EJson::Array>(TEXT("scores")))
897 {
898 TArray<TSharedPtr<FJsonValue>> JsonArray = JsonObject->GetArrayField(TEXT("scores"));
899 for (const auto& ScoreValue : JsonArray)
900 {
901 if (ScoreValue->Type == EJson::Object)
902 {
903 TSharedPtr<FJsonObject> ScoreObj = ScoreValue->AsObject();
904 FReadScoreDetail Entry;
905 ScoreObj->TryGetNumberField(TEXT("score"), Entry.score);
906 ScoreObj->TryGetStringField(TEXT("desc"), Entry.desc);
907 scores.Add(Entry);
908 }
909 }
910 }
911 }
912}
913
915{
916 FString OutputString;
917 FJsonObjectConverter::UStructToJsonObjectString(
918 *this,
919 OutputString,
920 0,
921 0
922 );
923 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
924}
925
926// =================================================================================
927// FResponseListenScenario
928// =================================================================================
929
930void FResponseListenScenario::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
931{
932 if (!Response.IsValid())
933 {
934 return;
935 }
936
937 FString JsonString = Response->GetContentAsString();
938 TSharedPtr<FJsonObject> JsonObject;
939 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
940
941 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
942 {
943 index = JsonObject->GetIntegerField(TEXT("index"));
944 dificulity = JsonObject->GetIntegerField(TEXT("dificulity"));
945 room_id = JsonObject->GetIntegerField(TEXT("room_id"));
946 correct_answer_index = JsonObject->GetIntegerField(TEXT("correct_answer_index"));
947
948 // target_data 배열 파싱
949 const TArray<TSharedPtr<FJsonValue>>* TargetDataArray;
950 if (JsonObject->TryGetArrayField(TEXT("target_data"), TargetDataArray))
951 {
952 for (const auto& Item : *TargetDataArray)
953 {
954 TSharedPtr<FJsonObject> TargetObj = Item->AsObject();
955 if (TargetObj.IsValid())
956 {
957 FScenarioTargetData TargetItem;
958
959 // word1 파싱
960 if (TargetObj->HasTypedField<EJson::Object>(TEXT("word1")))
961 {
962 TSharedPtr<FJsonObject> Word1Obj = TargetObj->GetObjectField(TEXT("word1"));
963 if (Word1Obj.IsValid())
964 {
965 TargetItem.word1.name = Word1Obj->GetStringField(TEXT("name"));
966 TargetItem.word1.code = Word1Obj->GetStringField(TEXT("code"));
967 }
968 }
969
970 // word2 파싱
971 if (TargetObj->HasTypedField<EJson::Object>(TEXT("word2")))
972 {
973 TSharedPtr<FJsonObject> Word2Obj = TargetObj->GetObjectField(TEXT("word2"));
974 if (Word2Obj.IsValid())
975 {
976 TargetItem.word2.name = Word2Obj->GetStringField(TEXT("name"));
977 TargetItem.word2.code = Word2Obj->GetStringField(TEXT("code"));
978 }
979 }
980
981 target_data.Add(TargetItem);
982 }
983 }
984 }
985
986 // word_data1 파싱
987 if (JsonObject->HasTypedField<EJson::Object>(TEXT("word_data1")))
988 {
989 TSharedPtr<FJsonObject> WordData1Obj = JsonObject->GetObjectField(TEXT("word_data1"));
990 FJsonObjectConverter::JsonObjectToUStruct(WordData1Obj.ToSharedRef(), FWordData::StaticStruct(), &word_data1);
991 }
992
993 // word_data2 파싱
994 if (JsonObject->HasTypedField<EJson::Object>(TEXT("word_data2")))
995 {
996 TSharedPtr<FJsonObject> WordData2Obj = JsonObject->GetObjectField(TEXT("word_data2"));
997 FJsonObjectConverter::JsonObjectToUStruct(WordData2Obj.ToSharedRef(), FWordData::StaticStruct(), &word_data2);
998 }
999
1000 // full_data 파싱
1001 if (JsonObject->HasTypedField<EJson::Object>(TEXT("full_data")))
1002 {
1003 TSharedPtr<FJsonObject> FullDataObj = JsonObject->GetObjectField(TEXT("full_data"));
1004 FJsonObjectConverter::JsonObjectToUStruct(FullDataObj.ToSharedRef(), FWordData::StaticStruct(), &full_data);
1005 }
1006
1007 // voice data 파싱
1008 FString VoiceDataString;
1009 if (JsonObject->TryGetStringField(TEXT("voice_data"), VoiceDataString))
1010 {
1011 FBase64::Decode(VoiceDataString, voice_data);
1012 }
1013 }
1014}
1015
1017{
1018 FString OutputString;
1019 FJsonObjectConverter::UStructToJsonObjectString(
1020 *this,
1021 OutputString,
1022 0,
1023 0
1024 );
1025 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
1026}
1027
1029{
1030 TSet<FString> UniqueSet;
1031
1032 for (const FScenarioTargetData& TargetData : target_data)
1033 {
1034 if (!TargetData.word1.name.IsEmpty())
1035 {
1036 UniqueSet.Add(TargetData.word1.name);
1037 }
1038 }
1039
1040 return UniqueSet.Array();
1041}
1042
1044{
1045 TSet<FString> UniqueSet;
1046
1047 for (const FScenarioTargetData& TargetData : target_data)
1048 {
1049 if (!TargetData.word2.name.IsEmpty())
1050 {
1051 UniqueSet.Add(TargetData.word2.name);
1052 }
1053 }
1054
1055 return UniqueSet.Array();
1056}
1057
1062
1063// =================================================================================
1064// FResponseListenResult
1065// =================================================================================
1066bool FRequestListenResult::ToJsonString(FString& OutJson) const
1067{
1068 TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
1069
1070 JsonObject->SetNumberField(TEXT("room_id"), room_id);
1071 JsonObject->SetNumberField(TEXT("user_id"), user_id);
1072 JsonObject->SetNumberField(TEXT("scenario_id"), scenario_id);
1073 JsonObject->SetNumberField(TEXT("stage_type"), stage_type);
1074 JsonObject->SetNumberField(TEXT("state_type"), state_type);
1075 JsonObject->SetNumberField(TEXT("result_time"), result_time);
1076
1077 TArray<TSharedPtr<FJsonValue>> WrongIdxArray;
1078 for (int32 Idx : wrong_idx)
1079 {
1080 WrongIdxArray.Add(MakeShared<FJsonValueNumber>(Idx));
1081 }
1082 JsonObject->SetArrayField(TEXT("wrong_idx"), WrongIdxArray);
1083
1084 TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutJson);
1085 return FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
1086}
1087
1088void FResponseListenResult::SetFromHttpResponse(const TSharedPtr<class IHttpResponse, ESPMode::ThreadSafe>& Response)
1089{
1090 if (!Response.IsValid())
1091 {
1092 return;
1093 }
1094
1095 FString JsonString = Response->GetContentAsString();
1096 TSharedPtr<FJsonObject> JsonObject;
1097 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
1098
1099 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
1100 {
1101 JsonObject->TryGetStringField(TEXT("grade"), grade);
1102 JsonObject->TryGetNumberField(TEXT("average_score"), average_score);
1103 JsonObject->TryGetNumberField(TEXT("top_percent"), top_percent);
1104
1105 // scores 배열 파싱
1106 if (JsonObject->HasTypedField<EJson::Array>(TEXT("scores")))
1107 {
1108 TArray<TSharedPtr<FJsonValue>> JsonArray = JsonObject->GetArrayField(TEXT("scores"));
1109 for (const auto& ScoreValue : JsonArray)
1110 {
1111 if (ScoreValue->Type == EJson::Object)
1112 {
1113 TSharedPtr<FJsonObject> ScoreObj = ScoreValue->AsObject();
1114 FListenScoreDetail Entry;
1115 ScoreObj->TryGetNumberField(TEXT("score"), Entry.score);
1116 ScoreObj->TryGetStringField(TEXT("desc"), Entry.desc);
1117 scores.Add(Entry);
1118 }
1119 }
1120 }
1121 }
1122}
1123
1125{
1126 FString OutputString;
1127 FJsonObjectConverter::UStructToJsonObjectString(
1128 *this,
1129 OutputString,
1130 0,
1131 0
1132 );
1133 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
1134}
1135
1136
1137bool FRequestSpeakResult::ToJsonString(FString& OutJson) const
1138{
1139 TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
1140
1141 JsonObject->SetNumberField(TEXT("room_id"), room_id);
1142 JsonObject->SetNumberField(TEXT("user_id"), user_id);
1143 JsonObject->SetNumberField(TEXT("scenario_id"), scenario_id);
1144 JsonObject->SetNumberField(TEXT("stage_type"), stage_type);
1145 JsonObject->SetNumberField(TEXT("state_type"), state_type);
1146 JsonObject->SetNumberField(TEXT("result_time"), result_time);
1147
1148 TArray<TSharedPtr<FJsonValue>> WrongIdxArray;
1149 for (int32 Idx : wrong_idx)
1150 {
1151 WrongIdxArray.Add(MakeShared<FJsonValueNumber>(Idx));
1152 }
1153 JsonObject->SetArrayField(TEXT("wrong_idx"), WrongIdxArray);
1154
1155 TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutJson);
1156 return FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
1157}
1158
1159
1160// =================================================================================
1161// FResponseSpeakResult
1162// =================================================================================
1163
1164void FResponseSpeakResult::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
1165{
1166 if (!Response.IsValid())
1167 {
1168 return;
1169 }
1170
1171 FString JsonString = Response->GetContentAsString();
1172 TSharedPtr<FJsonObject> JsonObject;
1173 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
1174
1175 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
1176 {
1177 grade = JsonObject->GetStringField(TEXT("grade"));
1178 average_score = JsonObject->GetIntegerField(TEXT("average_score"));
1179 top_percent = JsonObject->GetNumberField(TEXT("top_percent"));
1180
1181 // scores 배열 파싱
1182 const TArray<TSharedPtr<FJsonValue>>* ScoresArray;
1183 if (JsonObject->TryGetArrayField(TEXT("scores"), ScoresArray))
1184 {
1185 scores.Empty();
1186 for (const auto& ScoreValue : *ScoresArray)
1187 {
1188 TSharedPtr<FJsonObject> ScoreObj = ScoreValue->AsObject();
1189 if (ScoreObj.IsValid())
1190 {
1191 FSpeakScoreDetail ScoreDetail;
1192 ScoreDetail.score = ScoreObj->GetIntegerField(TEXT("score"));
1193 ScoreDetail.desc = ScoreObj->GetStringField(TEXT("desc"));
1194 scores.Add(ScoreDetail);
1195 }
1196 }
1197 }
1198 }
1199}
1200
1202{
1203 FString OutputString;
1204 FJsonObjectConverter::UStructToJsonObjectString(
1205 *this,
1206 OutputString,
1207 0,
1208 0
1209 );
1210 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
1211}
1212
1213TArray<FResultStatData> FResponseSpeakResult::GetResultStatData() const
1214{
1215 TArray<FResultStatData> StatDataList;
1216
1217 FResultStatData GradeResultData;
1218 GradeResultData.WidgetType = EResultItemWidgetType::Grade;
1219 GradeResultData.ColorType = EColorStyleType::Gray;
1220 GradeResultData.TitleText = FText::FromString(TEXT("Grade"));
1222 StatDataList.Add(GradeResultData);
1223
1224 FResultStatData TopRateResultData;
1225 TopRateResultData.WidgetType = EResultItemWidgetType::Rate;
1226 TopRateResultData.ColorType = EColorStyleType::Gray;
1227 TopRateResultData.TitleText = FText::FromString(TEXT("Top"));
1228 TopRateResultData.RatePercent = top_percent;
1229 StatDataList.Add(TopRateResultData);
1230
1231 FResultStatData AverageScoreResultData;
1232 AverageScoreResultData.WidgetType = EResultItemWidgetType::Symbol;
1233 AverageScoreResultData.ColorType = EColorStyleType::Gray;
1234 AverageScoreResultData.TitleText = FText::FromString(TEXT("Score"));
1235 AverageScoreResultData.SymbolTextureType = EResourceTextureType::Score;
1236 AverageScoreResultData.SymbolValue = FString::Printf(TEXT("%d"), average_score);
1237 StatDataList.Add(AverageScoreResultData);
1238
1239 return StatDataList;
1240}
1241
1243{
1244 return FString::Printf(TEXT("%s\n[%s]"), *eng, *kor);
1245}
1246
1247// =================================================================================
1248// FResponseSpeakScenario
1249// =================================================================================
1250
1251void FResponseSpeakScenario::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
1252{
1253 if (!Response.IsValid())
1254 {
1255 return;
1256 }
1257
1258 FString JsonString = Response->GetContentAsString();
1259 TSharedPtr<FJsonObject> JsonObject;
1260 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
1261
1262 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
1263 {
1264 index = JsonObject->GetIntegerField(TEXT("index"));
1265 difficulty = JsonObject->GetIntegerField(TEXT("difficulty"));
1266 room_id = JsonObject->GetIntegerField(TEXT("room_id"));
1267
1268 // audio 배열 파싱
1269 const TArray<TSharedPtr<FJsonValue>>* QuestionArray;
1270 if (JsonObject->TryGetArrayField(TEXT("audio"), QuestionArray))
1271 {
1272 for (const auto& Item : *QuestionArray)
1273 {
1274 TSharedPtr<FJsonObject> AudioObj = Item->AsObject();
1275 if (AudioObj.IsValid())
1276 {
1277 FSpeakStageQuestion QuestionItem;
1278 QuestionItem.kor = AudioObj->GetStringField(TEXT("kor"));
1279 QuestionItem.eng = AudioObj->GetStringField(TEXT("eng"));
1280 QuestionItem.pronunciation = AudioObj->GetStringField(TEXT("pronunciation"));
1281
1282 FString tmp_audio_data;
1283 JsonObject->TryGetStringField(TEXT("voice_data"), tmp_audio_data);
1284 FBase64::Decode(tmp_audio_data, QuestionItem.voice_data);
1285
1286 speak_quest_data.Add(QuestionItem);
1287 }
1288 }
1289 }
1290
1291 NETWORK_LOG(TEXT("[FResponseSpeakScenario] Parsed %d audio items"), speak_quest_data.Num());
1292 }
1293}
1294
1296{
1297 FString OutputString;
1298 FJsonObjectConverter::UStructToJsonObjectString(
1299 *this,
1300 OutputString,
1301 0,
1302 0
1303 );
1304 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
1305}
1306
1307// =================================================================================
1308// FResponseEvaluationResult
1309// =================================================================================
1310
1311void FResponseEvaluationResult::SetFromHttpResponse(const TSharedPtr<IHttpResponse, ESPMode::ThreadSafe>& Response)
1312{
1313 if (!Response.IsValid())
1314 {
1315 return;
1316 }
1317
1318 FString JsonString = Response->GetContentAsString();
1319 TSharedPtr<FJsonObject> JsonObject;
1320 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
1321
1322 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
1323 {
1324 // total_result 파싱
1325 if (JsonObject->HasTypedField<EJson::Object>(TEXT("total_result")))
1326 {
1327 TSharedPtr<FJsonObject> TotalResultObj = JsonObject->GetObjectField(TEXT("total_result"));
1328 if (TotalResultObj.IsValid())
1329 {
1330 total_result.final_score = TotalResultObj->GetIntegerField(TEXT("final_score"));
1331 total_result.grade = TotalResultObj->GetStringField(TEXT("grade"));
1332 total_result.feedback_summary = TotalResultObj->GetStringField(TEXT("feedback_summary"));
1333 }
1334 }
1335
1336 // scenario_results 배열 파싱
1337 const TArray<TSharedPtr<FJsonValue>>* ScenarioResultsArray;
1338 if (JsonObject->TryGetArrayField(TEXT("scenario_results"), ScenarioResultsArray))
1339 {
1340 for (const auto& Item : *ScenarioResultsArray)
1341 {
1342 TSharedPtr<FJsonObject> ScenarioObj = Item->AsObject();
1343 if (ScenarioObj.IsValid())
1344 {
1345 FScenarioResult ScenarioItem;
1346
1347 // scenario_type 파싱
1348 FString ScenarioTypeStr = ScenarioObj->GetStringField(TEXT("scenario_type"));
1349 if (ScenarioTypeStr == TEXT("READING"))
1350 ScenarioItem.scenario_type = EScenarioType::READING;
1351 else if (ScenarioTypeStr == TEXT("LISTENING"))
1352 ScenarioItem.scenario_type = EScenarioType::LISTENING;
1353 else if (ScenarioTypeStr == TEXT("WRITING"))
1354 ScenarioItem.scenario_type = EScenarioType::WRITING;
1355 else if (ScenarioTypeStr == TEXT("SPEAKING"))
1356 ScenarioItem.scenario_type = EScenarioType::SPEAKING;
1357
1358 // display_name 파싱
1359 ScenarioItem.display_name = ScenarioObj->GetStringField(TEXT("display_name"));
1360
1361 // final_score 파싱
1362 ScenarioItem.final_score = ScenarioObj->GetIntegerField(TEXT("final_score"));
1363
1364 // grade 파싱
1365 ScenarioItem.grade = ScenarioObj->GetStringField(TEXT("grade"));
1366
1367 // feedback_summary 파싱
1368 if (ScenarioObj->HasTypedField<EJson::Object>(TEXT("feedback_summary")))
1369 {
1370 TSharedPtr<FJsonObject> FeedbackObj = ScenarioObj->GetObjectField(TEXT("feedback_summary"));
1371 if (FeedbackObj.IsValid())
1372 {
1373 ScenarioItem.feedback_summary.title = FeedbackObj->GetStringField(TEXT("title"));
1374 ScenarioItem.feedback_summary.message = FeedbackObj->GetStringField(TEXT("message"));
1375 }
1376 }
1377
1378 // action_item 파싱
1379 ScenarioItem.action_item = ScenarioObj->GetStringField(TEXT("action_item"));
1380
1381 scenario_results.Add(ScenarioItem);
1382 }
1383 }
1384 }
1385 }
1386}
1387
1389{
1390 FString OutputString;
1391 FJsonObjectConverter::UStructToJsonObjectString(
1392 *this,
1393 OutputString,
1394 0,
1395 0
1396 );
1397 NETWORK_LOG( TEXT("[RES] %s"), *OutputString);
1398}
1399
1400
1401// =================================================================================
1402// Chat Answers API Implementation
1403// =================================================================================
1404
1405void FResponseChatAnswers::SetFromHttpResponse(const TSharedPtr<class IHttpResponse, ESPMode::ThreadSafe>& Response)
1406{
1407 if (!Response.IsValid())
1408 {
1409 return;
1410 }
1411
1412 FString JsonString = Response->GetContentAsString();
1413 TSharedPtr<FJsonObject> JsonObject;
1414 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
1415
1416 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
1417 {
1418 if (JsonObject->HasField(TEXT("question")))
1419 {
1420 question = JsonObject->GetStringField(TEXT("question"));
1421 }
1422
1423 if (JsonObject->HasField(TEXT("answer")))
1424 {
1425 answer = JsonObject->GetStringField(TEXT("answer"));
1426 }
1427 }
1428}
1429
1431{
1432 NETWORK_LOG(TEXT("[RES] Chat Answers - Answer: %s"), *answer);
1433}
1434
1435
1436// =================================================================================
1437// Chat Dailys API Implementation
1438// =================================================================================
1439
1440void FResponseChatDailys::SetFromHttpResponse(const TSharedPtr<class IHttpResponse, ESPMode::ThreadSafe>& Response)
1441{
1442 if (!Response.IsValid())
1443 {
1444 return;
1445 }
1446
1447 FString JsonString = Response->GetContentAsString();
1448 TSharedPtr<FJsonObject> JsonObject;
1449 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
1450
1451 if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
1452 {
1453 if (JsonObject->HasField(TEXT("question")))
1454 {
1455 question = JsonObject->GetStringField(TEXT("question"));
1456 }
1457
1458 if (JsonObject->HasField(TEXT("answer")))
1459 {
1460 answer = JsonObject->GetStringField(TEXT("answer"));
1461 }
1462 }
1463}
1464
1466{
1467 NETWORK_LOG(TEXT("[RES] Chat Dailys - Answer: %s"), *answer);
1468}
1469
EResourceTextureType
YiSan 전반에서 사용하는 공용 인터페이스를 선언합니다.
#define NETWORK_LOG(fmt,...)
네트워크 요청과 응답에 사용되는 구조체 및 설정을 정의합니다.
YiSan 전반에서 사용하는 공용 인터페이스를 선언합니다.
static FLinearColor GetRankColor(float InScore)
static EResourceTextureType ConvertGradeString(const FString &Grade)
static const int32 BotID
Definition Onepiece.h:56
Listen 퀘스트의 개별 점수 상세 정보를 담는 구조체입니다.
단어 데이터 구조체입니다.
FString Pronunciation
FString ToRichTextString(int32 Index) const
bool IsValid() const
구조체 값이 유효한지 여부를 반환합니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
TArray< FWriteQuestionData > question
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
Read 퀘스트의 개별 점수 상세 정보를 담는 구조체입니다.
bool ToJsonString(FString &OutJson) const
구조체를 JSON 문자열로 변환합니다.
TArray< FInterviewAnswerData > answer
TArray< int32 > wrong_idx
bool ToJsonString(FString &OutJson) const
구조체를 JSON 문자열로 변환합니다.
bool ToJsonString(FString &OutJson) const
구조체를 JSON 문자열로 변환합니다.
TArray< int32 > wrong_idx
TArray< int32 > wrong_idx
bool ToJsonString(FString &OutJson) const
구조체를 JSON 문자열로 변환합니다.
bool ToJsonString(FString &OutJson) const
구조체를 JSON 문자열로 변환합니다.
TArray< int32 > wrong_idx
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
TArray< FScenarioResult > scenario_results
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 상태 정보를 갱신합니다.
void PrintData()
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
TArray< FInterviewQuestionData > Questions
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
TArray< uint8 > audio_base64
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
TArray< FListenScoreDetail > scores
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
TArray< FString > GetWord1List() const
FScenarioTargetData GetCorrectAnswerData() const
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
TArray< FString > GetWord2List() const
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
TArray< uint8 > voice_data
TArray< FScenarioTargetData > target_data
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
TArray< FReadScoreDetail > scores
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
FScenarioTargetData GetCorrectAnswerData() const
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
TArray< FString > GetWord2List() const
TArray< FScenarioTargetData > target_data
TArray< FString > GetWord1List() const
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
TArray< FSpeakScoreDetail > scores
TArray< FResultStatData > GetResultStatData() const
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
TArray< FSpeakStageQuestion > speak_quest_data
오디오 질문 목록
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
TArray< FResultStatData > GetResultStatData() const
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 상태 정보를 갱신합니다.
FLinearColor GetChatProfileBg(int player_index) const
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 상태 정보를 갱신합니다.
EResourceTextureType GetChatProfileTextureType(int player_index) const
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 상태 정보를 갱신합니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 상태 정보를 갱신합니다.
FWriteDisplay display
FWriteRecord record
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
TArray< FResponseWriteScores > scores
Write 최종 결과 점수 정보 구조체입니다.
TArray< FResponseWriteData > ResponseWriteDataArray
void PrintData() const
디버그 로그에 응답 내용을 출력합니다.
void SetFromHttpResponse(const TSharedPtr< class IHttpResponse, ESPMode::ThreadSafe > &Response)
HTTP 응답을 파싱해 구조체를 채웁니다.
Result Stat 위젯 통합 데이터 구조 위젯 타입, 색상 스타일, 각 타입별 데이터를 통합 관리
EResourceTextureType SymbolTextureType
Symbol 타입 전용: 심볼 문자열
FLinearColor ScoreTextColor
float RatePercent
Rate 타입 전용: 퍼센트 값 (0.0 ~ 1.0)
EColorStyleType ColorType
색상 스타일
FText TitleText
타이틀 텍스트
EResultItemWidgetType WidgetType
위젯 타입
EResourceTextureType GradeTextureType
Grade 타입 전용: 텍스처 타입
float ScoreValue
Score 타입 전용: 점수 값
시나리오별 결과 구조체입니다.
FFeedbackSummary feedback_summary
EScenarioType scenario_type
Scenario 타겟 데이터입니다.
Speak 퀘스트의 개별 점수 상세 정보를 담는 구조체입니다.
SpeakQuest 오디오 질문 데이터 구조체입니다.
FString eng
영어 질문
FString GetQuestionMessage() const
TArray< uint8 > voice_data
음성 데이터 Base64
FString kor
한국어 질문
FString pronunciation
발음 가이드
FString feedback_summary
FString Kor
FString Pronunciation
TArray< FPhonemeData > GetPhonemeData() const
FString code
FString name
FString correction
FString message
Write 질문 및 정답 구조체입니다.
FWriteWordData word_data
FString input
FString target
FString stage
FString pronunciation