Skip to content

Commit 38d6421

Browse files
authored
Merge pull request #64 from CommitField/feat/#59
Feat: ์‹œ์ฆŒ ๋ณ„ ์—ฐ์† ์ปค๋ฐ‹ ํšŸ์ˆ˜, ์ตœ๋Œ€ ์—ฐ์† ์ปค๋ฐ‹ ํšŸ์ˆ˜, ์ด ์ปค๋ฐ‹ ์ˆ˜ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
2 parents f35ddd4 + 54febc1 commit 38d6421

File tree

3 files changed

+152
-32
lines changed

3 files changed

+152
-32
lines changed
Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cmf.commitField.domain.commit.sinceCommit.controller;
22

3+
import cmf.commitField.domain.commit.sinceCommit.dto.CommitAnalysisResponseDto;
34
import cmf.commitField.domain.commit.sinceCommit.dto.SinceCommitResponseDto;
45
import cmf.commitField.domain.commit.sinceCommit.service.SinceCommitService;
56
import lombok.RequiredArgsConstructor;
@@ -24,72 +25,79 @@ public ResponseEntity<List<SinceCommitResponseDto>> getCommits(
2425
@RequestParam String repo,
2526
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime since,
2627
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime until
27-
) {
28+
) {
2829
List<SinceCommitResponseDto> sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until);
29-
3030
return ResponseEntity.ok(sinceCommits);
3131
}
3232

33-
// ์‹œ์ฆŒ ๋ณ„ ์ปค๋ฐ‹ ์ˆ˜ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
33+
// ์—ฐ์† ์ปค๋ฐ‹ ์ผ์ˆ˜์™€ ๊ฐ™์€ ์ถ”๊ฐ€ ๋ถ„์„ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ฐ˜ํ™˜
34+
@GetMapping("/api/github/commits-analysis")
35+
public ResponseEntity<CommitAnalysisResponseDto> getCommitsAnalysis(
36+
@RequestParam String owner,
37+
@RequestParam String repo,
38+
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime since,
39+
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime until
40+
) {
41+
CommitAnalysisResponseDto analysis = sinceCommitService.getCommitAnalysis(owner, repo, since, until);
42+
return ResponseEntity.ok(analysis);
43+
}
44+
45+
// ์‹œ์ฆŒ ๋ณ„ ์ปค๋ฐ‹ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ(ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ 2024๋…„ ์„ค์ •)
3446

35-
// ๋ด„ ์‹œ์ฆŒ
47+
// ๋ด„ ์‹œ์ฆŒ(3/1 - 5/31)
3648
@GetMapping("/api/github/commits-spring")
37-
public ResponseEntity<List<SinceCommitResponseDto>> getSpringSeasonCommits(
49+
public ResponseEntity<CommitAnalysisResponseDto> getSpringSeasonCommits(
3850
@RequestParam String owner,
3951
@RequestParam String repo
4052
) {
4153
int currentYear = LocalDateTime.now().getYear();
4254
LocalDateTime since = LocalDateTime.of(2024, 3, 1, 0, 0);
4355
LocalDateTime until = LocalDateTime.of(2024, 5, 31, 23, 59, 59);
4456

45-
List<SinceCommitResponseDto> sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until);
46-
47-
return ResponseEntity.ok(sinceCommits);
57+
CommitAnalysisResponseDto analysis = sinceCommitService.getCommitAnalysis(owner, repo, since, until);
58+
return ResponseEntity.ok(analysis);
4859
}
4960

50-
// ์—ฌ๋ฆ„ ์‹œ์ฆŒ
61+
// ์—ฌ๋ฆ„ ์‹œ์ฆŒ(6/1 - 8/31)
5162
@GetMapping("/api/github/commits-summer")
52-
public ResponseEntity<List<SinceCommitResponseDto>> getSummerSeasonCommits(
63+
public ResponseEntity<CommitAnalysisResponseDto> getSummerSeasonCommits(
5364
@RequestParam String owner,
5465
@RequestParam String repo
5566
) {
5667
int currentYear = LocalDateTime.now().getYear();
57-
LocalDateTime since = LocalDateTime.of(currentYear, 6, 1, 0, 0);
58-
LocalDateTime until = LocalDateTime.of(currentYear, 8, 31, 23, 59, 59);
59-
60-
List<SinceCommitResponseDto> sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until);
68+
LocalDateTime since = LocalDateTime.of(2024, 6, 1, 0, 0);
69+
LocalDateTime until = LocalDateTime.of(2024, 8, 31, 23, 59, 59);
6170

62-
return ResponseEntity.ok(sinceCommits);
71+
CommitAnalysisResponseDto analysis = sinceCommitService.getCommitAnalysis(owner, repo, since, until);
72+
return ResponseEntity.ok(analysis);
6373
}
6474

