From 6b96ea12a488a910ec494731feacf83126f73dd3 Mon Sep 17 00:00:00 2001 From: coco3x Date: Sun, 12 May 2024 21:30:06 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AdminQueryController.java | 20 +++++- .../third_project/database/Database.java | 24 ++++++-- .../third_project/database/Job.java | 28 +++++++++ .../third_project/database/JobField.java | 13 ++++ .../third_project/database/Registration.java | 30 ++++++--- .../dto/ApplicantNumberByJobRes.java | 7 +++ ...licantNumbersByJobFieldAndPriorityRes.java | 9 +++ .../third_project/dto/JobFieldByPriority.java | 7 +++ .../dto/PostRegistrationRes.java | 5 ++ .../service/RegistrationService.java | 61 +++++++++++++++++++ 10 files changed, 189 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/econovation/third_project/database/Job.java create mode 100644 src/main/java/com/econovation/third_project/database/JobField.java create mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java create mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java create mode 100644 src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java create mode 100644 src/main/java/com/econovation/third_project/dto/PostRegistrationRes.java create mode 100644 src/main/java/com/econovation/third_project/service/RegistrationService.java diff --git a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java index 4c15adb..46ffaa6 100644 --- a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java +++ b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java @@ -2,6 +2,9 @@ import com.econovation.third_project.database.Database; import com.econovation.third_project.database.Registration; +import com.econovation.third_project.dto.ApplicantNumberByJobRes; +import com.econovation.third_project.service.RegistrationService; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -13,10 +16,11 @@ @RequiredArgsConstructor public class AdminQueryController { private final Database database; + private final RegistrationService registrationService; // 예시 코드 @PostMapping("/registration") - public ResponseEntity postRegistrate(@RequestBody Registration registration) { + public ResponseEntity postRegistration(@RequestBody Registration registration) { database.register(registration); return ResponseEntity.ok().build(); } @@ -25,4 +29,18 @@ public ResponseEntity getRegistration(String userId) { return ResponseEntity.ok().body(database.getRegistration(userId)); } + //아래 두 개 묶기 + @GetMapping("/registration/numbers/job") //uri 다시.. 확장성: 다른 필터링을 적용할 수 있다고 생각 + public ResponseEntity> getApplicationNumbersByJob(){ + return ResponseEntity.ok().body(registrationService.getApplicantNumbersByJob()); + } + + @GetMapping("/registration/numbers/job-field") + public ResponseEntity> getApplicationNumbersByJobFieldAndPriority(){ + return ResponseEntity.ok().body(registrationService.getApplicantNumbersByJobFieldAndPriority(); + } + + + + } diff --git a/src/main/java/com/econovation/third_project/database/Database.java b/src/main/java/com/econovation/third_project/database/Database.java index 33b8710..2bb8245 100644 --- a/src/main/java/com/econovation/third_project/database/Database.java +++ b/src/main/java/com/econovation/third_project/database/Database.java @@ -1,8 +1,11 @@ package com.econovation.third_project.database; +import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.stereotype.Component; /** @@ -11,10 +14,14 @@ */ @Component public class Database { - private final Map registration = new HashMap<>(); - private final Map path = new HashMap<>(); - private final Map personalInformation = new HashMap<>(); - private final Map desiredTime = new HashMap<>(); + //key: user id + private final Map registration = new ConcurrentHashMap<>(); + //key: user id - fk같은? + private final Map path = new ConcurrentHashMap<>(); + //key: user id + private final Map personalInformation = new ConcurrentHashMap<>(); + //key: user id + private final Map desiredTime = new ConcurrentHashMap<>(); public void register(Registration registrationRequest) { @@ -25,4 +32,13 @@ public void register(Registration registrationRequest) { public Registration getRegistration(String userId) { return registration.get(userId); } + + public Collection getRegistrations(){ + return registration.values();//이거 Collection 반환하는거 첨 알았다. + } + + + + + } \ No newline at end of file diff --git a/src/main/java/com/econovation/third_project/database/Job.java b/src/main/java/com/econovation/third_project/database/Job.java new file mode 100644 index 0000000..899ed83 --- /dev/null +++ b/src/main/java/com/econovation/third_project/database/Job.java @@ -0,0 +1,28 @@ +package com.econovation.third_project.database; + +import java.util.List; +import java.util.Optional; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) + +public enum Job { + DEVELOPER(List.of( + JobField.AI, + JobField.GAME, + JobField.APP, + JobField.IOT, + JobField.WEB, + JobField.ARVR + )), + PLANNER(List.of()), + DESIGNER(List.of()); + + private final List jobFields; + + + public List getJobFields() { + return jobFields; + } +} diff --git a/src/main/java/com/econovation/third_project/database/JobField.java b/src/main/java/com/econovation/third_project/database/JobField.java new file mode 100644 index 0000000..5828d53 --- /dev/null +++ b/src/main/java/com/econovation/third_project/database/JobField.java @@ -0,0 +1,13 @@ +package com.econovation.third_project.database; + +public enum JobField { + WEB(), + APP(), + AI(), + GAME(), + IOT(), + ARVR(); + + + +} diff --git a/src/main/java/com/econovation/third_project/database/Registration.java b/src/main/java/com/econovation/third_project/database/Registration.java index be42739..85f7e58 100644 --- a/src/main/java/com/econovation/third_project/database/Registration.java +++ b/src/main/java/com/econovation/third_project/database/Registration.java @@ -1,21 +1,31 @@ package com.econovation.third_project.database; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; @Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) public class Registration { - // 희망분야 - private String hopeField; + @NonNull + private Job hopeJob; + @NonNull + private Optional firstPriority; + @NonNull + private Optional secondPriority; - // 1지망 - private String firstPriority; + public static Registration of(String hopeJob, String firstPriority, String secondPriority){ + Job job = Job.valueOf(hopeJob.toUpperCase()); //없으면 Illegal - // 2지망 - private String secondPriority; + Optional firstJobField = job.getJobFields().stream().filter(jf -> jf.name().equals(firstPriority)).findAny(); + Optional secondJobField = job.getJobFields().stream().filter(jf -> jf.name().equals(secondPriority)).findAny(); - public Registration(String hopeField, String firstPriority, String secondPriority) { - this.hopeField = hopeField; - this.firstPriority = firstPriority; - this.secondPriority = secondPriority; + return new Registration(job, firstJobField, secondJobField); } + } diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java new file mode 100644 index 0000000..51b1796 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java @@ -0,0 +1,7 @@ +package com.econovation.third_project.dto; + +import com.econovation.third_project.database.Job; + +public record ApplicantNumberByJobRes(Job job, int number) { + +} diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java new file mode 100644 index 0000000..5ac9999 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java @@ -0,0 +1,9 @@ +package com.econovation.third_project.dto; + +import com.econovation.third_project.database.JobField; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = false) +public record ApplicantNumbersByJobFieldAndPriorityRes(int priority, JobField jobField, int number) { + +} diff --git a/src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java b/src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java new file mode 100644 index 0000000..ade8520 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java @@ -0,0 +1,7 @@ +package com.econovation.third_project.dto; + +import com.econovation.third_project.database.JobField; + +public record JobFieldByPriority(int priority, JobField jobField) { + +} diff --git a/src/main/java/com/econovation/third_project/dto/PostRegistrationRes.java b/src/main/java/com/econovation/third_project/dto/PostRegistrationRes.java new file mode 100644 index 0000000..e247f17 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/PostRegistrationRes.java @@ -0,0 +1,5 @@ +package com.econovation.third_project.dto; + +public record PostRegistrationRes(String registrationId) { + +} diff --git a/src/main/java/com/econovation/third_project/service/RegistrationService.java b/src/main/java/com/econovation/third_project/service/RegistrationService.java new file mode 100644 index 0000000..75d2e26 --- /dev/null +++ b/src/main/java/com/econovation/third_project/service/RegistrationService.java @@ -0,0 +1,61 @@ +package com.econovation.third_project.service; + + +import com.econovation.third_project.database.Database; +import com.econovation.third_project.database.Job; +import com.econovation.third_project.database.JobField; +import com.econovation.third_project.database.Registration; +import com.econovation.third_project.dto.ApplicantNumberByJobRes; +import com.econovation.third_project.dto.ApplicantNumbersByJobFieldAndPriorityRes; +import com.econovation.third_project.dto.JobFieldByPriority; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import javax.persistence.criteria.CriteriaBuilder.In; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class RegistrationService { + private final Database db; + + //분야별 지원자 수 read + public List getApplicantNumbersByJob(){ + //특정 기수만 필터링했다고 가정 + Map map = db.getRegistrations().stream() + .collect(Collectors.groupingBy(Registration::getHopeJob, Collectors.counting())); + //TODO: 내림차순 정렬 + List applicantNumbers = new ArrayList<>(); + map.forEach((job, number)-> applicantNumbers.add(new ApplicantNumberByJobRes(job, number.intValue()))); + return applicantNumbers; + } + + //지원 조회 + public Registration getRegistration(String registrationId){ + return db.getRegistration(registrationId); + } + + public List getApplicantNumbersByJobFieldAndPriority(){ //메서드를 유연하게 만들 필요가 있어보임... + // dto(몇 순위, 분야) + // 없는건 안만들어야 함 + + //특정 기수만 필터링했다고 가정 + Collection registrations = db.getRegistrations(); + //두 가지 조건을 조합해서 그룹핑해야 하는데.. + + } + + //지원 등록 +// public PostRegistrationRes postRegistration() + + //지원 수정 + + //지원 삭제 + +} From d2d17935acb10bf231c945488b3281bacbc3ab91 Mon Sep 17 00:00:00 2001 From: coco3x Date: Sat, 18 May 2024 23:27:26 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=EC=A7=80=EC=9B=90=20=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=ED=8E=98=EC=9D=B4=EC=A7=80=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../third_project/config/Field.java | 19 ++++++ .../econovation/third_project/config/Job.java | 14 ++++ .../third_project/config/SupportPath.java | 16 +++++ .../controller/AdminQueryController.java | 31 +++++---- .../third_project/database/Database.java | 26 +++++--- .../third_project/database/DesiredTime.java | 28 +++++++- .../database/DesiredTimeNow.java | 24 +++++++ .../third_project/database/Job.java | 28 -------- .../third_project/database/JobField.java | 13 ---- .../third_project/database/Path.java | 5 +- .../database/PersonalInformation.java | 11 +++- .../third_project/database/Registration.java | 32 +++++---- .../dto/ApplicantNumberByJobRes.java | 7 -- .../dto/ApplicantNumberInField.java | 8 +++ .../dto/ApplicantNumberInJob.java | 5 ++ .../dto/ApplicantNumberInMajor.java | 5 ++ .../dto/ApplicantNumberInPath.java | 5 ++ .../dto/ApplicantNumberInTime.java | 7 ++ ...licantNumbersByJobFieldAndPriorityRes.java | 9 --- .../third_project/dto/JobFieldByPriority.java | 7 -- .../service/DesiredTimeService.java | 27 ++++++++ .../third_project/service/PathService.java | 24 +++++++ .../service/PersonalInformationService.java | 31 +++++++++ .../service/RegistrationService.java | 65 +++++++++++-------- 24 files changed, 317 insertions(+), 130 deletions(-) create mode 100644 src/main/java/com/econovation/third_project/config/Field.java create mode 100644 src/main/java/com/econovation/third_project/config/Job.java create mode 100644 src/main/java/com/econovation/third_project/config/SupportPath.java create mode 100644 src/main/java/com/econovation/third_project/database/DesiredTimeNow.java delete mode 100644 src/main/java/com/econovation/third_project/database/Job.java delete mode 100644 src/main/java/com/econovation/third_project/database/JobField.java delete mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java create mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java create mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumberInJob.java create mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumberInMajor.java create mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumberInPath.java create mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumberInTime.java delete mode 100644 src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java delete mode 100644 src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java create mode 100644 src/main/java/com/econovation/third_project/service/DesiredTimeService.java create mode 100644 src/main/java/com/econovation/third_project/service/PathService.java create mode 100644 src/main/java/com/econovation/third_project/service/PersonalInformationService.java diff --git a/src/main/java/com/econovation/third_project/config/Field.java b/src/main/java/com/econovation/third_project/config/Field.java new file mode 100644 index 0000000..dd903dd --- /dev/null +++ b/src/main/java/com/econovation/third_project/config/Field.java @@ -0,0 +1,19 @@ +package com.econovation.third_project.config; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum Field { + WEB("WEB"), + APP("APP"), + AI("AI"), + GAME("GAME"), + IOT("IoT"), + ARVR("AR/VR"); + + private final String fieldName; + + +} diff --git a/src/main/java/com/econovation/third_project/config/Job.java b/src/main/java/com/econovation/third_project/config/Job.java new file mode 100644 index 0000000..0c431da --- /dev/null +++ b/src/main/java/com/econovation/third_project/config/Job.java @@ -0,0 +1,14 @@ +package com.econovation.third_project.config; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum Job { + DEVELOPER("개발자"), + PLANNER("기획자"), + DESIGNER("디자이너"); + + private final String jobName; +} diff --git a/src/main/java/com/econovation/third_project/config/SupportPath.java b/src/main/java/com/econovation/third_project/config/SupportPath.java new file mode 100644 index 0000000..be783e4 --- /dev/null +++ b/src/main/java/com/econovation/third_project/config/SupportPath.java @@ -0,0 +1,16 @@ +package com.econovation.third_project.config; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum SupportPath { + POSTER("홍보 포스터"), + DEPARTMENT_ANNOUNCEMENT("학과 공지사항"), + ACQUAINTANCE("지인 소개"), + INSTAGRAM("인스타그램"), + EVERYTIME("에브리타임"); + private final String entryPathName; + +} diff --git a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java index 46ffaa6..da0614e 100644 --- a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java +++ b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java @@ -2,21 +2,29 @@ import com.econovation.third_project.database.Database; import com.econovation.third_project.database.Registration; -import com.econovation.third_project.dto.ApplicantNumberByJobRes; +import com.econovation.third_project.service.DesiredTimeService; +import com.econovation.third_project.service.PathService; +import com.econovation.third_project.service.PersonalInformationService; import com.econovation.third_project.service.RegistrationService; import java.util.List; +import java.util.Map; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequiredArgsConstructor +@RequestMapping("/api/admin") public class AdminQueryController { private final Database database; private final RegistrationService registrationService; + private final PathService pathService; + private final PersonalInformationService personalInformationService; + private final DesiredTimeService desiredTimeService; // 예시 코드 @PostMapping("/registration") @@ -29,18 +37,19 @@ public ResponseEntity getRegistration(String userId) { return ResponseEntity.ok().body(database.getRegistration(userId)); } - //아래 두 개 묶기 - @GetMapping("/registration/numbers/job") //uri 다시.. 확장성: 다른 필터링을 적용할 수 있다고 생각 - public ResponseEntity> getApplicationNumbersByJob(){ - return ResponseEntity.ok().body(registrationService.getApplicantNumbersByJob()); + //쿼리 파라미터 + @GetMapping("/applicants") + public ResponseEntity>> getApplicantsInfo(){ + + return ResponseEntity.ok().body(Map.of( + "job", registrationService.getApplicantNumbersEachJob(), + "field", registrationService.getApplicantNumberEachField(), + "major", personalInformationService.getApplicantNumberEachMajor(), + "path", pathService.getApplicantNumberEachPath(), + "time", desiredTimeService.getApplicantNumberEachTime() + )); } - @GetMapping("/registration/numbers/job-field") - public ResponseEntity> getApplicationNumbersByJobFieldAndPriority(){ - return ResponseEntity.ok().body(registrationService.getApplicantNumbersByJobFieldAndPriority(); - } - - } diff --git a/src/main/java/com/econovation/third_project/database/Database.java b/src/main/java/com/econovation/third_project/database/Database.java index 2bb8245..719c2a0 100644 --- a/src/main/java/com/econovation/third_project/database/Database.java +++ b/src/main/java/com/econovation/third_project/database/Database.java @@ -1,8 +1,6 @@ package com.econovation.third_project.database; import java.util.Collection; -import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -16,13 +14,27 @@ public class Database { //key: user id private final Map registration = new ConcurrentHashMap<>(); - //key: user id - fk같은? + //key: path id private final Map path = new ConcurrentHashMap<>(); - //key: user id + //key: pi id private final Map personalInformation = new ConcurrentHashMap<>(); - //key: user id + //key: dt id private final Map desiredTime = new ConcurrentHashMap<>(); + public Collection getAllRegistrations(){ + return registration.values(); + } + public Collection getAllPersonalInformation(){ + return personalInformation.values(); + } + public Collection getAllPath() { + return path.values(); + } + public Collection getAllDesiredTime(){ + return desiredTime.values(); + } + + public void register(Registration registrationRequest) { // 기본적으로 이전 제출시 등록된 정보가 있으면 덮어쓰기를 지원합니다. @@ -33,10 +45,6 @@ public Registration getRegistration(String userId) { return registration.get(userId); } - public Collection getRegistrations(){ - return registration.values();//이거 Collection 반환하는거 첨 알았다. - } - diff --git a/src/main/java/com/econovation/third_project/database/DesiredTime.java b/src/main/java/com/econovation/third_project/database/DesiredTime.java index 2d7a140..64b90ca 100644 --- a/src/main/java/com/econovation/third_project/database/DesiredTime.java +++ b/src/main/java/com/econovation/third_project/database/DesiredTime.java @@ -1,13 +1,35 @@ package com.econovation.third_project.database; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; +import javax.persistence.criteria.CriteriaBuilder.In; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; -@AllArgsConstructor @Getter -public class DesiredTime { +public abstract class DesiredTime { + private static final Map, List> cachedTimes = new HashMap<>(); + String registrationId; // 희망 시간 (11 * 3)의 테이블 형태를 준수합니다. - private List desiredTime; + final List> desiredTimes; + + abstract void validateDesiredTime(List> desiredTimes); + + DesiredTime(String registrationId, List> desiredTimes) { + validateDesiredTime(desiredTimes); + this.registrationId = registrationId; + this.desiredTimes = desiredTimes.stream() + .map(time-> cachedTimes.putIfAbsent(time, time)) + .toList(); + } } diff --git a/src/main/java/com/econovation/third_project/database/DesiredTimeNow.java b/src/main/java/com/econovation/third_project/database/DesiredTimeNow.java new file mode 100644 index 0000000..91967ec --- /dev/null +++ b/src/main/java/com/econovation/third_project/database/DesiredTimeNow.java @@ -0,0 +1,24 @@ +package com.econovation.third_project.database; + +import java.util.List; + +public final class DesiredTimeNow extends DesiredTime{ + public DesiredTimeNow(String registrationId, List> desiredTimes){ + super(registrationId, desiredTimes); + } + + @Override + void validateDesiredTime(List> desiredTimes) { + //27기 기준 + int interviewDays = 3; + int hoursPerDay = 11; + + desiredTimes.forEach( + time -> { + if (time.get(0) >= interviewDays || time.get(1) >= hoursPerDay) + throw new IllegalArgumentException("면접 시간 잘못 입력"); + } + ); + + } +} diff --git a/src/main/java/com/econovation/third_project/database/Job.java b/src/main/java/com/econovation/third_project/database/Job.java deleted file mode 100644 index 899ed83..0000000 --- a/src/main/java/com/econovation/third_project/database/Job.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.econovation.third_project.database; - -import java.util.List; -import java.util.Optional; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) - -public enum Job { - DEVELOPER(List.of( - JobField.AI, - JobField.GAME, - JobField.APP, - JobField.IOT, - JobField.WEB, - JobField.ARVR - )), - PLANNER(List.of()), - DESIGNER(List.of()); - - private final List jobFields; - - - public List getJobFields() { - return jobFields; - } -} diff --git a/src/main/java/com/econovation/third_project/database/JobField.java b/src/main/java/com/econovation/third_project/database/JobField.java deleted file mode 100644 index 5828d53..0000000 --- a/src/main/java/com/econovation/third_project/database/JobField.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.econovation.third_project.database; - -public enum JobField { - WEB(), - APP(), - AI(), - GAME(), - IOT(), - ARVR(); - - - -} diff --git a/src/main/java/com/econovation/third_project/database/Path.java b/src/main/java/com/econovation/third_project/database/Path.java index 727433c..1c33f2d 100644 --- a/src/main/java/com/econovation/third_project/database/Path.java +++ b/src/main/java/com/econovation/third_project/database/Path.java @@ -1,12 +1,13 @@ package com.econovation.third_project.database; +import com.econovation.third_project.config.SupportPath; import lombok.AllArgsConstructor; import lombok.Getter; @AllArgsConstructor @Getter -public class Path { +public class Path{ String registrationId; // 지원 경로 - private String supportPath; + private SupportPath supportPath; } diff --git a/src/main/java/com/econovation/third_project/database/PersonalInformation.java b/src/main/java/com/econovation/third_project/database/PersonalInformation.java index 8a17b8a..b82490f 100644 --- a/src/main/java/com/econovation/third_project/database/PersonalInformation.java +++ b/src/main/java/com/econovation/third_project/database/PersonalInformation.java @@ -1,5 +1,6 @@ package com.econovation.third_project.database; +import java.util.Optional; import lombok.AllArgsConstructor; import lombok.Getter; @@ -31,8 +32,14 @@ public class PersonalInformation { // 부전공 private String minor; - - // 이메일 private String email; + + public Optional getDoubleMajor(){ + return Optional.ofNullable(this.doubleMajor); + } + public Optional getMinor(){ + return Optional.ofNullable(this.minor); + } + } diff --git a/src/main/java/com/econovation/third_project/database/Registration.java b/src/main/java/com/econovation/third_project/database/Registration.java index 85f7e58..99a1277 100644 --- a/src/main/java/com/econovation/third_project/database/Registration.java +++ b/src/main/java/com/econovation/third_project/database/Registration.java @@ -1,31 +1,37 @@ package com.econovation.third_project.database; -import java.util.List; +import com.econovation.third_project.config.Field; +import com.econovation.third_project.config.Job; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; -import lombok.RequiredArgsConstructor; @Getter -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) public class Registration { @NonNull private Job hopeJob; @NonNull - private Optional firstPriority; - @NonNull - private Optional secondPriority; + private Field firstPriority; + private Field secondPriority; + + public static Registration of(@NonNull String hopeJob, @NonNull String firstJobFieldName, String secondJobFieldName){ + Job job = Job.valueOf(hopeJob.toUpperCase()); - public static Registration of(String hopeJob, String firstPriority, String secondPriority){ - Job job = Job.valueOf(hopeJob.toUpperCase()); //없으면 Illegal + Field firstPriority = Field.valueOf(firstJobFieldName.toUpperCase()); + Field secondPriority = secondJobFieldName != null ? + Field.valueOf(secondJobFieldName.toUpperCase()) : null; - Optional firstJobField = job.getJobFields().stream().filter(jf -> jf.name().equals(firstPriority)).findAny(); - Optional secondJobField = job.getJobFields().stream().filter(jf -> jf.name().equals(secondPriority)).findAny(); + return new Registration(job, firstPriority, secondPriority); + } - return new Registration(job, firstJobField, secondJobField); + public Field getFirstPriority(){ + return this.firstPriority; + } + public Optional getSecondPriority(){ + return Optional.ofNullable(this.secondPriority); } } diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java deleted file mode 100644 index 51b1796..0000000 --- a/src/main/java/com/econovation/third_project/dto/ApplicantNumberByJobRes.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.econovation.third_project.dto; - -import com.econovation.third_project.database.Job; - -public record ApplicantNumberByJobRes(Job job, int number) { - -} diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java new file mode 100644 index 0000000..18be9bc --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java @@ -0,0 +1,8 @@ +package com.econovation.third_project.dto; + +public record ApplicantNumberInField(String fieldName, int firstNumber, int secondNumber) implements Comparable{ + @Override + public int compareTo(ApplicantNumberInField o) { + return (this.firstNumber+this.secondNumber) - (o.firstNumber + o.secondNumber); + } +} diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberInJob.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInJob.java new file mode 100644 index 0000000..08440d9 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInJob.java @@ -0,0 +1,5 @@ +package com.econovation.third_project.dto; + +public record ApplicantNumberInJob(String jobName, int number) { + +} diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberInMajor.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInMajor.java new file mode 100644 index 0000000..454b647 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInMajor.java @@ -0,0 +1,5 @@ +package com.econovation.third_project.dto; + +public record ApplicantNumberInMajor(String majorName, int number){ + +} diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberInPath.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInPath.java new file mode 100644 index 0000000..14ca7f7 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInPath.java @@ -0,0 +1,5 @@ +package com.econovation.third_project.dto; + +public record ApplicantNumberInPath(String entryPathName, int number){ + +} diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberInTime.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInTime.java new file mode 100644 index 0000000..6946684 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInTime.java @@ -0,0 +1,7 @@ +package com.econovation.third_project.dto; + +import java.util.List; + +public record ApplicantNumberInTime(List time, int number) { + +} diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java deleted file mode 100644 index 5ac9999..0000000 --- a/src/main/java/com/econovation/third_project/dto/ApplicantNumbersByJobFieldAndPriorityRes.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.econovation.third_project.dto; - -import com.econovation.third_project.database.JobField; -import lombok.EqualsAndHashCode; - -@EqualsAndHashCode(callSuper = false) -public record ApplicantNumbersByJobFieldAndPriorityRes(int priority, JobField jobField, int number) { - -} diff --git a/src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java b/src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java deleted file mode 100644 index ade8520..0000000 --- a/src/main/java/com/econovation/third_project/dto/JobFieldByPriority.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.econovation.third_project.dto; - -import com.econovation.third_project.database.JobField; - -public record JobFieldByPriority(int priority, JobField jobField) { - -} diff --git a/src/main/java/com/econovation/third_project/service/DesiredTimeService.java b/src/main/java/com/econovation/third_project/service/DesiredTimeService.java new file mode 100644 index 0000000..1fef3a8 --- /dev/null +++ b/src/main/java/com/econovation/third_project/service/DesiredTimeService.java @@ -0,0 +1,27 @@ +package com.econovation.third_project.service; + +import com.econovation.third_project.database.Database; +import com.econovation.third_project.dto.ApplicantNumberInJob; +import com.econovation.third_project.dto.ApplicantNumberInTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class DesiredTimeService { + private final Database db; + + //입력할 때 2개인지 확인해야 함 + + public List getApplicantNumberEachTime(){ + return db.getAllDesiredTime().stream() + .flatMap(desiredTime -> desiredTime.getDesiredTimes().stream()) + .collect(Collectors.groupingBy(time -> time, Collectors.counting())) + .entrySet().stream() + .map(entry->new ApplicantNumberInTime(entry.getKey(), entry.getValue().intValue())) + .toList(); + } + +} diff --git a/src/main/java/com/econovation/third_project/service/PathService.java b/src/main/java/com/econovation/third_project/service/PathService.java new file mode 100644 index 0000000..cdcffe3 --- /dev/null +++ b/src/main/java/com/econovation/third_project/service/PathService.java @@ -0,0 +1,24 @@ +package com.econovation.third_project.service; + +import com.econovation.third_project.database.Database; +import com.econovation.third_project.database.Path; +import com.econovation.third_project.dto.ApplicantNumberInPath; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PathService { + private final Database db; + + public List getApplicantNumberEachPath(){ + return db.getAllPath().stream() + .collect(Collectors.groupingBy(Path::getSupportPath, Collectors.counting())) + .entrySet().stream() + .map(entry->new ApplicantNumberInPath(entry.getKey().getEntryPathName(), entry.getValue().intValue())) + .toList(); + } + +} diff --git a/src/main/java/com/econovation/third_project/service/PersonalInformationService.java b/src/main/java/com/econovation/third_project/service/PersonalInformationService.java new file mode 100644 index 0000000..4b1aa74 --- /dev/null +++ b/src/main/java/com/econovation/third_project/service/PersonalInformationService.java @@ -0,0 +1,31 @@ +package com.econovation.third_project.service; + +import com.econovation.third_project.database.Database; +import com.econovation.third_project.dto.ApplicantNumberInMajor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PersonalInformationService { + private final Database db; + + //학과별 지원자 수 + public List getApplicantNumberEachMajor(){ + Map majorCounts = new HashMap<>(); + + db.getAllPersonalInformation().forEach(info -> { + //주전공 + majorCounts.merge(info.getMajor(), 1, Integer::sum); + //복수전공 + info.getDoubleMajor().ifPresent(doubleMajor -> majorCounts.merge(doubleMajor, 1, Integer::sum)); + }); + + return majorCounts.entrySet().stream() + .map(entry -> new ApplicantNumberInMajor(entry.getKey(), entry.getValue())) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/econovation/third_project/service/RegistrationService.java b/src/main/java/com/econovation/third_project/service/RegistrationService.java index 75d2e26..140bb8e 100644 --- a/src/main/java/com/econovation/third_project/service/RegistrationService.java +++ b/src/main/java/com/econovation/third_project/service/RegistrationService.java @@ -2,38 +2,36 @@ import com.econovation.third_project.database.Database; -import com.econovation.third_project.database.Job; -import com.econovation.third_project.database.JobField; +import com.econovation.third_project.config.Field; +import com.econovation.third_project.config.Job; import com.econovation.third_project.database.Registration; -import com.econovation.third_project.dto.ApplicantNumberByJobRes; -import com.econovation.third_project.dto.ApplicantNumbersByJobFieldAndPriorityRes; -import com.econovation.third_project.dto.JobFieldByPriority; -import java.util.ArrayList; -import java.util.Collection; +import com.econovation.third_project.dto.ApplicantNumberInJob; +import com.econovation.third_project.dto.ApplicantNumberInField; +import static java.util.Comparator.reverseOrder; + +import java.util.EnumMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; -import javax.persistence.criteria.CriteriaBuilder.In; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; + + + @Service @RequiredArgsConstructor public class RegistrationService { private final Database db; - //분야별 지원자 수 read - public List getApplicantNumbersByJob(){ - //특정 기수만 필터링했다고 가정 - Map map = db.getRegistrations().stream() - .collect(Collectors.groupingBy(Registration::getHopeJob, Collectors.counting())); - //TODO: 내림차순 정렬 - List applicantNumbers = new ArrayList<>(); - map.forEach((job, number)-> applicantNumbers.add(new ApplicantNumberByJobRes(job, number.intValue()))); - return applicantNumbers; + //분야별 지원자 수 + public List getApplicantNumbersEachJob(){ + return db.getAllRegistrations().stream() + .collect(Collectors.groupingBy(Registration::getHopeJob, Collectors.counting())) + .entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .map(entry->new ApplicantNumberInJob(entry.getKey().getJobName(), entry.getValue().intValue())) + .toList(); } //지원 조회 @@ -41,14 +39,29 @@ public Registration getRegistration(String registrationId){ return db.getRegistration(registrationId); } - public List getApplicantNumbersByJobFieldAndPriority(){ //메서드를 유연하게 만들 필요가 있어보임... - // dto(몇 순위, 분야) - // 없는건 안만들어야 함 + //세부 분야별 지원자 수 + public List getApplicantNumberEachField(){ + Map jobPriorityCounts = new EnumMap<>(Field.class); + + for (Field field : Field.values()) + jobPriorityCounts.put(field, new int[2]); - //특정 기수만 필터링했다고 가정 - Collection registrations = db.getRegistrations(); - //두 가지 조건을 조합해서 그룹핑해야 하는데.. + db.getAllRegistrations() + .forEach(regi->{ + jobPriorityCounts.get(regi.getFirstPriority())[0]++; + regi.getSecondPriority() + .ifPresent(secondPriority -> jobPriorityCounts.get(secondPriority)[1]++); + }); + return jobPriorityCounts.entrySet() + .stream() + .map(entry-> + new ApplicantNumberInField( + entry.getKey().getFieldName(), + entry.getValue()[0], + entry.getValue()[1])) + .sorted(reverseOrder()) + .toList(); } //지원 등록 From d051aa654ef428d414aa48f4d01dfecc10a57bbb Mon Sep 17 00:00:00 2001 From: coco3x Date: Mon, 20 May 2024 01:23:38 +0900 Subject: [PATCH 3/9] fix --- .../controller/AdminQueryController.java | 15 +---- .../controller/ApplicationController.java | 20 ++++++ .../third_project/database/Application.java | 36 +++++++++++ .../third_project/database/Database.java | 62 +++++++++++++------ .../third_project/database/DesiredTime.java | 16 +---- ...DesiredTimeNow.java => DesiredTime27.java} | 6 +- .../third_project/database/Path.java | 20 +++++- .../database/PersonalInformation.java | 9 +-- .../third_project/database/Registration.java | 4 -- .../third_project/database/User.java | 12 ++++ .../dto/CreateApplicationReq.java | 17 +++++ .../third_project/dto/DesiredTimeReq.java | 11 ++++ .../third_project/dto/PathReq.java | 10 +++ .../dto/PersonalInformationReq.java | 28 +++++++++ .../third_project/dto/RegistrationReq.java | 12 ++++ .../service/ApplicationService.java | 23 +++++++ .../third_project/service/PathService.java | 5 +- .../service/RegistrationService.java | 13 ++-- 18 files changed, 252 insertions(+), 67 deletions(-) create mode 100644 src/main/java/com/econovation/third_project/controller/ApplicationController.java create mode 100644 src/main/java/com/econovation/third_project/database/Application.java rename src/main/java/com/econovation/third_project/database/{DesiredTimeNow.java => DesiredTime27.java} (73%) create mode 100644 src/main/java/com/econovation/third_project/database/User.java create mode 100644 src/main/java/com/econovation/third_project/dto/CreateApplicationReq.java create mode 100644 src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java create mode 100644 src/main/java/com/econovation/third_project/dto/PathReq.java create mode 100644 src/main/java/com/econovation/third_project/dto/PersonalInformationReq.java create mode 100644 src/main/java/com/econovation/third_project/dto/RegistrationReq.java create mode 100644 src/main/java/com/econovation/third_project/service/ApplicationService.java diff --git a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java index da0614e..3e6768b 100644 --- a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java +++ b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java @@ -2,6 +2,8 @@ import com.econovation.third_project.database.Database; import com.econovation.third_project.database.Registration; +import com.econovation.third_project.dto.CreateApplicationReq; +import com.econovation.third_project.service.ApplicationService; import com.econovation.third_project.service.DesiredTimeService; import com.econovation.third_project.service.PathService; import com.econovation.third_project.service.PersonalInformationService; @@ -20,22 +22,11 @@ @RequiredArgsConstructor @RequestMapping("/api/admin") public class AdminQueryController { - private final Database database; private final RegistrationService registrationService; private final PathService pathService; private final PersonalInformationService personalInformationService; private final DesiredTimeService desiredTimeService; - // 예시 코드 - @PostMapping("/registration") - public ResponseEntity postRegistration(@RequestBody Registration registration) { - database.register(registration); - return ResponseEntity.ok().build(); - } - @GetMapping("/registration") - public ResponseEntity getRegistration(String userId) { - return ResponseEntity.ok().body(database.getRegistration(userId)); - } //쿼리 파라미터 @GetMapping("/applicants") @@ -46,7 +37,7 @@ public ResponseEntity>> getApplicantsInfo(){ "field", registrationService.getApplicantNumberEachField(), "major", personalInformationService.getApplicantNumberEachMajor(), "path", pathService.getApplicantNumberEachPath(), - "time", desiredTimeService.getApplicantNumberEachTime() + "desired_time", desiredTimeService.getApplicantNumberEachTime() )); } diff --git a/src/main/java/com/econovation/third_project/controller/ApplicationController.java b/src/main/java/com/econovation/third_project/controller/ApplicationController.java new file mode 100644 index 0000000..2dc3c37 --- /dev/null +++ b/src/main/java/com/econovation/third_project/controller/ApplicationController.java @@ -0,0 +1,20 @@ +package com.econovation.third_project.controller; + +import com.econovation.third_project.dto.CreateApplicationReq; +import com.econovation.third_project.service.ApplicationService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/api") +@RequiredArgsConstructor +public class ApplicationController { + private final ApplicationService applicationService; + + @PostMapping("/application") + public ResponseEntity createApplication(@RequestBody CreateApplicationReq createApplicationReq){ + return ResponseEntity.ok().body(applicationService.createApplication(createApplicationReq)); + } +} diff --git a/src/main/java/com/econovation/third_project/database/Application.java b/src/main/java/com/econovation/third_project/database/Application.java new file mode 100644 index 0000000..2654ba9 --- /dev/null +++ b/src/main/java/com/econovation/third_project/database/Application.java @@ -0,0 +1,36 @@ +package com.econovation.third_project.database; + +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; + + +@Getter +public final class Application { + private static final AtomicInteger lastUsedId = new AtomicInteger(0); + @NonNull + private final Integer applicationId = lastUsedId.getAndIncrement(); + @NonNull + private final Registration registration; + @NonNull + private final PersonalInformation personalInformation; + @NonNull + private final Path path; + @NonNull + private final DesiredTime desiredTime; + + @Builder + public Application(Registration registration, PersonalInformation personalInformation, + Path path, + DesiredTime desiredTime) { + this.registration = registration; + this.personalInformation = personalInformation; + this.path = path; + this.desiredTime = desiredTime; + } +} + + + + diff --git a/src/main/java/com/econovation/third_project/database/Database.java b/src/main/java/com/econovation/third_project/database/Database.java index 719c2a0..f7eee3c 100644 --- a/src/main/java/com/econovation/third_project/database/Database.java +++ b/src/main/java/com/econovation/third_project/database/Database.java @@ -2,7 +2,7 @@ import java.util.Collection; import java.util.Map; -import java.util.UUID; +import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import org.springframework.stereotype.Component; @@ -12,38 +12,62 @@ */ @Component public class Database { - //key: user id - private final Map registration = new ConcurrentHashMap<>(); - //key: path id - private final Map path = new ConcurrentHashMap<>(); - //key: pi id - private final Map personalInformation = new ConcurrentHashMap<>(); - //key: dt id - private final Map desiredTime = new ConcurrentHashMap<>(); + //key: user id, value: application id + private final Map applications = new ConcurrentHashMap<>(); + //key: application id + private final Map registrations = new ConcurrentHashMap<>(); + //key: application id + private final Map paths = new ConcurrentHashMap<>(); + //key: application id + private final Map personalInformation = new ConcurrentHashMap<>(); + //key: application id + private final Map desiredTimes = new ConcurrentHashMap<>(); public Collection getAllRegistrations(){ - return registration.values(); + return registrations.values(); } public Collection getAllPersonalInformation(){ return personalInformation.values(); } public Collection getAllPath() { - return path.values(); + return paths.values(); } public Collection getAllDesiredTime(){ - return desiredTime.values(); + return desiredTimes.values(); } + //지원자는 userId가 없으니 같은 지원서인지 판단할 기준을 따로 만들어야 함 + public Integer upsertApplication(Integer userId, Application application){ + Integer applicationId = applications.computeIfAbsent(userId, k -> application.getApplicationId()); + upsertRegistration(applicationId, application.getRegistration()); + upsertPath(applicationId, application.getPath()); + upsertDesiredTime(applicationId, application.getDesiredTime()); + upsertPersonalInformation(applicationId, application.getPersonalInformation()); + return applicationId; + } + public void upsertRegistration(Integer applicationId, Registration registration){ + registrations.put(applicationId, registration); + } + public void upsertPath(Integer applicationId, Path path){ + paths.put(applicationId, path); + } + public void upsertPersonalInformation(Integer applicationId, PersonalInformation personalInformation){ + this.personalInformation.put(applicationId, personalInformation); + } + public void upsertDesiredTime(Integer applicationId, DesiredTime desiredTime){ + desiredTimes.put(applicationId, desiredTime); + } - public void register(Registration registrationRequest) { - // 기본적으로 이전 제출시 등록된 정보가 있으면 덮어쓰기를 지원합니다. - registration.put(UUID.randomUUID().toString(), registrationRequest); - } - public Registration getRegistration(String userId) { - return registration.get(userId); - } +// public void register(Registration registrationRequest) { +// // 기본적으로 이전 제출시 등록된 정보가 있으면 덮어쓰기를 지원합니다. +// registration.put(UUID.randomUUID().toString(), registrationRequest); +// } +// +// public Registration getRegistration(String userId) { +// return registration.get(userId); +// } diff --git a/src/main/java/com/econovation/third_project/database/DesiredTime.java b/src/main/java/com/econovation/third_project/database/DesiredTime.java index 64b90ca..2d30b55 100644 --- a/src/main/java/com/econovation/third_project/database/DesiredTime.java +++ b/src/main/java/com/econovation/third_project/database/DesiredTime.java @@ -1,35 +1,23 @@ package com.econovation.third_project.database; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.stream.Collectors; -import javax.persistence.criteria.CriteriaBuilder.In; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.NoArgsConstructor; @Getter public abstract class DesiredTime { private static final Map, List> cachedTimes = new HashMap<>(); - String registrationId; // 희망 시간 (11 * 3)의 테이블 형태를 준수합니다. final List> desiredTimes; abstract void validateDesiredTime(List> desiredTimes); - DesiredTime(String registrationId, List> desiredTimes) { + DesiredTime(List> desiredTimes) { validateDesiredTime(desiredTimes); - this.registrationId = registrationId; this.desiredTimes = desiredTimes.stream() - .map(time-> cachedTimes.putIfAbsent(time, time)) + .map(time-> cachedTimes.computeIfAbsent(time, t->t)) .toList(); } } diff --git a/src/main/java/com/econovation/third_project/database/DesiredTimeNow.java b/src/main/java/com/econovation/third_project/database/DesiredTime27.java similarity index 73% rename from src/main/java/com/econovation/third_project/database/DesiredTimeNow.java rename to src/main/java/com/econovation/third_project/database/DesiredTime27.java index 91967ec..69d73d9 100644 --- a/src/main/java/com/econovation/third_project/database/DesiredTimeNow.java +++ b/src/main/java/com/econovation/third_project/database/DesiredTime27.java @@ -2,9 +2,9 @@ import java.util.List; -public final class DesiredTimeNow extends DesiredTime{ - public DesiredTimeNow(String registrationId, List> desiredTimes){ - super(registrationId, desiredTimes); +public final class DesiredTime27 extends DesiredTime{ + public DesiredTime27(List> desiredTimes){ + super(desiredTimes); } @Override diff --git a/src/main/java/com/econovation/third_project/database/Path.java b/src/main/java/com/econovation/third_project/database/Path.java index 1c33f2d..b7ddc9a 100644 --- a/src/main/java/com/econovation/third_project/database/Path.java +++ b/src/main/java/com/econovation/third_project/database/Path.java @@ -1,13 +1,27 @@ package com.econovation.third_project.database; import com.econovation.third_project.config.SupportPath; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collector; import lombok.AllArgsConstructor; import lombok.Getter; -@AllArgsConstructor @Getter public class Path{ - String registrationId; // 지원 경로 - private SupportPath supportPath; + private final EnumSet supportPaths; + + public Path(EnumSet supportPaths) { + this.supportPaths = supportPaths; + } + + public static Path from(Set stringPaths){ + EnumSet enumPaths = EnumSet.noneOf(SupportPath.class); + stringPaths.stream() + .forEach(stringPath-> enumPaths.add(SupportPath.valueOf(stringPath.toUpperCase()))); + return new Path(enumPaths); + } } diff --git a/src/main/java/com/econovation/third_project/database/PersonalInformation.java b/src/main/java/com/econovation/third_project/database/PersonalInformation.java index b82490f..40f8c7a 100644 --- a/src/main/java/com/econovation/third_project/database/PersonalInformation.java +++ b/src/main/java/com/econovation/third_project/database/PersonalInformation.java @@ -2,12 +2,12 @@ import java.util.Optional; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; -@AllArgsConstructor @Getter +@Builder public class PersonalInformation { - private String registrationId; // 이름 private String name; @@ -35,10 +35,11 @@ public class PersonalInformation { // 이메일 private String email; - public Optional getDoubleMajor(){ + public Optional getDoubleMajor() { return Optional.ofNullable(this.doubleMajor); } - public Optional getMinor(){ + + public Optional getMinor() { return Optional.ofNullable(this.minor); } diff --git a/src/main/java/com/econovation/third_project/database/Registration.java b/src/main/java/com/econovation/third_project/database/Registration.java index 99a1277..b85818f 100644 --- a/src/main/java/com/econovation/third_project/database/Registration.java +++ b/src/main/java/com/econovation/third_project/database/Registration.java @@ -26,10 +26,6 @@ public static Registration of(@NonNull String hopeJob, @NonNull String firstJobF return new Registration(job, firstPriority, secondPriority); } - - public Field getFirstPriority(){ - return this.firstPriority; - } public Optional getSecondPriority(){ return Optional.ofNullable(this.secondPriority); } diff --git a/src/main/java/com/econovation/third_project/database/User.java b/src/main/java/com/econovation/third_project/database/User.java new file mode 100644 index 0000000..79f2eec --- /dev/null +++ b/src/main/java/com/econovation/third_project/database/User.java @@ -0,0 +1,12 @@ +package com.econovation.third_project.database; + +import java.util.concurrent.atomic.AtomicInteger; + +public class User { + private static final AtomicInteger lastUsedId = new AtomicInteger(0); + + private static int nextId(){ + return lastUsedId.getAndIncrement(); + } + +} diff --git a/src/main/java/com/econovation/third_project/dto/CreateApplicationReq.java b/src/main/java/com/econovation/third_project/dto/CreateApplicationReq.java new file mode 100644 index 0000000..1962db6 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/CreateApplicationReq.java @@ -0,0 +1,17 @@ +package com.econovation.third_project.dto; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.NonNull; + +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public record CreateApplicationReq( + @NonNull + RegistrationReq registration, + @NonNull + PersonalInformationReq personalInformation, + @NonNull + PathReq path, + @NonNull + DesiredTimeReq desiredTime + ){} diff --git a/src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java b/src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java new file mode 100644 index 0000000..53ecc08 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java @@ -0,0 +1,11 @@ +package com.econovation.third_project.dto; + +import com.econovation.third_project.database.DesiredTime; +import com.econovation.third_project.database.DesiredTime27; +import java.util.List; + +public record DesiredTimeReq(List> desiredTimes){ + public DesiredTime toEntity(){ + return new DesiredTime27(desiredTimes); + } +} diff --git a/src/main/java/com/econovation/third_project/dto/PathReq.java b/src/main/java/com/econovation/third_project/dto/PathReq.java new file mode 100644 index 0000000..b6bf969 --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/PathReq.java @@ -0,0 +1,10 @@ +package com.econovation.third_project.dto; + +import com.econovation.third_project.database.Path; +import java.util.Set; + +public record PathReq(Set paths) { + public Path toEntity(){ + return Path.from(paths); + } +} diff --git a/src/main/java/com/econovation/third_project/dto/PersonalInformationReq.java b/src/main/java/com/econovation/third_project/dto/PersonalInformationReq.java new file mode 100644 index 0000000..e0abbde --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/PersonalInformationReq.java @@ -0,0 +1,28 @@ +package com.econovation.third_project.dto; + +import com.econovation.third_project.database.PersonalInformation; + +public record PersonalInformationReq( + String name, + String phoneNumber, + Integer studentId, + Integer grade, + Integer semester, + String major, + String doubleMajor, + String minor, + String email) { + public PersonalInformation toEntity(){ + return PersonalInformation.builder() + .name(this.name) + .doubleMajor(this.doubleMajor) + .email(this.email) + .grade(this.grade) + .major(this.major) + .minor(this.minor) + .phoneNumber(this.phoneNumber) + .semester(this.semester) + .studentId(this.studentId) + .build(); + } +} diff --git a/src/main/java/com/econovation/third_project/dto/RegistrationReq.java b/src/main/java/com/econovation/third_project/dto/RegistrationReq.java new file mode 100644 index 0000000..b02f82c --- /dev/null +++ b/src/main/java/com/econovation/third_project/dto/RegistrationReq.java @@ -0,0 +1,12 @@ +package com.econovation.third_project.dto; + +import com.econovation.third_project.database.Registration; + +public record RegistrationReq(String job, String firstPriority, String secondPriority) { + public RegistrationReq{ + System.out.println(job); + } + public Registration toEntity(){ + return Registration.of(this.job, this.firstPriority, this.secondPriority); + } +} diff --git a/src/main/java/com/econovation/third_project/service/ApplicationService.java b/src/main/java/com/econovation/third_project/service/ApplicationService.java new file mode 100644 index 0000000..d702f3b --- /dev/null +++ b/src/main/java/com/econovation/third_project/service/ApplicationService.java @@ -0,0 +1,23 @@ +package com.econovation.third_project.service; + +import com.econovation.third_project.database.Application; +import com.econovation.third_project.database.Database; +import com.econovation.third_project.dto.CreateApplicationReq; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ApplicationService { + private final Database db; + public int createApplication(CreateApplicationReq createApplicationReq){ + Application application = Application.builder() + .registration(createApplicationReq.registration().toEntity()) + .personalInformation(createApplicationReq.personalInformation().toEntity()) + .path(createApplicationReq.path().toEntity()) + .desiredTime(createApplicationReq.desiredTime().toEntity()) + .build(); + return db.upsertApplication(1, application); + } + +} diff --git a/src/main/java/com/econovation/third_project/service/PathService.java b/src/main/java/com/econovation/third_project/service/PathService.java index cdcffe3..277372e 100644 --- a/src/main/java/com/econovation/third_project/service/PathService.java +++ b/src/main/java/com/econovation/third_project/service/PathService.java @@ -1,9 +1,9 @@ package com.econovation.third_project.service; import com.econovation.third_project.database.Database; -import com.econovation.third_project.database.Path; import com.econovation.third_project.dto.ApplicantNumberInPath; import java.util.List; +import java.util.function.Function; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,7 +15,8 @@ public class PathService { public List getApplicantNumberEachPath(){ return db.getAllPath().stream() - .collect(Collectors.groupingBy(Path::getSupportPath, Collectors.counting())) + .flatMap(path-> path.getSupportPaths().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .entrySet().stream() .map(entry->new ApplicantNumberInPath(entry.getKey().getEntryPathName(), entry.getValue().intValue())) .toList(); diff --git a/src/main/java/com/econovation/third_project/service/RegistrationService.java b/src/main/java/com/econovation/third_project/service/RegistrationService.java index 140bb8e..a0de47a 100644 --- a/src/main/java/com/econovation/third_project/service/RegistrationService.java +++ b/src/main/java/com/econovation/third_project/service/RegistrationService.java @@ -35,9 +35,9 @@ public List getApplicantNumbersEachJob(){ } //지원 조회 - public Registration getRegistration(String registrationId){ - return db.getRegistration(registrationId); - } +// public Registration getRegistration(String registrationId){ +// return db.getRegistration(registrationId); +// } //세부 분야별 지원자 수 public List getApplicantNumberEachField(){ @@ -53,13 +53,14 @@ public List getApplicantNumberEachField(){ .ifPresent(secondPriority -> jobPriorityCounts.get(secondPriority)[1]++); }); - return jobPriorityCounts.entrySet() - .stream() + return jobPriorityCounts.entrySet().stream() .map(entry-> new ApplicantNumberInField( entry.getKey().getFieldName(), entry.getValue()[0], - entry.getValue()[1])) + entry.getValue()[1] + ) + ) .sorted(reverseOrder()) .toList(); } From 9e548d44613661c5afbf04f7ea16a3f41a92b5a5 Mon Sep 17 00:00:00 2001 From: coco3x Date: Mon, 20 May 2024 16:57:54 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=EB=8F=99=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../third_project/controller/AdminQueryController.java | 7 +++++-- .../third_project/service/DesiredTimeService.java | 5 +++++ .../econovation/third_project/service/PathService.java | 5 +++++ .../service/PersonalInformationService.java | 5 +++++ .../third_project/service/RegistrationService.java | 10 ++++++++++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java index 3e6768b..85c6b1c 100644 --- a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java +++ b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java @@ -31,16 +31,19 @@ public class AdminQueryController { //쿼리 파라미터 @GetMapping("/applicants") public ResponseEntity>> getApplicantsInfo(){ - - return ResponseEntity.ok().body(Map.of( + long start = System.currentTimeMillis(); + ResponseEntity>> response = ResponseEntity.ok().body(Map.of( "job", registrationService.getApplicantNumbersEachJob(), "field", registrationService.getApplicantNumberEachField(), "major", personalInformationService.getApplicantNumberEachMajor(), "path", pathService.getApplicantNumberEachPath(), "desired_time", desiredTimeService.getApplicantNumberEachTime() )); + System.out.println(System.currentTimeMillis() - start); + return response; } + } diff --git a/src/main/java/com/econovation/third_project/service/DesiredTimeService.java b/src/main/java/com/econovation/third_project/service/DesiredTimeService.java index 1fef3a8..bbe21cb 100644 --- a/src/main/java/com/econovation/third_project/service/DesiredTimeService.java +++ b/src/main/java/com/econovation/third_project/service/DesiredTimeService.java @@ -16,6 +16,11 @@ public class DesiredTimeService { //입력할 때 2개인지 확인해야 함 public List getApplicantNumberEachTime(){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } return db.getAllDesiredTime().stream() .flatMap(desiredTime -> desiredTime.getDesiredTimes().stream()) .collect(Collectors.groupingBy(time -> time, Collectors.counting())) diff --git a/src/main/java/com/econovation/third_project/service/PathService.java b/src/main/java/com/econovation/third_project/service/PathService.java index 277372e..84158c5 100644 --- a/src/main/java/com/econovation/third_project/service/PathService.java +++ b/src/main/java/com/econovation/third_project/service/PathService.java @@ -14,6 +14,11 @@ public class PathService { private final Database db; public List getApplicantNumberEachPath(){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } return db.getAllPath().stream() .flatMap(path-> path.getSupportPaths().stream()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) diff --git a/src/main/java/com/econovation/third_project/service/PersonalInformationService.java b/src/main/java/com/econovation/third_project/service/PersonalInformationService.java index 4b1aa74..09d62ff 100644 --- a/src/main/java/com/econovation/third_project/service/PersonalInformationService.java +++ b/src/main/java/com/econovation/third_project/service/PersonalInformationService.java @@ -15,6 +15,11 @@ public class PersonalInformationService { //학과별 지원자 수 public List getApplicantNumberEachMajor(){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } Map majorCounts = new HashMap<>(); db.getAllPersonalInformation().forEach(info -> { diff --git a/src/main/java/com/econovation/third_project/service/RegistrationService.java b/src/main/java/com/econovation/third_project/service/RegistrationService.java index a0de47a..7df1064 100644 --- a/src/main/java/com/econovation/third_project/service/RegistrationService.java +++ b/src/main/java/com/econovation/third_project/service/RegistrationService.java @@ -26,6 +26,11 @@ public class RegistrationService { //분야별 지원자 수 public List getApplicantNumbersEachJob(){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } return db.getAllRegistrations().stream() .collect(Collectors.groupingBy(Registration::getHopeJob, Collectors.counting())) .entrySet().stream() @@ -41,6 +46,11 @@ public List getApplicantNumbersEachJob(){ //세부 분야별 지원자 수 public List getApplicantNumberEachField(){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } Map jobPriorityCounts = new EnumMap<>(Field.class); for (Field field : Field.values()) From 0ca824839cf31bcedab7c35bef734185fd716f1c Mon Sep 17 00:00:00 2001 From: coco3x Date: Mon, 20 May 2024 22:32:02 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=EB=B3=91=EB=A0=AC=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AdminQueryController.java | 68 ++++++++++++++++--- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java index 85c6b1c..c696d23 100644 --- a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java +++ b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java @@ -1,20 +1,19 @@ package com.econovation.third_project.controller; -import com.econovation.third_project.database.Database; -import com.econovation.third_project.database.Registration; -import com.econovation.third_project.dto.CreateApplicationReq; -import com.econovation.third_project.service.ApplicationService; import com.econovation.third_project.service.DesiredTimeService; import com.econovation.third_project.service.PathService; import com.econovation.third_project.service.PersonalInformationService; import com.econovation.third_project.service.RegistrationService; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import java.util.function.Supplier; +import static java.util.stream.Collectors.*; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -28,22 +27,71 @@ public class AdminQueryController { private final DesiredTimeService desiredTimeService; - //쿼리 파라미터 + //모든 데이터 한 번에 반환 @GetMapping("/applicants") public ResponseEntity>> getApplicantsInfo(){ - long start = System.currentTimeMillis(); - ResponseEntity>> response = ResponseEntity.ok().body(Map.of( + return ResponseEntity.ok().body(Map.of( "job", registrationService.getApplicantNumbersEachJob(), "field", registrationService.getApplicantNumberEachField(), "major", personalInformationService.getApplicantNumberEachMajor(), "path", pathService.getApplicantNumberEachPath(), "desired_time", desiredTimeService.getApplicantNumberEachTime() )); - System.out.println(System.currentTimeMillis() - start); - return response; } + //동적 응답 + 병렬 스트림 + @GetMapping("/applicants/parallel") + public ResponseEntity>> getApplicantsInfo(@RequestBody List fields){ + Map>> services = Map.of( + "job", registrationService::getApplicantNumbersEachJob, + "field", registrationService::getApplicantNumberEachField, + "major", personalInformationService::getApplicantNumberEachMajor, + "path", pathService::getApplicantNumberEachPath, + "desired_time", desiredTimeService::getApplicantNumberEachTime + ); + Map> result = fields.stream().parallel() + .filter(services::containsKey) + .collect(toMap( + Function.identity(), + requestField-> services.get(requestField).get() + ) + ); + return ResponseEntity.ok().body(result); + } + + //동적 응답 + async + @GetMapping("/applicants/async") + public ResponseEntity>> getApplicantsInfoAsync(@RequestBody List fields){ + Map>> services = Map.of( + "job", registrationService::getApplicantNumbersEachJob, + "field", registrationService::getApplicantNumberEachField, + "major", personalInformationService::getApplicantNumberEachMajor, + "path", pathService::getApplicantNumberEachPath, + "desired_time", desiredTimeService::getApplicantNumberEachTime + ); + + Map>> futures = fields.stream() + .collect(toMap( + Function.identity(), + field -> { + Supplier> service = services.get(field); + if (service == null) + throw new IllegalArgumentException(); + return CompletableFuture.supplyAsync(service); + } + )); + + CompletableFuture>> result = CompletableFuture.allOf( + futures.values().toArray(CompletableFuture[]::new) + ).thenApply(v -> + fields.stream() + .collect(toMap(Function.identity(), field-> futures.get(field).join())) + ); + + return ResponseEntity.ok().body(result.join()); + } + //병렬 스트림 + async } From 59ade23141fdddddc0a89dc4cd525f0b50cdc484 Mon Sep 17 00:00:00 2001 From: coco3x Date: Mon, 20 May 2024 22:40:23 +0900 Subject: [PATCH 6/9] comment: todo --- .../third_project/controller/AdminQueryController.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java index c696d23..3c08395 100644 --- a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java +++ b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java @@ -92,6 +92,14 @@ public ResponseEntity>> getApplicantsInfoAsync(@RequestBody return ResponseEntity.ok().body(result.join()); } - //병렬 스트림 + async + + //TODO: + // 병렬 스트림 + async의 장점, + // 병렬 스트림, async 각각 적절한 상황, + // 서비스 메서드마다 다른 인자가 필요한 경우, + // 일부 의존 관계가 있을경우 어떻게 처리할지 + // 서비스 메서드 맵 어떻게 뺄지, + // 적절한 스레드 수 알아보기, + // 자바 비동기 기초, } From 70e6cde07f4a367f7b1eb7b53bbb456db8af5f29 Mon Sep 17 00:00:00 2001 From: coco3x Date: Mon, 20 May 2024 23:13:45 +0900 Subject: [PATCH 7/9] =?UTF-8?q?fix:=2027=EA=B8=B0=20DesiredTime=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기준이 바뀔때마다 클래스 하나씩 추가하는건 좋지 않다고 생각돼서 삭제함 --- .../controller/ApplicationController.java | 2 ++ .../third_project/database/DesiredTime.java | 23 ++++++++++++------ .../third_project/database/DesiredTime27.java | 24 ------------------- .../third_project/dto/DesiredTimeReq.java | 3 +-- 4 files changed, 19 insertions(+), 33 deletions(-) delete mode 100644 src/main/java/com/econovation/third_project/database/DesiredTime27.java diff --git a/src/main/java/com/econovation/third_project/controller/ApplicationController.java b/src/main/java/com/econovation/third_project/controller/ApplicationController.java index 2dc3c37..ce15d15 100644 --- a/src/main/java/com/econovation/third_project/controller/ApplicationController.java +++ b/src/main/java/com/econovation/third_project/controller/ApplicationController.java @@ -7,9 +7,11 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api") @RequiredArgsConstructor +@RestController public class ApplicationController { private final ApplicationService applicationService; diff --git a/src/main/java/com/econovation/third_project/database/DesiredTime.java b/src/main/java/com/econovation/third_project/database/DesiredTime.java index 2d30b55..475fe64 100644 --- a/src/main/java/com/econovation/third_project/database/DesiredTime.java +++ b/src/main/java/com/econovation/third_project/database/DesiredTime.java @@ -6,18 +6,27 @@ import lombok.Getter; @Getter -public abstract class DesiredTime { +public class DesiredTime { private static final Map, List> cachedTimes = new HashMap<>(); + private final List> desiredTimes; - // 희망 시간 (11 * 3)의 테이블 형태를 준수합니다. - final List> desiredTimes; - - abstract void validateDesiredTime(List> desiredTimes); - - DesiredTime(List> desiredTimes) { + public DesiredTime(List> desiredTimes) { validateDesiredTime(desiredTimes); this.desiredTimes = desiredTimes.stream() .map(time-> cachedTimes.computeIfAbsent(time, t->t)) .toList(); } + private void validateDesiredTime(List> desiredTimes) { + //27기 기준 + int interviewDays = 3; + int hoursPerDay = 11; + + desiredTimes.forEach( + time -> { + if (time.get(0) >= interviewDays || time.get(1) >= hoursPerDay) + throw new IllegalArgumentException("면접 시간 잘못 입력"); + } + ); + + } } diff --git a/src/main/java/com/econovation/third_project/database/DesiredTime27.java b/src/main/java/com/econovation/third_project/database/DesiredTime27.java deleted file mode 100644 index 69d73d9..0000000 --- a/src/main/java/com/econovation/third_project/database/DesiredTime27.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.econovation.third_project.database; - -import java.util.List; - -public final class DesiredTime27 extends DesiredTime{ - public DesiredTime27(List> desiredTimes){ - super(desiredTimes); - } - - @Override - void validateDesiredTime(List> desiredTimes) { - //27기 기준 - int interviewDays = 3; - int hoursPerDay = 11; - - desiredTimes.forEach( - time -> { - if (time.get(0) >= interviewDays || time.get(1) >= hoursPerDay) - throw new IllegalArgumentException("면접 시간 잘못 입력"); - } - ); - - } -} diff --git a/src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java b/src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java index 53ecc08..97db7ea 100644 --- a/src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java +++ b/src/main/java/com/econovation/third_project/dto/DesiredTimeReq.java @@ -1,11 +1,10 @@ package com.econovation.third_project.dto; import com.econovation.third_project.database.DesiredTime; -import com.econovation.third_project.database.DesiredTime27; import java.util.List; public record DesiredTimeReq(List> desiredTimes){ public DesiredTime toEntity(){ - return new DesiredTime27(desiredTimes); + return new DesiredTime(desiredTimes); } } From eda68fc108b2fde781464c9dfd7bd0cec8073824 Mon Sep 17 00:00:00 2001 From: coco3x Date: Sat, 25 May 2024 00:46:57 +0900 Subject: [PATCH 8/9] =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=A7=91=EA=B3=84=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC,=20=EB=82=98=EB=A8=B8=EC=A7=80=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agrregate/AdminPageQuery.java | 9 ++ .../agrregate/AdminPageQueryAggregator.java | 45 ++++++++++ .../third_project/agrregate/PathQuery.java | 21 +++++ .../third_project/config/Field.java | 3 +- .../controller/AdminQueryController.java | 83 ++----------------- .../third_project/database/Registration.java | 7 +- .../dto/ApplicantNumberInField.java | 11 +++ .../service/PersonalInformationService.java | 20 ++--- .../service/RegistrationService.java | 67 +++++++-------- 9 files changed, 135 insertions(+), 131 deletions(-) create mode 100644 src/main/java/com/econovation/third_project/agrregate/AdminPageQuery.java create mode 100644 src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java create mode 100644 src/main/java/com/econovation/third_project/agrregate/PathQuery.java diff --git a/src/main/java/com/econovation/third_project/agrregate/AdminPageQuery.java b/src/main/java/com/econovation/third_project/agrregate/AdminPageQuery.java new file mode 100644 index 0000000..a2b73bf --- /dev/null +++ b/src/main/java/com/econovation/third_project/agrregate/AdminPageQuery.java @@ -0,0 +1,9 @@ +package com.econovation.third_project.agrregate; + +import java.util.List; + +public interface AdminPageQuery { + String getType(); + List execute(); + +} diff --git a/src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java b/src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java new file mode 100644 index 0000000..4ad8d19 --- /dev/null +++ b/src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java @@ -0,0 +1,45 @@ +package com.econovation.third_project.agrregate; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class AdminPageQueryAggregator { + private final List queries; + + public Map> aggregate(Set requests){ + List queriesToExecute = getQueriesToExecute(requests); + Map>> executedQueries = executeQueriesAsync(queriesToExecute); + return aggregateResults(executedQueries); + } + + private List getQueriesToExecute(Set requests){ + return this.queries.stream() + .filter(query -> requests.contains(query.getType())) + .toList(); + } + + private Map>> executeQueriesAsync(List queriesToExecute){ + return queriesToExecute.stream() + .collect(Collectors.toMap( + AdminPageQuery::getType, + query-> CompletableFuture.supplyAsync(query::execute) + )); + } + + private Map> aggregateResults(Map>> executedQueries) { + return CompletableFuture.allOf(executedQueries.values().toArray(new CompletableFuture[0])) + .>>thenApply(v -> + executedQueries.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().join())) + ) + .join(); + } + +} diff --git a/src/main/java/com/econovation/third_project/agrregate/PathQuery.java b/src/main/java/com/econovation/third_project/agrregate/PathQuery.java new file mode 100644 index 0000000..cdd14f1 --- /dev/null +++ b/src/main/java/com/econovation/third_project/agrregate/PathQuery.java @@ -0,0 +1,21 @@ +package com.econovation.third_project.agrregate; + +import com.econovation.third_project.service.PathService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class PathQuery implements AdminPageQuery{ + private final PathService pathService; + @Override + public String getType() { + return "path"; + } + + @Override + public List execute() { + return pathService.getApplicantNumberEachPath(); + } +} diff --git a/src/main/java/com/econovation/third_project/config/Field.java b/src/main/java/com/econovation/third_project/config/Field.java index dd903dd..3d9ebb2 100644 --- a/src/main/java/com/econovation/third_project/config/Field.java +++ b/src/main/java/com/econovation/third_project/config/Field.java @@ -11,7 +11,8 @@ public enum Field { AI("AI"), GAME("GAME"), IOT("IoT"), - ARVR("AR/VR"); + ARVR("AR/VR"), + NONE("선택없음"); private final String fieldName; diff --git a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java index 3c08395..5d911ce 100644 --- a/src/main/java/com/econovation/third_project/controller/AdminQueryController.java +++ b/src/main/java/com/econovation/third_project/controller/AdminQueryController.java @@ -1,15 +1,9 @@ package com.econovation.third_project.controller; -import com.econovation.third_project.service.DesiredTimeService; -import com.econovation.third_project.service.PathService; -import com.econovation.third_project.service.PersonalInformationService; -import com.econovation.third_project.service.RegistrationService; +import com.econovation.third_project.agrregate.AdminPageQueryAggregator; import java.util.List; import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; -import java.util.function.Supplier; -import static java.util.stream.Collectors.*; +import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -21,75 +15,12 @@ @RequiredArgsConstructor @RequestMapping("/api/admin") public class AdminQueryController { - private final RegistrationService registrationService; - private final PathService pathService; - private final PersonalInformationService personalInformationService; - private final DesiredTimeService desiredTimeService; + private final AdminPageQueryAggregator adminPageQueryAggregator; - - //모든 데이터 한 번에 반환 - @GetMapping("/applicants") - public ResponseEntity>> getApplicantsInfo(){ - return ResponseEntity.ok().body(Map.of( - "job", registrationService.getApplicantNumbersEachJob(), - "field", registrationService.getApplicantNumberEachField(), - "major", personalInformationService.getApplicantNumberEachMajor(), - "path", pathService.getApplicantNumberEachPath(), - "desired_time", desiredTimeService.getApplicantNumberEachTime() - )); - } - - //동적 응답 + 병렬 스트림 - @GetMapping("/applicants/parallel") - public ResponseEntity>> getApplicantsInfo(@RequestBody List fields){ - Map>> services = Map.of( - "job", registrationService::getApplicantNumbersEachJob, - "field", registrationService::getApplicantNumberEachField, - "major", personalInformationService::getApplicantNumberEachMajor, - "path", pathService::getApplicantNumberEachPath, - "desired_time", desiredTimeService::getApplicantNumberEachTime - ); - Map> result = fields.stream().parallel() - .filter(services::containsKey) - .collect(toMap( - Function.identity(), - requestField-> services.get(requestField).get() - ) - ); - - return ResponseEntity.ok().body(result); - } - - //동적 응답 + async - @GetMapping("/applicants/async") - public ResponseEntity>> getApplicantsInfoAsync(@RequestBody List fields){ - Map>> services = Map.of( - "job", registrationService::getApplicantNumbersEachJob, - "field", registrationService::getApplicantNumberEachField, - "major", personalInformationService::getApplicantNumberEachMajor, - "path", pathService::getApplicantNumberEachPath, - "desired_time", desiredTimeService::getApplicantNumberEachTime - ); - - Map>> futures = fields.stream() - .collect(toMap( - Function.identity(), - field -> { - Supplier> service = services.get(field); - if (service == null) - throw new IllegalArgumentException(); - return CompletableFuture.supplyAsync(service); - } - )); - - CompletableFuture>> result = CompletableFuture.allOf( - futures.values().toArray(CompletableFuture[]::new) - ).thenApply(v -> - fields.stream() - .collect(toMap(Function.identity(), field-> futures.get(field).join())) - ); - - return ResponseEntity.ok().body(result.join()); + @GetMapping("/applicants/async-test") + public ResponseEntity>> getApplicantsInfo(@RequestBody Set fields){ + return ResponseEntity.ok().body( + adminPageQueryAggregator.aggregate(fields)); } diff --git a/src/main/java/com/econovation/third_project/database/Registration.java b/src/main/java/com/econovation/third_project/database/Registration.java index b85818f..e1df4c6 100644 --- a/src/main/java/com/econovation/third_project/database/Registration.java +++ b/src/main/java/com/econovation/third_project/database/Registration.java @@ -15,19 +15,16 @@ public class Registration { private Job hopeJob; @NonNull private Field firstPriority; + @Getter private Field secondPriority; public static Registration of(@NonNull String hopeJob, @NonNull String firstJobFieldName, String secondJobFieldName){ Job job = Job.valueOf(hopeJob.toUpperCase()); Field firstPriority = Field.valueOf(firstJobFieldName.toUpperCase()); - Field secondPriority = secondJobFieldName != null ? - Field.valueOf(secondJobFieldName.toUpperCase()) : null; + Field secondPriority = Field.valueOf(secondJobFieldName.toUpperCase()); return new Registration(job, firstPriority, secondPriority); } - public Optional getSecondPriority(){ - return Optional.ofNullable(this.secondPriority); - } } diff --git a/src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java index 18be9bc..59b277d 100644 --- a/src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java +++ b/src/main/java/com/econovation/third_project/dto/ApplicantNumberInField.java @@ -1,8 +1,19 @@ package com.econovation.third_project.dto; +import com.econovation.third_project.config.Field; +import java.util.Map.Entry; + public record ApplicantNumberInField(String fieldName, int firstNumber, int secondNumber) implements Comparable{ @Override public int compareTo(ApplicantNumberInField o) { return (this.firstNumber+this.secondNumber) - (o.firstNumber + o.secondNumber); } + + public ApplicantNumberInField(Entry entry) { + this( + entry.getKey().getFieldName(), + entry.getValue()[0], + entry.getValue()[1] + ); + } } diff --git a/src/main/java/com/econovation/third_project/service/PersonalInformationService.java b/src/main/java/com/econovation/third_project/service/PersonalInformationService.java index 09d62ff..b53964f 100644 --- a/src/main/java/com/econovation/third_project/service/PersonalInformationService.java +++ b/src/main/java/com/econovation/third_project/service/PersonalInformationService.java @@ -5,6 +5,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,17 +24,13 @@ public List getApplicantNumberEachMajor(){ } catch (InterruptedException e) { throw new RuntimeException(e); } - Map majorCounts = new HashMap<>(); - db.getAllPersonalInformation().forEach(info -> { - //주전공 - majorCounts.merge(info.getMajor(), 1, Integer::sum); - //복수전공 - info.getDoubleMajor().ifPresent(doubleMajor -> majorCounts.merge(doubleMajor, 1, Integer::sum)); - }); - - return majorCounts.entrySet().stream() - .map(entry -> new ApplicantNumberInMajor(entry.getKey(), entry.getValue())) + return db.getAllPersonalInformation().stream() + .flatMap(info-> Stream.of(info.getMajor(), info.getDoubleMajor().orElse(null))) + .filter(Objects::nonNull) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) + .entrySet().stream() + .map(entry-> new ApplicantNumberInMajor(entry.getKey(), entry.getValue().intValue())) .toList(); } } \ No newline at end of file diff --git a/src/main/java/com/econovation/third_project/service/RegistrationService.java b/src/main/java/com/econovation/third_project/service/RegistrationService.java index 7df1064..9d93610 100644 --- a/src/main/java/com/econovation/third_project/service/RegistrationService.java +++ b/src/main/java/com/econovation/third_project/service/RegistrationService.java @@ -9,10 +9,12 @@ import com.econovation.third_project.dto.ApplicantNumberInField; import static java.util.Comparator.reverseOrder; +import java.util.Collection; import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,11 +28,6 @@ public class RegistrationService { //분야별 지원자 수 public List getApplicantNumbersEachJob(){ - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } return db.getAllRegistrations().stream() .collect(Collectors.groupingBy(Registration::getHopeJob, Collectors.counting())) .entrySet().stream() @@ -39,47 +36,39 @@ public List getApplicantNumbersEachJob(){ .toList(); } - //지원 조회 -// public Registration getRegistration(String registrationId){ -// return db.getRegistration(registrationId); -// } - //세부 분야별 지원자 수 public List getApplicantNumberEachField(){ - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - Map jobPriorityCounts = new EnumMap<>(Field.class); - - for (Field field : Field.values()) - jobPriorityCounts.put(field, new int[2]); - - db.getAllRegistrations() - .forEach(regi->{ - jobPriorityCounts.get(regi.getFirstPriority())[0]++; - regi.getSecondPriority() - .ifPresent(secondPriority -> jobPriorityCounts.get(secondPriority)[1]++); - }); - - return jobPriorityCounts.entrySet().stream() - .map(entry-> - new ApplicantNumberInField( - entry.getKey().getFieldName(), - entry.getValue()[0], - entry.getValue()[1] - ) - ) + return PriorityCounts.of(db.getAllRegistrations()) + .getJobPriorityCounts() + .entrySet().stream() + .map(ApplicantNumberInField::new) .sorted(reverseOrder()) .toList(); } - //지원 등록 -// public PostRegistrationRes postRegistration() +} - //지원 수정 +@Getter +final class PriorityCounts{ + private final Map jobPriorityCounts = new EnumMap<>(Field.class); - //지원 삭제 + private PriorityCounts() { + for (Field field : Field.values()) + jobPriorityCounts.put(field, new int[2]); + } + static PriorityCounts of(Collection registrations){ + PriorityCounts priorityCounts = new PriorityCounts(); + registrations.forEach(regi->{ + priorityCounts.incrementFirstPriority(regi.getFirstPriority()); + priorityCounts.incrementSecondPriority(regi.getSecondPriority()); + }); + return priorityCounts; + } + private void incrementFirstPriority(Field field){ + jobPriorityCounts.get(field)[0]++; + } + private void incrementSecondPriority(Field field){ + jobPriorityCounts.get(field)[1]++; + } } From cab84230c7c623c02c7a38cbc09ae19b74f6cbe5 Mon Sep 17 00:00:00 2001 From: coco3x Date: Sat, 25 May 2024 03:13:26 +0900 Subject: [PATCH 9/9] fix: aggregator --- .../agrregate/AdminPageQueryAggregator.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java b/src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java index 4ad8d19..69c5ed1 100644 --- a/src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java +++ b/src/main/java/com/econovation/third_project/agrregate/AdminPageQueryAggregator.java @@ -2,16 +2,21 @@ import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.function.Function; import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +//TODO: 제네릭? @Component -@RequiredArgsConstructor public class AdminPageQueryAggregator { - private final List queries; + private final Map queries; + public AdminPageQueryAggregator(List queries) { + this.queries = queries.stream() + .collect(Collectors.toMap(AdminPageQuery::getType, Function.identity())); + } public Map> aggregate(Set requests){ List queriesToExecute = getQueriesToExecute(requests); @@ -20,8 +25,10 @@ public Map> aggregate(Set requests){ } private List getQueriesToExecute(Set requests){ - return this.queries.stream() - .filter(query -> requests.contains(query.getType())) + return requests.stream() + .map(request -> Optional.ofNullable(queries.get(request)) + .orElseThrow(IllegalArgumentException::new) + ) .toList(); }