1+ package com .swunitzel .fiterview .services ;
2+
3+ import com .swunitzel .fiterview .apiPayload .code .status .ErrorStatus ;
4+ import com .swunitzel .fiterview .apiPayload .exception .handler .InterviewHandler ;
5+ import com .swunitzel .fiterview .converter .ReportConverter ;
6+ import com .swunitzel .fiterview .domain .Answer ;
7+ import com .swunitzel .fiterview .domain .Interview ;
8+ import com .swunitzel .fiterview .dto .ReportDto ;
9+ import com .swunitzel .fiterview .repository .AnswerRepository ;
10+ import com .swunitzel .fiterview .repository .InterviewRepository ;
11+ import lombok .RequiredArgsConstructor ;
12+ import org .springframework .stereotype .Service ;
13+
14+ import java .util .List ;
15+
16+ @ Service
17+ @ RequiredArgsConstructor
18+ public class ReportService {
19+
20+ private final AnswerRepository answerRepository ;
21+ private final InterviewRepository interviewRepository ;
22+
23+ public ReportDto .NonverbalCommunicationReportDto getNonverbalCommunicationReport (String interviewId ) {
24+
25+ List <Answer > answers = answerRepository .findAllByInterviewId (interviewId );
26+
27+ // 영상 분석 결과 지표 합계
28+ float totalPostureScore = 0f ;
29+ float totalSmileScore = 0f ;
30+ int totalGazeDownScore = 0 ;
31+
32+ // 자세 측정 카운드
33+ int totalShoulderTiltCount = 0 ;
34+ int totalTurnLeftCount = 0 ;
35+ int totalTurnRightCount = 0 ;
36+
37+ for (Answer answer : answers ) {
38+ totalPostureScore += scorePosture (
39+ answer .getShoulderTiltCount (),
40+ answer .getTurnLeftCount (),
41+ answer .getTurnRightCount ());
42+ totalSmileScore += scoreSmile (answer .getSmileRatio ());
43+ totalGazeDownScore += scoreGaze (answer .getGazeDownCount ());
44+ totalShoulderTiltCount += answer .getShoulderTiltCount ();
45+ totalTurnLeftCount += answer .getTurnLeftCount ();
46+ totalTurnRightCount += answer .getTurnRightCount ();
47+ }
48+
49+ int answerCount = answers .size ();
50+
51+ float avgPostureScore = totalPostureScore / answerCount ;
52+ float avgFacialScore = totalSmileScore / answerCount ;
53+ float avgGazeScore = totalGazeDownScore / answerCount ;
54+ float avgShoulderTiltCount = totalShoulderTiltCount / answerCount ;
55+ float avgTurnLeftCount = totalTurnLeftCount / answerCount ;
56+ float avgTurnRightCount = totalTurnRightCount / answerCount ;
57+
58+ // 인터뷰에 총첨 업데이트
59+ Interview interview = interviewRepository .findById (interviewId )
60+ .orElseThrow (() -> new InterviewHandler (ErrorStatus ._INTERVIEW_NOT_FOUND ));
61+
62+ Interview updatedInterview = interview .updateTotalScore (avgPostureScore , avgFacialScore , avgGazeScore ,
63+ avgShoulderTiltCount , avgTurnLeftCount , avgTurnRightCount );
64+
65+ return ReportConverter .toDto (updatedInterview );
66+ }
67+
68+ int scoreGaze (int downCount ) {
69+ if (downCount <= 3 ) {
70+ return 100 ;
71+ } else if (downCount <= 6 ) {
72+ return 90 ;
73+ } else if (downCount <= 10 ) {
74+ return 80 ;
75+ } else if (downCount <= 15 ) {
76+ return 70 ;
77+ } else {
78+ return 60 ;
79+ }
80+ }
81+
82+ float scorePosture (int shoulderTilt , int turnLeft , int turnRight ) {
83+
84+ // 가중치 적용 (어깨기울기 2배, 고개 돌림 각각 1배)
85+ int weightedSum = shoulderTilt * 2 + turnLeft + turnRight ;
86+
87+ return 100f - weightedSum * 1.5f ;
88+ }
89+
90+ float scoreSmile (float smilRatio ) {
91+ if (smilRatio >= 0.5f ) {
92+ return 90 + (smilRatio - 0.5f ) * 20 ; // 90~100점
93+ } else if (smilRatio >= 0.3f ) {
94+ return 70 + (smilRatio - 0.3f ) * 100 ; // 70~89점
95+ } else {
96+ return 50 * smilRatio / 0.3f ; // 0~50점
97+ }
98+ }
99+ }
0 commit comments