diff --git a/src/main/java/mvc/promiseme/calendar/entity/Calendar.java b/src/main/java/mvc/promiseme/calendar/entity/Calendar.java index 995dffb..3a422e5 100644 --- a/src/main/java/mvc/promiseme/calendar/entity/Calendar.java +++ b/src/main/java/mvc/promiseme/calendar/entity/Calendar.java @@ -1,10 +1,7 @@ package mvc.promiseme.calendar.entity; import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import mvc.promiseme.project.entity.Member; import mvc.promiseme.project.entity.Project; @@ -20,6 +17,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter +@Setter @Builder public class Calendar { diff --git a/src/main/java/mvc/promiseme/project/controller/ProjectController.java b/src/main/java/mvc/promiseme/project/controller/ProjectController.java index ad8ff5e..7b8fd7a 100644 --- a/src/main/java/mvc/promiseme/project/controller/ProjectController.java +++ b/src/main/java/mvc/promiseme/project/controller/ProjectController.java @@ -6,6 +6,7 @@ import mvc.promiseme.project.dto.ProjectRequestDTO; import mvc.promiseme.project.dto.ProjectResponseDTO; import mvc.promiseme.project.dto.RecommendMemberRequestDTO; +import mvc.promiseme.project.dto.RecommendScheduleRequestDTO; import mvc.promiseme.project.service.ProjectService; import mvc.promiseme.project.service.RecommendService; import org.springframework.http.ResponseEntity; @@ -36,15 +37,18 @@ public ResponseEntity> categoryRanking(){ } @PostMapping("/create") - public ResponseEntity insert(@RequestBody ProjectRequestDTO projectRequestDTO){ + public ResponseEntity> insert(@RequestBody ProjectRequestDTO projectRequestDTO){ + Map result = new HashMap<>(); - return ResponseEntity.ok(projectService.insert(projectRequestDTO)); + + result.put("projectId",projectService.insert(projectRequestDTO)); + return ResponseEntity.ok(result); } @GetMapping("/progress") public ResponseEntity> progress(@RequestParam("projectId")Long projectId){ Map progressResult = new HashMap<>(); - progressResult.put("Prgress", projectService.progress(projectId)); + progressResult.put("progress", projectService.progress(projectId)); return ResponseEntity.ok(progressResult); } @@ -59,6 +63,9 @@ public ResponseEntity > dday(@RequestParam("projectId") Long public ResponseEntity> recommendMember(@RequestBody RecommendMemberRequestDTO recommendMemberRequestDTO){ return ResponseEntity.ok(recommendService.recommendMember(recommendMemberRequestDTO)); } - + @PostMapping("/recommend/schedule") + public ResponseEntity>> recommendSchedule(@RequestBody RecommendScheduleRequestDTO recommendScheduleRequestDTO){ + return ResponseEntity.ok(recommendService.recommendSchedule(recommendScheduleRequestDTO)); + } } diff --git a/src/main/java/mvc/promiseme/project/dto/MemberDTO.java b/src/main/java/mvc/promiseme/project/dto/MemberDTO.java new file mode 100644 index 0000000..78b35c1 --- /dev/null +++ b/src/main/java/mvc/promiseme/project/dto/MemberDTO.java @@ -0,0 +1,13 @@ +package mvc.promiseme.project.dto; + +import lombok.*; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Builder +public class MemberDTO { + private Long userId; + private String role; +} diff --git a/src/main/java/mvc/promiseme/project/dto/Message.java b/src/main/java/mvc/promiseme/project/dto/Message.java new file mode 100644 index 0000000..c9ae290 --- /dev/null +++ b/src/main/java/mvc/promiseme/project/dto/Message.java @@ -0,0 +1,14 @@ +package mvc.promiseme.project.dto; + +import lombok.*; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Builder +public class Message { + private String role; + private String content; + +} diff --git a/src/main/java/mvc/promiseme/project/dto/ProjectRequestDTO.java b/src/main/java/mvc/promiseme/project/dto/ProjectRequestDTO.java index a02605b..f370b70 100644 --- a/src/main/java/mvc/promiseme/project/dto/ProjectRequestDTO.java +++ b/src/main/java/mvc/promiseme/project/dto/ProjectRequestDTO.java @@ -1,8 +1,10 @@ package mvc.promiseme.project.dto; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.*; import java.time.LocalDate; +import java.util.List; @NoArgsConstructor @AllArgsConstructor @@ -12,7 +14,9 @@ public class ProjectRequestDTO { private String name; private String category; - private String topic; + @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate start; + @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate deadline; + private List memberList; } diff --git a/src/main/java/mvc/promiseme/project/dto/RecommendMemberRequestDTO.java b/src/main/java/mvc/promiseme/project/dto/RecommendMemberRequestDTO.java index baf7d41..e1250d0 100644 --- a/src/main/java/mvc/promiseme/project/dto/RecommendMemberRequestDTO.java +++ b/src/main/java/mvc/promiseme/project/dto/RecommendMemberRequestDTO.java @@ -1,5 +1,6 @@ package mvc.promiseme.project.dto; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.*; import java.time.LocalDate; @@ -11,6 +12,10 @@ @Builder public class RecommendMemberRequestDTO { private String category; + + @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate start; + + @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate deadline; } diff --git a/src/main/java/mvc/promiseme/project/dto/RecommendScheduleRequestDTO.java b/src/main/java/mvc/promiseme/project/dto/RecommendScheduleRequestDTO.java index 0bb13f6..81b4d23 100644 --- a/src/main/java/mvc/promiseme/project/dto/RecommendScheduleRequestDTO.java +++ b/src/main/java/mvc/promiseme/project/dto/RecommendScheduleRequestDTO.java @@ -10,8 +10,8 @@ @Setter @Builder public class RecommendScheduleRequestDTO { + private Long projectId; private String category; - private String topic; private String member; private LocalDate start; private LocalDate deadline; diff --git a/src/main/java/mvc/promiseme/project/entity/Project.java b/src/main/java/mvc/promiseme/project/entity/Project.java index 3ef24a5..ff09e8e 100644 --- a/src/main/java/mvc/promiseme/project/entity/Project.java +++ b/src/main/java/mvc/promiseme/project/entity/Project.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import mvc.promiseme.calendar.entity.Calendar; import mvc.promiseme.meeting.entity.Meeting; +import mvc.promiseme.project.dto.ProjectRequestDTO; import mvc.promiseme.todo.entity.Todo; import mvc.promiseme.notice.entity.Notice; @@ -66,4 +67,13 @@ public void prePersist() { @OneToMany(mappedBy = "project") private List todoList = new ArrayList<>(); + + public Project mapToEntity(ProjectRequestDTO projectRequestDTO){ + return Project.builder().name(projectRequestDTO.getName()) + .createdAt(LocalDate.now()) + .category(projectRequestDTO.getCategory()) + .start(projectRequestDTO.getStart()). + deadline(projectRequestDTO.getDeadline()) + .isProgress(Progress.PROGRESSING).build(); + } } diff --git a/src/main/java/mvc/promiseme/project/repository/RoleRepository.java b/src/main/java/mvc/promiseme/project/repository/RoleRepository.java new file mode 100644 index 0000000..5cd60cb --- /dev/null +++ b/src/main/java/mvc/promiseme/project/repository/RoleRepository.java @@ -0,0 +1,8 @@ +package mvc.promiseme.project.repository; + +import mvc.promiseme.project.entity.Role; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RoleRepository extends JpaRepository { + Role findByName(String name); +} diff --git a/src/main/java/mvc/promiseme/project/service/ClovaStudioRecommend.java b/src/main/java/mvc/promiseme/project/service/ClovaStudioRecommend.java index 4375efa..807c190 100644 --- a/src/main/java/mvc/promiseme/project/service/ClovaStudioRecommend.java +++ b/src/main/java/mvc/promiseme/project/service/ClovaStudioRecommend.java @@ -14,10 +14,12 @@ public class ClovaStudioRecommend { @Value("${RECOMMEND_URL}") private String url; - @Value("${API_KEY_CLOVA_STUDIO}") + @Value("${RECOMMEND_API_KEY}") private String apiKeyClovaStudio; - @Value("${API_KEY}") - private String apiKey; - @Value("${REQUEST_ID}") - private String requestId; + @Value("${RECOMMEND_API_GATE_WAY_KEY}") + private String apiGateWayKey; + @Value("${RECOMMEND_MEMBER_REQUEST_ID}") + private String requestMemberId; + @Value("${RECOMMEND_SCHEDULE_REQUEST_ID}") + private String requestScheduleId; } \ No newline at end of file diff --git a/src/main/java/mvc/promiseme/project/service/ProjectService.java b/src/main/java/mvc/promiseme/project/service/ProjectService.java index ae6fa16..9f36078 100644 --- a/src/main/java/mvc/promiseme/project/service/ProjectService.java +++ b/src/main/java/mvc/promiseme/project/service/ProjectService.java @@ -9,7 +9,7 @@ public interface ProjectService { public List projectAll(Long userId); public List categoryRanking(); - public String insert (ProjectRequestDTO projectRequestDTO); + public Long insert (ProjectRequestDTO projectRequestDTO); public int progress(Long projectId); public int dday (Long projectId); diff --git a/src/main/java/mvc/promiseme/project/service/ProjectServiceImpl.java b/src/main/java/mvc/promiseme/project/service/ProjectServiceImpl.java index bdc6eee..d4e0a05 100644 --- a/src/main/java/mvc/promiseme/project/service/ProjectServiceImpl.java +++ b/src/main/java/mvc/promiseme/project/service/ProjectServiceImpl.java @@ -3,22 +3,24 @@ import lombok.RequiredArgsConstructor; import mvc.promiseme.common.exception.ErrorCode; import mvc.promiseme.common.exception.UserException; +import mvc.promiseme.project.dto.MemberDTO; import mvc.promiseme.project.dto.ProjectRequestDTO; import mvc.promiseme.project.dto.ProjectResponseDTO; import mvc.promiseme.project.entity.Member; +import mvc.promiseme.project.entity.MemberStatus; import mvc.promiseme.project.entity.Project; +import mvc.promiseme.project.entity.Role; import mvc.promiseme.project.repository.MemberRepository; import mvc.promiseme.project.repository.ProjectRepository; +import mvc.promiseme.project.repository.RoleRepository; import mvc.promiseme.todo.dto.TodoRequestDTO; +import mvc.promiseme.todo.entity.Todo; import mvc.promiseme.users.entity.Users; import mvc.promiseme.users.repository.UserRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Service @RequiredArgsConstructor @@ -27,6 +29,7 @@ public class ProjectServiceImpl implements ProjectService { private final ProjectRepository projectRepository; private final UserRepository userRepository; private final MemberRepository memberRepository; + private final RoleRepository roleRepository; @Override @Transactional public List projectAll(Long userId) { @@ -43,10 +46,33 @@ public List projectAll(Long userId) { public List categoryRanking() { return projectRepository.getCategoryRanking(); } - + @Transactional @Override - public String insert(ProjectRequestDTO projectRequestDTO) { - return null; + public Long insert(ProjectRequestDTO projectRequestDTO) { + try{ + Project p = new Project(); + Project project = p.mapToEntity(projectRequestDTO); + projectRepository.save(project); + System.out.println("projectId : " + project.getProjectId()); + List memberList = projectRequestDTO.getMemberList(); + + for(MemberDTO m : memberList){ + Role r = new Role(); + Role role = roleRepository.findByName(m.getRole()); + if(role==null) { + role = Role.builder().name(m.getRole()).build(); + roleRepository.save(role); + } + System.out.println("role name "+role.getName()); + Users user = userRepository.findById(m.getUserId()).orElseThrow(() -> new NoSuchElementException("[ERROR] 해당하는 사용자가 존재하지 않습니다.")); + Member member = Member.builder().project(project).role(role).users(user).status(MemberStatus.PARTICIPATION).build(); + memberRepository.save(member); + } + return project.getProjectId(); + + }catch (Exception e){ + throw new UserException(ErrorCode.DUPLICATE_USER); + } } @Override diff --git a/src/main/java/mvc/promiseme/project/service/RecommendService.java b/src/main/java/mvc/promiseme/project/service/RecommendService.java index 4934704..02fb934 100644 --- a/src/main/java/mvc/promiseme/project/service/RecommendService.java +++ b/src/main/java/mvc/promiseme/project/service/RecommendService.java @@ -2,12 +2,16 @@ import lombok.RequiredArgsConstructor; import mvc.promiseme.project.dto.RecommendMemberRequestDTO; +import mvc.promiseme.project.dto.RecommendScheduleRequestDTO; import org.springframework.stereotype.Service; +import java.util.List; import java.util.Map; public interface RecommendService { public Map recommendMember(RecommendMemberRequestDTO recommendMemberRequestDTO); -} + public List> recommendSchedule(RecommendScheduleRequestDTO recommendScheduleRequestDTO); + + } diff --git a/src/main/java/mvc/promiseme/project/service/RecommendServiceImpl.java b/src/main/java/mvc/promiseme/project/service/RecommendServiceImpl.java index f62c100..0f41b7c 100644 --- a/src/main/java/mvc/promiseme/project/service/RecommendServiceImpl.java +++ b/src/main/java/mvc/promiseme/project/service/RecommendServiceImpl.java @@ -3,60 +3,270 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.RequiredArgsConstructor; +import mvc.promiseme.calendar.entity.Calendar; +import mvc.promiseme.calendar.repository.CalendarRepository; +import mvc.promiseme.project.dto.Message; import mvc.promiseme.project.dto.RecommendMemberRequestDTO; +import mvc.promiseme.project.dto.RecommendScheduleRequestDTO; +import mvc.promiseme.project.entity.Project; +import mvc.promiseme.project.entity.Role; +import mvc.promiseme.project.repository.ProjectRepository; +import mvc.promiseme.project.repository.RoleRepository; import org.springframework.http.*; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestTemplate; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; +import java.time.LocalDate; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + @Service @RequiredArgsConstructor public class RecommendServiceImpl implements RecommendService{ private final ClovaStudioRecommend clovaStudioRecommend; + private final ProjectRepository projectRepository; + private final CalendarRepository calendarRepository; + private final RoleRepository roleRepository; @Override public Map recommendMember(RecommendMemberRequestDTO recommendMemberRequestDTO) { String url = clovaStudioRecommend.getUrl(); String apiKeyClovaStudio = clovaStudioRecommend.getApiKeyClovaStudio(); - StringBuilder prompt = new StringBuilder(); - prompt.append("{\"role\":\"system\",\"content\":\"당신은 프로젝트 관리를 잘하는 사람입니다. 당신은 프로젝트 분야와 프로젝트 기간을 알려주면 필요한 구성원을 추천해줄 수 있습니다.\"}," + - "{\"role\":\"user\",\"content\":\"나는 마케팅프로젝트를 진행할예정입니다. 시작날짜는 2023-12-07, 마감날짜는 2023-12-31입니다. 이때 필요한 팀의 구성원 역할을 알려주세요." + - " 다른 말 필요없이\\r\\n\\\"역할\\\" : \\\"역할이 해야할일\\\"\\r\\n로만 대답해주세요. 다른 말 없이 역할과 역할이 해야할일만 작성해주세요.\"}," + - "{\"role\":\"assistant\",\"content\":\"PM : 프로젝트 전반에 걸쳐 일정, 예산, 인력 등을 관리하며 팀원들 간의 의사소통을 중재합니다.\\n디자이너: 마케팅 전략에 맞는 시각적인 디자인을 담당합니다.\\n개발자: 웹 또는 앱 개발을 담당하여 사용자 친화적인 인터페이스를 구축합니다.\\n마케팅 전문가: 시장 조사 및 분석, 타겟 마케팅 전략 수립, 광고 캠페인 기획 등을 담당합니다.\\n작가: 마케팅 컨텐츠 작성을 담당합니다.\\n테크니컬 라이터: 기술적인 문서 작성을 담당합니다.\\n프로젝트 매니저 보조: PM을 도와 일정 관리, 예산 관리, 인력 관리 등을 담당합니다.\\n데이터 분석가: 마케팅 성과를 분석하고 보고서를 작성합니다.\\n소셜 미디어 매니저: 소셜 미디어 채널을 관리하고, 광고 게시 및 고객과의 소통을 담당합니다.\\n회계사: 예산 관리 및 회계 업무를 담당합니다.\"}"); - prompt.append("{\"role\":\"user\",\"content\":\"나는" + recommendMemberRequestDTO.getCategory() +"프로젝트를 진행할예정입니다. " + - "시작날짜는"+recommendMemberRequestDTO.getStart() +", " + - "마감날짜는"+recommendMemberRequestDTO.getDeadline() +"입니다. " + - "이때 필요한 팀의 구성원 역할을 알려주세요. " + - "다른 말 필요없이\\r\\n\\\"역할\\\" : \\\"역할이 해야할일\\\"\\r\\n로만 대답해주세요. 다른 말 없이 역할과 역할이 해야할일만 작성해주세요.\"}"); + List messages = new ArrayList<>(); + + // 첫 번째 메시지 + Message systemMessage = new Message("system", "당신은 프로젝트 관리를 잘하는 사람입니다. 당신은 프로젝트 분야와 프로젝트 기간을 알려주면 필요한 구성원을 추천해줄 수 있습니다."); + messages.add(systemMessage); + + // 두 번째 메시지 + Message userMessage = new Message("user", "나는 마케팅프로젝트를 진행할예정입니다. 시작날짜는 2023-12-07, 마감날짜는 2023-12-31입니다. 이때 필요한 팀의 구성원 역할을 알려주세요. 다른 말 필요없이\n\"역할\" : \"역할이 해야할일\"\n로만 대답해주세요. 다른 말 없이 역할과 역할이 해야할일만 작성해주세요."); + messages.add(userMessage); + + // 세 번째 메시지 + Message assistantMessage = new Message("assistant", "PM : 프로젝트 전반에 걸쳐 일정, 예산, 인력 등을 관리하며 팀원들 간의 의사소통을 중재합니다.\n디자이너: 마케팅 전략에 맞는 시각적인 디자인을 담당합니다.\n개발자: 웹 또는 앱 개발을 담당하여 사용자 친화적인 인터페이스를 구축합니다.\n마케팅 전문가: 시장 조사 및 분석, 타겟 마케팅 전략 수립, 광고 캠페인 기획 등을 담당합니다.\n작가: 마케팅 컨텐츠 작성을 담당합니다.\n테크니컬 라이터: 기술적인 문서 작성을 담당합니다.\n프로젝트 매니저 보조: PM을 도와 일정 관리, 예산 관리, 인력 관리 등을 담당합니다.\n데이터 분석가: 마케팅 성과를 분석하고 보고서를 작성합니다.\n소셜 미디어 매니저: 소셜 미디어 채널을 관리하고, 광고 게시 및 고객과의 소통을 담당합니다.\n회계사: 예산 관리 및 회계 업무를 담당합니다."); + messages.add(assistantMessage); + + Message requestMessage = new Message("user", "나는" + recommendMemberRequestDTO.getCategory() + "프로젝트를 진행할예정입니다. 시작날짜는" + recommendMemberRequestDTO.getStart() + ", 마감날짜는" + recommendMemberRequestDTO.getDeadline() + "입니다. 이때 필요한 팀의 구성원 역할을 알려주세요. 다른 말 필요없이\n\"역할\" : \"역할이 해야할일\"\n로만 대답해주세요. 다른 말 없이 역할과 역할이 해야할일만 작성해주세요."); + messages.add(requestMessage); + + HttpHeaders headers = new HttpHeaders(); + headers.set("X-NCP-CLOVASTUDIO-API-KEY", apiKeyClovaStudio); + headers.set("X-NCP-APIGW-API-KEY", clovaStudioRecommend.getApiGateWayKey()); + headers.set("X-NCP-CLOVASTUDIO-REQUEST-ID", clovaStudioRecommend.getRequestMemberId()); + headers.set("Content-Type", "application/json"); + + Map requestBody = new HashMap<>(); + requestBody.put("messages", messages); + requestBody.put("topP", 0.8); + requestBody.put("topK", 0); + requestBody.put("maxTokens", 256); + requestBody.put("temperature", 0.5); + requestBody.put("repeatPenalty", 5.0); + requestBody.put("includeAiFilters", "True"); + + HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); + + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); + + JsonObject jsonObject = JsonParser.parseString(responseEntity.getBody()).getAsJsonObject(); + JsonObject messageObject = jsonObject.getAsJsonObject("result").getAsJsonObject("message"); + String content = messageObject.get("content").getAsString(); + Map roleDescriptions = new HashMap<>(); + + String[] roleLines = content.split("\n"); + for (String line : roleLines) { + String[] rolePair = line.split(":"); + if (rolePair.length == 2) { + String role = rolePair[0].trim(); + String description = rolePair[1].trim(); + roleDescriptions.put(role, description); + } + + + } + return roleDescriptions; + } + @Transactional + public List> recommendSchedule(RecommendScheduleRequestDTO recommendScheduleRequestDTO) { + String url = clovaStudioRecommend.getUrl(); + String apiKeyClovaStudio = clovaStudioRecommend.getApiKeyClovaStudio(); + + + List messages = new ArrayList<>(); + + // 첫 번째 메시지 + Message systemMessage = new Message("system", "당신은 프로젝트 관리를 잘하는 사람입니다. 당신은 프로젝트 분야와 프로젝트 기간을 알려주면 필요한 구성원을 추천해줄 수 있습니다."); + messages.add(systemMessage); + + // 두 번째 메시지 + Message userMessage = new Message("user","나는 웹개발프로젝트를 진행할예정입니다. 시작날짜는 2023-12-07, 마감날짜는 2023-12-31입니다. 우리팀은 기획자, 백엔드개발자, 프론트개발자,디자이너가 있습니다. 기간 내에 각 역할별로 해야하는 업무를 알려주세요. 각자 프로젝트에서 해야하는 업무도 알려주고 그 업무들의 순서를 정해줬으면 좋겠습니다. 각 업무의 시작날짜와 마감날짜도 함께 알려주세요. 시작날짜와 마감날짜 형식은 \"yyyy-MM-dd\" 형식으로 작성해주세요. 다른 말 필요없이\n" + + "\n" + + "\"역할\" \n" + + "\"해야할 업무\" (시작날짜 ~ 마감날짜)로만 대답해주세요. 다른 말 없이 역할과 해야할 업무, 시작날짜, 마감날짜만 작성해주세요. 역할 앞에 숫자를 넣지 말고, 업무 앞에 -를 넣지 마세요. "); + messages.add(userMessage); + + // 세 번째 메시지 + Message assistantMessage = new Message("assistant", "기획자\n" + + "사용자 요구사항 정의서 작성 (2023-12-07 ~ 2023-12-10)\n" + + "기능 명세서 작성 (2023-12-11 ~ 2023-12-15)\n" + + "화면 설계서 작성 (2023-12-16 ~ 2023-12-20)\n" + + "\n" + + "백엔드 개발자\n" + + "DB 스키마 작성 (2023-12-21 ~ 2023-12-25)\n" + + "API 기능 구현 (2023-26 ~ 2023-12-30)\n" + + "서버 구축 및 배포 (2023-12-31)\n" + + "\n" + + "프론트엔드 개발자\n" + + "HTML/CSS 레이아웃 구성 (2023-12-07 ~ 2023-12-10)\n" + + "JavaScript 기능 구현 (2023-12-11 ~ 2023-12-20)\n" + + "반응형 웹 적용 (2023-12-21 ~ 2023-12-25)\n" + + "\n" + + "디자이너\n" + + "로고 디자인 (2023-12-07 ~ 202310)\n" + + "UI/UX 디자인 (2023-12-11 ~ 2023-12-20)\n" + + "웹 페이지 디자인 (2023-12-21 ~ 2023-12-31)"); + messages.add(assistantMessage); + + Message requestMessage = new Message("user", "나는" + recommendScheduleRequestDTO.getCategory() + "프로젝트를 진행할예정입니다. 시작날짜는" + recommendScheduleRequestDTO.getStart() + ", 마감날짜는" + recommendScheduleRequestDTO.getDeadline() + "입니다. 우리팀은"+recommendScheduleRequestDTO.getMember()+"가 있습니다. 기간 내에 각 역할별로 해야하는 업무를 알려주세요. 각자 프로젝트에서 해야하는 업무도 알려주고 그 업무들의 순서를 정해줬으면 좋겠습니다. 각 업무의 시작날짜와 마감날짜도 함께 알려주세요. 시작날짜와 마감날짜 형식은 \"yyyy-MM-dd\" 형식으로 작성해주세요. 다른 말 필요없이\n" + + "\n" + + "\"역할\" \n" + + "\"해야할 업무\" (시작날짜 ~ 마감날짜)로만 대답해주세요. 다른 말 없이 역할과 해야할 업무, 시작날짜, 마감날짜만 작성해주세요. 역할 앞에 숫자를 넣지 말고, 업무 앞에 -를 넣지 마세요. "); + messages.add(requestMessage); + HttpHeaders headers = new HttpHeaders(); headers.set("X-NCP-CLOVASTUDIO-API-KEY", apiKeyClovaStudio); - headers.set("X-NCP-APIGW-API-KEY", clovaStudioRecommend.getApiKey()); - headers.set("X-NCP-CLOVASTUDIO-REQUEST-ID", clovaStudioRecommend.getRequestId()); - headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("X-NCP-APIGW-API-KEY", clovaStudioRecommend.getApiGateWayKey()); + headers.set("X-NCP-CLOVASTUDIO-REQUEST-ID", clovaStudioRecommend.getRequestScheduleId()); + headers.set("Content-Type", "application/json"); Map requestBody = new HashMap<>(); - requestBody.put("texts", prompt); - requestBody.put("segMinSize", 300); - requestBody.put("includeAiFilters", true); + requestBody.put("messages", messages); + requestBody.put("topP", 0.8); + requestBody.put("topK", 0); requestBody.put("maxTokens", 256); - requestBody.put("autoSentenceSplitter", true); - requestBody.put("segCount", -1); - requestBody.put("segMaxSize", 1000); + requestBody.put("temperature", 0.5); + requestBody.put("repeatPenalty", 5.0); + requestBody.put("includeAiFilters", "True"); HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); RestTemplate restTemplate = new RestTemplate(); ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); - String resultText = null; JsonObject jsonObject = JsonParser.parseString(responseEntity.getBody()).getAsJsonObject(); - resultText = jsonObject.getAsJsonObject("result").get("text").getAsString(); - System.out.println(resultText); + JsonObject messageObject = jsonObject.getAsJsonObject("result").getAsJsonObject("message"); + String content = messageObject.get("content").getAsString(); + List> roleScheduleList = new ArrayList<>(); + + String[] roleLines = content.split("\n\n"); + System.out.println("================roleLines=========="); + for(String s : roleLines) + System.out.println(s); + + System.out.println("================roleLines=========="); + for (String line : roleLines) { + String[] rolePair = line.split("\n"); + if (rolePair.length > 0) { + String role = rolePair[0].trim(); + String rolePattern = "(\\d+\\.\\s*)?(.+)"; + Pattern roleRegex = Pattern.compile(rolePattern); + Matcher roleMatcher = roleRegex.matcher(role); + + if (roleMatcher.matches()) { + String roleNumber = roleMatcher.group(1); // 1. + role = roleMatcher.group(2); // 기획자 + + // 숫자와 점을 제거한 role + role = role.trim(); + } + + if(Character.isDigit(role.charAt(0))) + role = role.substring(4); + for (int i = 1; i < rolePair.length; i++) { + Map roleSchedule = new HashMap<>(); + String patternString = "(.*?) \\((.*?) ~ (.*?)\\)"; + + // 패턴 컴파일 + Pattern pattern = Pattern.compile(patternString); + + // 매처 생성 + Matcher matcher = pattern.matcher(rolePair[i]); - return null; + // 매칭되는 그룹 찾기 + if (matcher.find()) { + String task = matcher.group(1).trim(); + String taskPattern = "-?\\s*(.+)"; + + Pattern taskRegex = Pattern.compile(taskPattern); + Matcher taskMatcher = taskRegex.matcher(task); + + if (taskMatcher.matches()) + task = taskMatcher.group(1).trim(); + + String startDate = matcher.group(2).trim(); + String endDate = matcher.group(3).trim(); + + // 결과 출력 + System.out.println("Role : " + role); + System.out.println("Task: " + task); + System.out.println("Start Date: " + startDate); + System.out.println("End Date: " + endDate); + System.out.println(); + + roleSchedule.put("role", role); + roleSchedule.put("task", task); + roleSchedule.put("start", startDate); + roleSchedule.put("finish", endDate); + } else { + String patternString1 = "(.*?) \\((.*?)\\)"; + + // 패턴 컴파일 + Pattern pattern1 = Pattern.compile(patternString1); + + // 매처 생성 + Matcher matcher1 = pattern1.matcher(rolePair[i]); + + // 매칭되는 그룹 찾기 + if (matcher1.find()) { + String task = matcher1.group(1).trim(); + String startDate = matcher1.group(2).trim(); + String endDate = matcher1.group(2).trim(); + + roleSchedule.put("role", role); + roleSchedule.put("task", task); + roleSchedule.put("start", startDate); + roleSchedule.put("finish", endDate); + } else { + System.out.println("No match found for line: " + line); + // 이 부분에서 예외 처리 또는 로깅을 수행할 수 있습니다. + } + } + roleScheduleList.add(roleSchedule); + } + } + } + insertCalender(recommendScheduleRequestDTO.getProjectId(),roleScheduleList); + return roleScheduleList; } + + @Transactional + public void insertCalender(Long projectId, List> roleScheduleList) { + Project project = projectRepository.findById(projectId).orElseThrow(()->new NoSuchElementException("[ERROR] 해당하는 프로젝트가 존재하지 않습니다.")); + for(Map map : roleScheduleList){ + Role r = new Role(); + Role role = roleRepository.findByName(map.get("role")); + if(role==null) { + role = Role.builder().name(map.get("role")).build(); + roleRepository.save(role); + } + Calendar calendar = Calendar.builder().project(project).role(role).content(map.get("content")).finishDate(LocalDate.parse(map.get("finish"))).startDate(LocalDate.parse(map.get("start"))).build(); + calendarRepository.save(calendar); + } + } + } diff --git a/src/test/java/mvc/promiseme/project/projectTest.java b/src/test/java/mvc/promiseme/project/projectTest.java index 634e8a5..20e46d9 100644 --- a/src/test/java/mvc/promiseme/project/projectTest.java +++ b/src/test/java/mvc/promiseme/project/projectTest.java @@ -1,14 +1,19 @@ package mvc.promiseme.project; +import mvc.promiseme.project.dto.MemberDTO; import mvc.promiseme.project.dto.ProjectRequestDTO; import mvc.promiseme.project.dto.ProjectResponseDTO; +import mvc.promiseme.project.dto.RecommendScheduleRequestDTO; import mvc.promiseme.project.service.ProjectService; +import mvc.promiseme.project.service.RecommendService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; +import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -19,6 +24,9 @@ public class projectTest { @Autowired private ProjectService projectService; + @Autowired + private RecommendService recommendService; + @Test public void testGetDday() { int dday= projectService.dday(1L); @@ -42,9 +50,27 @@ public void testProjectAll(){ for(ProjectResponseDTO s : list){ System.out.println(s.getProjectId()); System.out.println(s.getName()); - System.out.println(s.getRole()); } + } + @Test + public void testInsert(){ + List memberDTOList = new ArrayList<>(); + memberDTOList.add(MemberDTO.builder().role("기획자").userId(1L).build()); + memberDTOList.add(MemberDTO.builder().role("디자이너").userId(2L).build()); + memberDTOList.add(MemberDTO.builder().role("프론트 개발자").userId(3L).build()); + memberDTOList.add(MemberDTO.builder().role("백엔드 개발자").userId(4L).build()); + ProjectRequestDTO requestDTO = ProjectRequestDTO.builder() + .category("웹개발"). + deadline(LocalDate.parse("2023-12-17")) + .name("포텐데이") + .start(LocalDate.parse("2023-12-03")) + .memberList(memberDTOList).build(); + System.out.println(projectService.insert(requestDTO)); + } + @Test + public void testRecommendSchedule(){ + recommendService.recommendSchedule(new RecommendScheduleRequestDTO(8L,"웹개발","기획자,백엔드개발자,프론트개발자,디자이너",LocalDate.parse("2023-10-13"),LocalDate.parse("2023-12-14"))); } }