65-
// ๊ฐ€์„ ์‹œ์ฆŒ
75+
// ๊ฐ€์„ ์‹œ์ฆŒ(9/1 - 11/30)
6676
@GetMapping("/api/github/commits-fall")
67-
public ResponseEntity<List<SinceCommitResponseDto>> getFallSeasonCommits(
77+
public ResponseEntity<CommitAnalysisResponseDto> getFallSeasonCommits(
6878
@RequestParam String owner,
6979
@RequestParam String repo
7080
) {
7181
int currentYear = LocalDateTime.now().getYear();
72-
LocalDateTime since = LocalDateTime.of(currentYear, 9, 1, 0, 0);
73-
LocalDateTime until = LocalDateTime.of(currentYear, 11, 30, 23, 59, 59);
74-
75-
List<SinceCommitResponseDto> sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until);
82+
LocalDateTime since = LocalDateTime.of(2024, 9, 1, 0, 0);
83+
LocalDateTime until = LocalDateTime.of(2024, 11, 30, 23, 59, 59);
7684

77-
return ResponseEntity.ok(sinceCommits);
85+
CommitAnalysisResponseDto analysis = sinceCommitService.getCommitAnalysis(owner, repo, since, until);
86+
return ResponseEntity.ok(analysis);
7887
}
7988

