Skip to content

Commit 1cc5263

Browse files
authored
btsk-122: learn-stat-계산방식 변경 및 마이그레이션 api에도 잔디 값 바꾸도록 변경 (#158)
* fix: learn-stat-계산방식 변경 및 마이그레이션 api에도 잔디 값 바꾸도록 * refactor: 코드스타일 * fix: 테스트코드와 로직 fix * fix: codestyle * fix: 테스트 제거 * fix: 엔드포인트 경량 웹서버로 노출
1 parent 67c39db commit 1cc5263

18 files changed

Lines changed: 115 additions & 133 deletions

docker-compose.qa.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ services:
8686
environment:
8787
<<: *pullit-common-env
8888
SPRING_PROFILES_ACTIVE: qa,worker
89+
SPRING_MAIN_WEB_APPLICATION_TYPE: NONE
90+
MANAGEMENT_SERVER_PORT: 8080
8991

9092
pullit-qa-worker-green:
9193
restart: unless-stopped
@@ -109,6 +111,8 @@ services:
109111
environment:
110112
<<: *pullit-common-env
111113
SPRING_PROFILES_ACTIVE: qa,worker
114+
SPRING_MAIN_WEB_APPLICATION_TYPE: NONE
115+
MANAGEMENT_SERVER_PORT: 8080
112116

113117
pullit-qa-db:
114118
image: mariadb:10.11

src/main/java/kr/it/pullit/modules/projection/learnstats/api/LearnStatsEventPublicApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ public interface LearnStatsEventPublicApi {
66

77
void publishQuestionSetSolved(Long memberId, int solvedQuestionCount);
88

9-
void publishCorrectAnswerCount(Long memberId, long correctCount);
9+
void publishRecalculateCorrectAnswerCount(Long memberId);
1010
}

src/main/java/kr/it/pullit/modules/projection/learnstats/domain/LearnStats.java

Lines changed: 27 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import jakarta.persistence.Table;
99
import java.time.LocalDate;
1010
import java.time.LocalDateTime;
11-
import java.time.temporal.ChronoUnit;
11+
import java.util.Comparator;
1212
import java.util.List;
1313
import kr.it.pullit.modules.projection.learnstats.exception.InvalidSolvedQuestionCountException;
1414
import kr.it.pullit.shared.jpa.BaseEntity;
@@ -78,7 +78,6 @@ public void onQuestionSetSolved(int solvedQuestionCount, LocalDate today) {
7878
this.totalSolvedQuestionSetCount++;
7979
this.totalSolvedQuestionCount += solvedQuestionCount;
8080
this.weeklySolvedQuestionCount += solvedQuestionCount;
81-
updateConsecutiveStreak(today);
8281
}
8382

8483
public void onQuestionSetDeleted(long correctQuestionsInSet) {
@@ -94,57 +93,54 @@ public void updateTotalSolvedQuestionCount(long realCount) {
9493
this.totalSolvedQuestionCount = realCount;
9594
}
9695

97-
public void increaseCorrectQuestionCount(long correctCount) {
98-
if (correctCount > 0) {
99-
this.totalCorrectQuestionCount += correctCount;
100-
}
96+
public void updateTotalCorrectQuestionCount(long totalCorrectQuestionCount) {
97+
this.totalCorrectQuestionCount = totalCorrectQuestionCount;
10198
}
10299

103100
public void recalibrate(
104101
long totalAttemptedQuestionCount,
105102
long totalCorrectQuestionCount,
106103
int weeklySolvedQuestionCount,
107-
List<LocalDateTime> completedDates) {
104+
List<LocalDateTime> completedDates,
105+
LocalDate today) {
108106
this.totalSolvedQuestionCount = totalAttemptedQuestionCount;
109107
this.totalCorrectQuestionCount = totalCorrectQuestionCount;
110108
this.weeklySolvedQuestionCount = weeklySolvedQuestionCount;
111-
this.consecutiveLearningDays = calculateConsecutiveDaysFrom(completedDates);
109+
this.consecutiveLearningDays = calculateCurrentStreakFrom(completedDates, today);
112110
this.lastLearningDate = findLastLearningDateFrom(completedDates);
113111
}
114112

115-
private int calculateConsecutiveDaysFrom(List<LocalDateTime> completedDates) {
113+
private int calculateCurrentStreakFrom(List<LocalDateTime> completedDates, LocalDate today) {
116114
if (completedDates == null || completedDates.isEmpty()) {
117115
return 0;
118116
}
119117

120-
List<LocalDateTime> sortedCompletedDates = completedDates.stream().sorted().toList();
121-
122-
int consecutiveDays = 0;
123-
LocalDate previousDate = null;
118+
List<LocalDate> distinctSortedDates =
119+
completedDates.stream()
120+
.map(LocalDateTime::toLocalDate)
121+
.distinct()
122+
.sorted(Comparator.reverseOrder())
123+
.toList();
124124

125-
for (LocalDateTime completedDateTime : sortedCompletedDates) {
126-
LocalDate currentDate = completedDateTime.toLocalDate();
127-
consecutiveDays = updateConsecutiveCount(consecutiveDays, previousDate, currentDate);
128-
previousDate = currentDate;
129-
}
130-
return consecutiveDays;
131-
}
125+
LocalDate lastDate = distinctSortedDates.get(0);
132126

133-
private int updateConsecutiveCount(
134-
int currentConsecutiveDays, LocalDate previousDate, LocalDate currentDate) {
135-
if (previousDate == null) {
136-
return 1;
127+
if (DAYS.between(lastDate, today) > 1) {
128+
return 0;
137129
}
138130

139-
long daysBetween = ChronoUnit.DAYS.between(previousDate, currentDate);
131+
int consecutiveDays = 1;
132+
LocalDate previousDate = lastDate;
140133

141-
if (daysBetween == 1) {
142-
return currentConsecutiveDays + 1;
143-
}
144-
if (daysBetween > 1) {
145-
return 1;
134+
for (int i = 1; i < distinctSortedDates.size(); i++) {
135+
LocalDate currentDate = distinctSortedDates.get(i);
136+
if (DAYS.between(currentDate, previousDate) == 1) {
137+
consecutiveDays++;
138+
previousDate = currentDate;
139+
} else {
140+
break;
141+
}
146142
}
147-
return currentConsecutiveDays;
143+
return consecutiveDays;
148144
}
149145

150146
private LocalDate findLastLearningDateFrom(List<LocalDateTime> completedDates) {
@@ -157,38 +153,6 @@ private LocalDate findLastLearningDateFrom(List<LocalDateTime> completedDates) {
157153
.orElse(null);
158154
}
159155

160-
private void updateConsecutiveStreak(LocalDate today) {
161-
if (lastLearningDate == null) {
162-
consecutiveLearningDays = 1;
163-
lastLearningDate = today;
164-
return;
165-
}
166-
167-
int delta = (int) DAYS.between(lastLearningDate, today);
168-
169-
if (isSameOrPastDay(delta)) {
170-
updateLastLearningDateIfNeeded(today);
171-
return;
172-
}
173-
174-
updateConsecutiveDays(delta);
175-
lastLearningDate = today;
176-
}
177-
178-
private void updateConsecutiveDays(int delta) {
179-
consecutiveLearningDays = (delta == 1) ? consecutiveLearningDays + 1 : 1;
180-
}
181-
182-
private void updateLastLearningDateIfNeeded(LocalDate today) {
183-
if (today.isAfter(lastLearningDate)) {
184-
lastLearningDate = today;
185-
}
186-
}
187-
188-
private boolean isSameOrPastDay(int delta) {
189-
return delta <= 0;
190-
}
191-
192156
public void resetConsecutiveDaysIfMissed(LocalDate today) {
193157
if (lastLearningDate != null) {
194158
long daysBetween = DAYS.between(lastLearningDate, today);

src/main/java/kr/it/pullit/modules/projection/learnstats/event/handler/LearnStatsEventDispatcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public boolean dispatch(OutboxEvent e) {
4141
case CORRECT_ANSWER_COUNT_INCREASED -> {
4242
CorrectAnswerPayload payload =
4343
objectMapper.readValue(e.getPayload(), CorrectAnswerPayload.class);
44-
projectionService.increaseCorrectQuestionCount(payload.memberId(), payload.correctCount());
44+
projectionService.recalculateCorrectQuestionCount(payload.memberId());
4545
}
4646
default -> {
4747
return false;

src/main/java/kr/it/pullit/modules/projection/learnstats/event/publisher/LearnStatsEventPublisher.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ public void publishQuestionSetSolved(Long memberId, int solvedQuestionCount) {
4141

4242
@Override
4343
@SneakyThrows
44-
public void publishCorrectAnswerCount(Long memberId, long correctCount) {
45-
CorrectAnswerPayload payload = new CorrectAnswerPayload(memberId, correctCount);
44+
public void publishRecalculateCorrectAnswerCount(Long memberId) {
45+
CorrectAnswerPayload payload = new CorrectAnswerPayload(memberId, 0);
4646
String jsonPayload = objectMapper.writeValueAsString(payload);
4747
OutboxEvent event =
4848
OutboxEvent.of(

src/main/java/kr/it/pullit/modules/projection/learnstats/service/LearnStatsRecalibrationService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.time.Clock;
44
import java.time.DayOfWeek;
5+
import java.time.LocalDate;
56
import java.time.LocalDateTime;
67
import java.time.temporal.TemporalAdjusters;
78
import java.util.List;
@@ -70,7 +71,12 @@ private void recalibrateMember(Long memberId) {
7071
LearnStats stats =
7172
learnStatsRepository.findById(memberId).orElseGet(() -> LearnStats.newOf(memberId));
7273

73-
stats.recalibrate(totalAttemptedCount, totalCorrectCount, weeklySolvedCount, completedDates);
74+
stats.recalibrate(
75+
totalAttemptedCount,
76+
totalCorrectCount,
77+
weeklySolvedCount,
78+
completedDates,
79+
LocalDate.now(clock));
7480
stats.updateTotalQuestionCount(totalQuestionCount);
7581

7682
learnStatsRepository.save(stats);

src/main/java/kr/it/pullit/modules/projection/learnstats/service/LearnStatsService.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import kr.it.pullit.modules.projection.learnstats.api.LearnStatsPublicApi;
77
import kr.it.pullit.modules.projection.learnstats.domain.LearnStats;
88
import kr.it.pullit.modules.projection.learnstats.repository.LearnStatsRepository;
9+
import kr.it.pullit.modules.questionset.api.MarkingResultPublicApi;
910
import lombok.RequiredArgsConstructor;
1011
import org.springframework.stereotype.Service;
1112
import org.springframework.transaction.annotation.Transactional;
@@ -16,6 +17,7 @@
1617
public class LearnStatsService implements LearnStatsPublicApi {
1718

1819
private final LearnStatsRepository repo;
20+
private final MarkingResultPublicApi markingResultPublicApi;
1921
private final Clock clock;
2022

2123
@Override
@@ -32,6 +34,14 @@ public void applyQuestionSetSolved(Long memberId, int questionCount) {
3234
repo.save(p);
3335
}
3436

37+
public void recalculateCorrectQuestionCount(Long memberId) {
38+
long totalCorrectQuestionCount = markingResultPublicApi.countCorrectAnswersByMemberId(memberId);
39+
40+
LearnStats p = repo.findById(memberId).orElseGet(() -> LearnStats.newOf(memberId));
41+
p.updateTotalCorrectQuestionCount(totalCorrectQuestionCount);
42+
repo.save(p);
43+
}
44+
3545
@Override
3646
public void applyQuestionSetDeleted(Long memberId, long correctQuestionCount) {
3747
repo.findById(memberId)
@@ -42,12 +52,6 @@ public void applyQuestionSetDeleted(Long memberId, long correctQuestionCount) {
4252
});
4353
}
4454

45-
public void increaseCorrectQuestionCount(Long memberId, long correctCount) {
46-
LearnStats p = repo.findById(memberId).orElseGet(() -> LearnStats.newOf(memberId));
47-
p.increaseCorrectQuestionCount(correctCount);
48-
repo.save(p);
49-
}
50-
5155
@Override
5256
@Transactional(readOnly = true)
5357
public Optional<LearnStats> getLearnStats(Long memberId) {

src/main/java/kr/it/pullit/modules/questionset/api/MarkingResultPublicApi.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ public interface MarkingResultPublicApi {
1616
* @return 총 맞힌 문제 수
1717
*/
1818
long countTotalCorrectQuestionsByMemberId(Long memberId);
19+
20+
long countCorrectAnswersByMemberId(Long memberId);
1921
}

src/main/java/kr/it/pullit/modules/questionset/event/MarkingCompletedEventHandler.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import kr.it.pullit.modules.projection.learnstats.api.LearnStatsDailyPublicApi;
44
import kr.it.pullit.modules.projection.learnstats.api.LearnStatsEventPublicApi;
5-
import kr.it.pullit.modules.questionset.web.dto.response.MarkingResultDto;
65
import lombok.RequiredArgsConstructor;
76
import org.springframework.stereotype.Component;
87
import org.springframework.transaction.annotation.Propagation;
@@ -25,10 +24,7 @@ public void handleMarkingCompletedEvent(MarkingCompletedEvent event) {
2524
return;
2625
}
2726

28-
long correctCount = event.results().stream().filter(MarkingResultDto::isCorrect).count();
29-
if (correctCount > 0) {
30-
learnStatsEventPublicApi.publishCorrectAnswerCount(event.memberId(), correctCount);
31-
}
27+
learnStatsEventPublicApi.publishRecalculateCorrectAnswerCount(event.memberId());
3228

3329
learnStatsEventPublicApi.publishQuestionSetSolved(event.memberId(), event.results().size());
3430
learnStatsDailyPublicApi.addDailyStats(event.memberId(), event.results().size(), 1);

src/main/java/kr/it/pullit/modules/questionset/repository/MarkingResultRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ public interface MarkingResultRepository {
1212
long countDistinctQuestionByMemberId(Long memberId);
1313

1414
long countByMemberIdAndIsCorrectIsTrue(Long memberId);
15+
16+
long countCorrectAnswersByMemberId(Long memberId);
1517
}

0 commit comments

Comments
 (0)