diff --git a/refactoring/src/main/java/com/example/refactoring/_03_long_function/_08_introduce_parameter_object/Participant.java b/refactoring/src/main/java/com/example/refactoring/_03_long_function/_08_introduce_parameter_object/Participant.java new file mode 100644 index 00000000..8cf91a77 --- /dev/null +++ b/refactoring/src/main/java/com/example/refactoring/_03_long_function/_08_introduce_parameter_object/Participant.java @@ -0,0 +1,22 @@ +package com.example.refactoring._03_long_function._08_introduce_parameter_object; + +import java.util.HashMap; +import java.util.Map; + +public record Participant(String username, Map homework) { + public Participant(String username) { + this(username, new HashMap<>()); + } + + public double getRate(double total) { + long count = this.homework.values().stream() + .filter(v -> v == true) + .count(); + return count * 100 / total; + } + + public void setHomeworkDone(int index) { + this.homework.put(index, true); + } + +} \ No newline at end of file diff --git a/refactoring/src/main/java/com/example/refactoring/_03_long_function/_08_introduce_parameter_object/StudyDashboard.java b/refactoring/src/main/java/com/example/refactoring/_03_long_function/_08_introduce_parameter_object/StudyDashboard.java new file mode 100644 index 00000000..40426f1d --- /dev/null +++ b/refactoring/src/main/java/com/example/refactoring/_03_long_function/_08_introduce_parameter_object/StudyDashboard.java @@ -0,0 +1,131 @@ +package com.example.refactoring._03_long_function._08_introduce_parameter_object; + +import org.kohsuke.github.GHIssue; +import org.kohsuke.github.GHIssueComment; +import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GitHub; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class StudyDashboard { + + // 메소드로 전달하는 공통되는 파라미터를 객체로 만들거나 멤버변수로 선언 + private final int totalNumberOfEvents; + + public StudyDashboard(int totalNumberOfEvents) { + this.totalNumberOfEvents = totalNumberOfEvents; + } + + public static void main(String[] args) throws IOException, InterruptedException { + StudyDashboard studyDashboard = new StudyDashboard(15); + studyDashboard.print(); + } + + private void print() throws IOException, InterruptedException { + GitHub gitHub = GitHub.connect(); + GHRepository repository = gitHub.getRepository("whiteship/live-study"); + List participants = new CopyOnWriteArrayList<>(); + + ExecutorService service = Executors.newFixedThreadPool(8); + CountDownLatch latch = new CountDownLatch(totalNumberOfEvents); + + for (int index = 1 ; index <= totalNumberOfEvents ; index++) { + int eventId = index; + service.execute(new Runnable() { + @Override + public void run() { + try { + GHIssue issue = repository.getIssue(eventId); + List comments = issue.getComments(); + + for (GHIssueComment comment : comments) { + String username = comment.getUserName(); + boolean isNewUser = participants.stream().noneMatch(p -> p.username().equals(username)); + Participant participant = null; + if (isNewUser) { + participant = new Participant(username); + participants.add(participant); + } else { + participant = participants.stream().filter(p -> p.username().equals(username)).findFirst().orElseThrow(); + } + + participant.setHomeworkDone(eventId); + } + + latch.countDown(); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + }); + } + + latch.await(); + service.shutdown(); + + try (FileWriter fileWriter = new FileWriter("participants.md"); + PrintWriter writer = new PrintWriter(fileWriter)) { + participants.sort(Comparator.comparing(Participant::username)); + + writer.print(header(participants.size())); + + participants.forEach(p -> { + String markdownForHomework = getMarkdownForParticipant(p); + writer.print(markdownForHomework); + }); + } + } + + private double getRate(Participant p) { + long count = p.homework().values().stream() + .filter(v -> v == true) + .count(); + double rate = count * 100 / this.totalNumberOfEvents; + return rate; + } + + private String getMarkdownForParticipant(Participant p) { + return String.format("| %s %s | %.2f%% |\n", p.username(), checkMark(p, this.totalNumberOfEvents), getRate(p)); + } + + /** + * | 참여자 (420) | 1주차 | 2주차 | 3주차 | 참석율 | + * | --- | --- | --- | --- | --- | + */ + private String header(int totalNumberOfParticipants) { + StringBuilder header = new StringBuilder(String.format("| 참여자 (%d) |", totalNumberOfParticipants)); + + for (int index = 1; index <= this.totalNumberOfEvents; index++) { + header.append(String.format(" %d주차 |", index)); + } + header.append(" 참석율 |\n"); + + header.append("| --- ".repeat(Math.max(0, this.totalNumberOfEvents + 2))); + header.append("|\n"); + + return header.toString(); + } + + /** + * |:white_check_mark:|:white_check_mark:|:white_check_mark:|:x:| + */ + private String checkMark(Participant p, int totalEvents) { + StringBuilder line = new StringBuilder(); + for (int i = 1 ; i <= totalEvents ; i++) { + if(p.homework().containsKey(i) && p.homework().get(i)) { + line.append("|:white_check_mark:"); + } else { + line.append("|:x:"); + } + } + return line.toString(); + } +}