11package com .example .enjoy .service ;
22
3+ import ch .qos .logback .core .joran .sanity .Pair ;
34import com .example .enjoy .dto .CourseDto ;
45import com .example .enjoy .dto .CourseStatusDto ;
56import com .example .enjoy .dto .TrackDetailDto ;
67import com .example .enjoy .dto .TrackProgressDto ;
8+ import com .example .enjoy .entity .FavoriteCourse ;
79import com .example .enjoy .entity .StudentCourse ;
810import com .example .enjoy .entity .Track ;
911import com .example .enjoy .entity .TrackCourse ;
12+ import com .example .enjoy .entity .user .User ;
13+ import com .example .enjoy .repository .FavoriteCourseRepository ;
1014import com .example .enjoy .repository .StudentCourseRepository ;
1115import com .example .enjoy .repository .TrackRepository ;
16+ import com .example .enjoy .repository .UserRepository ;
1217import org .springframework .stereotype .Service ;
1318import lombok .RequiredArgsConstructor ;
1419import org .springframework .transaction .annotation .Transactional ;
@@ -24,7 +29,10 @@ public class TrackService {
2429
2530 private final TrackRepository trackRepository ;
2631 private final StudentCourseRepository studentCourseRepository ; // 기존 기능
32+ private final FavoriteCourseRepository favoriteCourseRepository ;
33+ private final UserRepository userRepository ;
2734
35+ //진척률 계산
2836 public List <TrackProgressDto > calculateTrackProgress (String studentId ) {
2937 Set <String > completedCourseNames = getCompletedCourseNames (studentId ); // 이수 과목명 목록
3038
@@ -60,13 +68,13 @@ public List<TrackProgressDto> calculateTrackProgress(String studentId) {
6068 * 학생이 이수한 과목 이름을 Set으로 반환하는 메서드
6169 */
6270 @ Transactional (readOnly = true )
63- public TrackDetailDto getTrackDetails (String studentId , Long trackId ) {
71+ public TrackDetailDto getTrackDetails (String studentId , String trackName ) {
6472
6573 // 1. [리팩토링] 학생 이수 과목 조회 로직을 private 메서드로 호출
6674 Set <String > completedCourseNames = getCompletedCourseNames (studentId );
6775
68- // 2. ID로 트랙 정보와 소속 과목들을 한번에 조회
69- Track track = trackRepository .findByIdWithCourses ( trackId )
76+ // 2. 트랙 정보와 소속 과목들을 한번에 조회
77+ Track track = trackRepository .findByName ( trackName )
7078 .orElseThrow (() -> new IllegalArgumentException ("존재하지 않는 트랙입니다." ));
7179
7280 // 3. 트랙의 과목 목록을 CourseStatusDto 리스트로 변환
@@ -101,6 +109,33 @@ public TrackDetailDto getTrackDetails(String studentId, Long trackId) {
101109 return trackDetailDto ;
102110 }
103111
112+ public TrackDetailDto getTrackDetailsByName (String trackName ) {
113+ Track track = trackRepository .findByName (trackName )
114+ .orElseThrow (() -> new IllegalArgumentException ("존재하지 않는 트랙입니다." ));
115+
116+ // 트랙의 과목 목록을 CourseStatusDto 리스트로 변환
117+ List <CourseStatusDto > courseStatusList = track .getCourses ().stream ()
118+ .map (trackCourse -> {
119+ CourseStatusDto dto = new CourseStatusDto ();
120+ dto .setTitle (trackCourse .getCourseName ());
121+ dto .setCode (trackCourse .getCourseCode ());
122+ dto .setYear (trackCourse .getAcademicYear ());
123+ dto .setSemester (trackCourse .getAcademicSemester ());
124+ dto .setStatus ("NONE" ); // 기본값 설정, 이수 여부는 별도로 처리
125+ return dto ;
126+ })
127+ .collect (Collectors .toList ());
128+
129+ // 최종적으로 TrackDetailDto를 조립하여 반환
130+ TrackDetailDto trackDetailDto = new TrackDetailDto ();
131+ trackDetailDto .setTrackId (track .getId ());
132+ trackDetailDto .setTrackName (track .getName ());
133+ trackDetailDto .setDepartment (track .getDepartment ());
134+ trackDetailDto .setCourses (courseStatusList );
135+
136+ return trackDetailDto ;
137+ }
138+
104139 /**
105140 * 학생 ID로 해당 학생이 이수한 모든 과목명을 조회합니다.
106141 */
@@ -118,4 +153,67 @@ private boolean isCourseCompleted(TrackCourse course, Set<String> completedCours
118153 return completedCourseNames .contains (course .getCourseName ()) ||
119154 (course .getCourseAlias () != null && completedCourseNames .contains (course .getCourseAlias ()));
120155 }
156+
157+ public Track getTopTrackByProgressScore (String studentId ) {
158+ User user = userRepository .findByStudentId (studentId )
159+ .orElseThrow (() -> new RuntimeException ("사용자를 찾을 수 없습니다." ));
160+ List <TrackProgressDto > trackProgress = calculateTrackProgress (studentId );
161+
162+ TrackProgressDto topProgress = trackProgress .stream ()
163+ .max ((a , b ) -> Double .compare (
164+ (double ) a .getCompletedCount () / a .getRequiredCount (),
165+ (double ) b .getCompletedCount () / b .getRequiredCount ()))
166+ .orElse (null );
167+
168+ if (topProgress == null ) {
169+ return null ;
170+ }
171+
172+ return trackRepository .findByName (topProgress .getTrackName ())
173+ .orElse (null );
174+ }
175+
176+ // 선호과목 기준 추천 트랙 1개 반환
177+ public Track getTopTrackByFavoriteScore (String studentId ) {
178+ User user = userRepository .findByStudentId (studentId )
179+ .orElseThrow (() -> new RuntimeException ("사용자를 찾을 수 없습니다." ));
180+ Set <String > favoriteCourses = favoriteCourseRepository .findAllByUser (user )
181+ .stream ()
182+ .map (FavoriteCourse ::getCourseName )
183+ .collect (Collectors .toSet ());
184+
185+ List <TrackProgressDto > trackProgress = calculateTrackProgress (studentId );
186+
187+ TrackProgressDto topFavorite = trackProgress .stream ()
188+ .max ((a , b ) -> Double .compare (
189+ calculateFavoriteScore (a , favoriteCourses ),
190+ calculateFavoriteScore (b , favoriteCourses )))
191+ .orElse (null );
192+
193+ if (topFavorite == null ) {
194+ return null ;
195+ }
196+
197+ return trackRepository .findByName (topFavorite .getTrackName ())
198+ .orElse (null );
199+ }
200+
201+ private double calculateFavoriteScore (TrackProgressDto track , Set <String > favoriteCourses ) {
202+ List <CourseDto > allCourses = new ArrayList <>();
203+ allCourses .addAll (track .getCompletedCourses ());
204+ allCourses .addAll (track .getRemainingCourses ());
205+
206+ long matchCount = allCourses .stream ()
207+ .filter (course ->
208+ (course .getCourseName () != null && favoriteCourses .contains (course .getCourseName ())) ||
209+ (course .getCourseAlias () != null && favoriteCourses .contains (course .getCourseAlias ()))
210+ )
211+ .count ();
212+
213+ return allCourses .isEmpty () ? 0.0 : (double ) matchCount / allCourses .size ();
214+ }
215+
216+ public List <Track > getAllTracks () {
217+ return trackRepository .findAll ();
218+ }
121219}
0 commit comments