80-
// ๊ฒจ์šธ ์‹œ์ฆŒ
89+
// ๊ฒจ์šธ ์‹œ์ฆŒ(์ด์ „ ๋…„๋„ 12/1 - ๋‹ค์Œ ๋…„๋„ 2/30)
8190
@GetMapping("/api/github/commits-winter")
82-
public ResponseEntity<List<SinceCommitResponseDto>> getWinterSeasonCommits(
91+
public ResponseEntity<CommitAnalysisResponseDto> getWinterSeasonCommits(
8392
@RequestParam String owner,
8493
@RequestParam String repo
8594
) {
8695
int currentYear = LocalDateTime.now().getYear();
87-
LocalDateTime since = LocalDateTime.of(currentYear, 12, 1, 0, 0);
88-
LocalDateTime until = LocalDateTime.of(currentYear + 1, 2, 1, 23, 59, 59)
89-
.with(TemporalAdjusters.lastDayOfMonth()); // ์œค๋…„ ๊ณ ๋ ค
96+
LocalDateTime since = LocalDateTime.of(2023, 12, 1, 0, 0);
97+
LocalDateTime until = LocalDateTime.of(2024 + 1, 2, 1, 23, 59, 59)
98+
.with(TemporalAdjusters.lastDayOfMonth());
9099

91-
List<SinceCommitResponseDto> sinceCommits = sinceCommitService.getSinceCommits(owner, repo, since, until);
92-
93-
return ResponseEntity.ok(sinceCommits);
100+
CommitAnalysisResponseDto analysis = sinceCommitService.getCommitAnalysis(owner, repo, since, until);
101+
return ResponseEntity.ok(analysis);
94102
}
95103
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package cmf.commitField.domain.commit.sinceCommit.dto;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.Setter;
6+
7+
import java.util.List;
8+
9+
@Getter
10+
@Setter
11+
public class CommitAnalysisResponseDto {
12+
private final List<SinceCommitResponseDto> commits;
13+
private final int totalCommits;
14+
private final int currentStreakDays;
15+
private final int maxStreakDays;
16+
17+
public CommitAnalysisResponseDto(List<SinceCommitResponseDto> commits, int currentStreakDays, int maxStreakDays) {
18+
this.commits = commits;
19+
this.totalCommits = commits.size();
20+
this.currentStreakDays = currentStreakDays;
21+
this.maxStreakDays = maxStreakDays;
22+
}
23+
}

โ€Žsrc/main/java/cmf/commitField/domain/commit/sinceCommit/service/SinceCommitService.javaโ€Ž

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package cmf.commitField.domain.commit.sinceCommit.service;
22

3+
import cmf.commitField.domain.commit.sinceCommit.dto.CommitAnalysisResponseDto;
34
import cmf.commitField.domain.commit.sinceCommit.dto.SinceCommitResponseDto;
5+
import lombok.AllArgsConstructor;
6+
import lombok.NoArgsConstructor;
7+
import lombok.RequiredArgsConstructor;
48
import lombok.extern.slf4j.Slf4j;
59
import org.springframework.beans.factory.annotation.Value;
610
import org.springframework.core.ParameterizedTypeReference;
@@ -9,9 +13,12 @@
913
import org.springframework.stereotype.Service;
1014
import org.springframework.web.reactive.function.client.WebClient;
1115

16+
import java.time.LocalDate;
1217
import java.time.LocalDateTime;
18+
import java.time.ZoneOffset;
1319
import java.time.format.DateTimeFormatter;
14-
import java.util.List;
20+
import java.util.*;
21+
import java.util.stream.Collectors;
1522

1623
@Slf4j
1724
@Service
@@ -37,13 +44,95 @@ public List<SinceCommitResponseDto> getSinceCommits(String owner, String repo, L
3744
.build(owner, repo))
3845
.header("Authorization", "bearer " + PAT)
3946
.retrieve()
40-
.bodyToMono(new ParameterizedTypeReference<List<SinceCommitResponseDto>>() {})
47+
.bodyToMono(new ParameterizedTypeReference<List<SinceCommitResponseDto>>() {
48+
})
4149
.block();
4250
} catch (Exception e) {
4351
log.error("GitHub API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {}", e.getMessage());
4452
throw new RuntimeException("GitHub API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.", e);
4553
}
4654
}
55+
56+
// ์—ฐ์† ์ปค๋ฐ‹ ์ˆ˜ ๊ณ„์‚ฐ
57+
58+
// ์ƒˆ๋กœ์šด ๋ถ„์„ ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€
59+
public CommitAnalysisResponseDto getCommitAnalysis(String owner, String repo, LocalDateTime since, LocalDateTime until) {
60+
List<SinceCommitResponseDto> commits = getSinceCommits(owner, repo, since, until);
61+
StreakResult streakResult = calculateStreaks(commits);
62+
return new CommitAnalysisResponseDto(commits, streakResult.currentStreak, streakResult.maxStreak);
63+
}
64+
65+
@RequiredArgsConstructor
66+
private static class StreakResult {
67+
final int currentStreak;
68+
final int maxStreak;
69+
}
70+
71+
private StreakResult calculateStreaks(List<SinceCommitResponseDto> commits) {
72+
if (commits == null || commits.isEmpty()) {
73+
return new StreakResult(0, 0);
74+
}
75+
76+
// ์ปค๋ฐ‹ ๋‚ ์งœ๋ฅผ LocalDate๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  Set์œผ๋กœ ์ค‘๋ณต ์ œ๊ฑฐ
77+
Set<LocalDate> commitDates = commits.stream()
78+
.map(commit -> LocalDateTime.parse(
79+
commit.getCommit().getAuthor().getDate(),
80+
DateTimeFormatter.ISO_DATE_TIME)
81+
.toLocalDate())
82+
.collect(Collectors.toCollection(TreeSet::new));
83+
84+
// ์˜ค๋Š˜ ๋‚ ์งœ ๊ฐ€์ ธ์˜ค๊ธฐ (UTC ๊ธฐ์ค€)
85+
LocalDate today = LocalDate.now(ZoneOffset.UTC);
86+
87+
// ํ˜„์žฌ streak ๊ณ„์‚ฐ
88+
int currentStreak = calculateCurrentStreak(commitDates, today);
89+
90+
// ์ตœ๋Œ€ streak ๊ณ„์‚ฐ
91+
int maxStreak = calculateMaxStreak(commitDates);
92+
93+
return new StreakResult(currentStreak, maxStreak);
94+
}
95+
96+
private int calculateCurrentStreak(Set<LocalDate> commitDates, LocalDate today) {
97+
// ์–ด์ œ ์ปค๋ฐ‹์ด ์—†์œผ๋ฉด ์˜ค๋Š˜ ์ปค๋ฐ‹๋งŒ ํ™•์ธ
98+
if (!commitDates.contains(today.minusDays(1))) {
99+
return commitDates.contains(today) ? 1 : 0;
100+
}
101+
102+
int streakCount = 0;
103+
LocalDate checkDate = today;
104+
105+
// ์˜ค๋Š˜๋ถ€ํ„ฐ ์—ญ์ˆœ์œผ๋กœ ์—ฐ์†๋œ ์ปค๋ฐ‹์ด ์žˆ๋Š”์ง€ ํ™•์ธ
106+
while (commitDates.contains(checkDate)) {
107+
streakCount++;
108+
checkDate = checkDate.minusDays(1);
109+
}
110+
111+
return streakCount;
112+
}
113+
114+
private int calculateMaxStreak(Set<LocalDate> commitDates) {
115+
if (commitDates.isEmpty()) {
116+
return 0;
117+
}
118+
119+
List<LocalDate> sortedDates = new ArrayList<>(commitDates);
120+
Collections.sort(sortedDates);
121+
122+
int maxStreak = 1;
123+
int currentStreak = 1;
124+
125+
for (int i = 1; i < sortedDates.size(); i++) {
126+
if (sortedDates.get(i).minusDays(1).equals(sortedDates.get(i - 1))) {
127+
currentStreak++;
128+
maxStreak = Math.max(maxStreak, currentStreak);
129+
} else {
130+
currentStreak = 1;
131+
}
132+
}
133+
134+
return maxStreak;
135+
}
47136
}
48137
/*
49138
ParameterizedTypeReference๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฃผ์š” ์ด์œ 

0 commit comments

Comments
ย (0)