Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.coderder.colorMeeting.config.auth.PrincipalDetails;
import com.coderder.colorMeeting.dto.request.ScheduleRequestDto;
import com.coderder.colorMeeting.dto.request.TeamScheduleRequestDto;
import com.coderder.colorMeeting.dto.request.TeamTimeDto;
import com.coderder.colorMeeting.dto.response.*;
import com.coderder.colorMeeting.service.ScheduleService;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -65,11 +64,11 @@ public ResponseEntity<List<PersonalScheduleListDto>> getTeamUserAllSchedule(@Req
return ResponseEntity.ok().body(scheduleBlockDtoList);
}
@GetMapping("/api/schedule/recommendations")
public ResponseEntity<ScheduleListDto> getRecommendations(@RequestBody TeamTimeDto teamTimeDto){
List<ScheduleBlockDto> recommendationList = scheduleService.getTeamEmptyTimes(teamTimeDto);
ScheduleListDto scheduleListDto = ScheduleListDto.builder()
.schedule(recommendationList).build();
return ResponseEntity.ok().body(scheduleListDto);
public ResponseEntity<RandomRecommendationDto> getRecommendations(
@RequestParam Long teamId,
@RequestParam Integer spanTime){
RandomRecommendationDto randomRecommendationDto = scheduleService.getRandomRecommandation(teamId, spanTime);
return ResponseEntity.ok().body(randomRecommendationDto);
}
@PostMapping("/api/schedule/teamschedule")
public ResponseEntity<ResponseMessage> makeTeamSchedule(@RequestParam Long teamId, @RequestBody TeamScheduleRequestDto teamScheduleDto){
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.coderder.colorMeeting.dto.request;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class TeamTimeDto {
private Long teamId;
private int spendingMinute;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.coderder.colorMeeting.dto.response;

import com.coderder.colorMeeting.model.Member;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
import net.bytebuddy.implementation.bind.annotation.Super;

import java.util.List;

@SuperBuilder
@Getter
public class AvailableScheduleDto extends ScheduleBlockDto{
private List<Member> availableMember;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.coderder.colorMeeting.dto.response;

import lombok.Builder;
import lombok.Data;

import java.util.List;

@Data
@Builder
public class RandomRecommendationDto {
private String start;
private String end;
private List<String> memberNickNames;
}
157 changes: 157 additions & 0 deletions src/main/java/com/coderder/colorMeeting/etc/ScheduleCalendar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package com.coderder.colorMeeting.etc;

import com.coderder.colorMeeting.dto.response.AvailableScheduleDto;
import com.coderder.colorMeeting.model.Member;
import com.coderder.colorMeeting.model.PersonalSchedule;
import lombok.AllArgsConstructor;

import java.time.LocalTime;
import java.util.*;

@AllArgsConstructor
public class ScheduleCalendar {
private List<List<Set<Member>>> calendar;
private List<Member> teamMembers;

public static ScheduleCalendar createCalendar(List<PersonalSchedule> teamSchedules, List<Member> members, int hourDividedBy) {
List<List<Set<Member>>> calendar = new ArrayList<>();
for(int i=0; i<7; i++){
List<Set<Member>> list = new ArrayList<>();
for(int j=0; j<24*hourDividedBy; j++){
list.add(new HashSet<>());
}
calendar.add(list);
}

for(PersonalSchedule schedule : teamSchedules){
List<Set<Member>> list = calendar.get(convertWeekday(schedule.getWeekday()));
int startIndex = convertTime(schedule.getStartTime(), hourDividedBy);
int endIndex = convertTime(schedule.getFinishTime().minusMinutes(1), hourDividedBy);
for(int i=startIndex; i<=endIndex; i++){
list.get(i).add(schedule.getMember());
}
}
//members can change!!!
return new ScheduleCalendar(calendar, members);
}
private static int convertWeekday(String weekday){
if(weekday.equalsIgnoreCase("mon") || weekday.equalsIgnoreCase("monday")) return 0;
else if(weekday.equalsIgnoreCase("tue") || weekday.equalsIgnoreCase("tuesday")) return 1;
else if(weekday.equalsIgnoreCase("wed") || weekday.equalsIgnoreCase("wednesday")) return 2;
else if(weekday.equalsIgnoreCase("thu") || weekday.equalsIgnoreCase("thursday")) return 3;
else if(weekday.equalsIgnoreCase("fri") || weekday.equalsIgnoreCase("friday")) return 4;
else if(weekday.equalsIgnoreCase("sat") || weekday.equalsIgnoreCase("saturday")) return 5;
else if(weekday.equalsIgnoreCase("sun") || weekday.equalsIgnoreCase("sunday")) return 6;
else return -1;
}
private static int convertTime(LocalTime time, int timeInterval){
int min = time.getMinute();
int hour = time.getHour();
int blockIndex = hour*timeInterval + (min / (60/timeInterval));
return blockIndex;
}

private static int convertTime(String time, int timeInterval){
int min = Integer.parseInt(time.split(":")[1]);
int hour = Integer.parseInt(time.split(":")[0]);
int blockIndex = hour*timeInterval + (min / (60/timeInterval));
return blockIndex;
}

private String convertToWeekday(int weekday){
if(weekday == 0) return "mon";
else if(weekday == 1) return "tue";
else if(weekday == 2) return "wed";
else if(weekday == 3) return "thu";
else if(weekday == 4) return "fri";
else if(weekday == 5) return "sat";
else if(weekday == 6) return "sun";
else return "";
}
private LocalTime convertToTime(int timeBlock, int timeInterval){
return LocalTime.of(timeBlock/timeInterval
, (timeBlock%timeInterval)*(60/timeInterval));
}


public List<AvailableScheduleDto> getMostAvailableList(Integer spanTime, Integer hourDividedBy) {
Integer maxNum = 0;
Integer requiredBlockNum = spanTime / (60/hourDividedBy);
System.out.println(requiredBlockNum);
//then, start,end time would be start only by "hourDividedBy"

//count continuous blocks(value) per member(key)
Map<Member, Integer> memberCounter = new HashMap<>();

initializeCounter(memberCounter, teamMembers);
List<AvailableScheduleDto> availableScheduleDtoList = new ArrayList<>();
for(int i=0; i< calendar.size(); i++){
List<Set<Member>> day = calendar.get(i);
for(int blockIndex=0; blockIndex<day.size(); blockIndex++){
Set<Member> oneBlock = day.get(blockIndex);
setCounter(memberCounter, oneBlock, requiredBlockNum);

Set<Member> availableMems = new HashSet<>();
for(Member member : memberCounter.keySet()){
if(memberCounter.get(member) == requiredBlockNum) availableMems.add(member);
}

if(maxNum < availableMems.size()){
maxNum = availableMems.size();
availableScheduleDtoList.clear();
String start = convertBlockToTime(blockIndex-requiredBlockNum+1, hourDividedBy);
String end = convertBlockToTime(blockIndex, hourDividedBy);
insertAvailableSchedule(availableScheduleDtoList, availableMems, start, end, convertToWeekday(i));

}else if(maxNum == availableMems.size()){
String start = convertBlockToTime(blockIndex-requiredBlockNum+1, hourDividedBy);
String end = convertBlockToTime(blockIndex+1, hourDividedBy);
insertAvailableSchedule(availableScheduleDtoList, availableMems, start, end, convertToWeekday(i));
}
}
}
return availableScheduleDtoList;
}

private String convertBlockToTime(Integer blockIndex, Integer hourDividedBy) {
int hour = blockIndex / hourDividedBy;
int minute = (blockIndex % hourDividedBy) * (60/hourDividedBy);

String time = String.format("%02d",hour)+":"+String.format("%02d",minute);
return time;
}

private void setCounter(Map<Member, Integer> memberCounter, Set<Member> oneBlock, Integer requiredBlockNum) {
for(Member mem : memberCounter.keySet()){
if(oneBlock.contains(mem)) memberCounter.put(mem, 0);
else {
Integer continuousCount = memberCounter.get(mem) == requiredBlockNum ?
memberCounter.get(mem) : memberCounter.get(mem)+1;
memberCounter.put(mem, continuousCount);
}
}
}

private void insertAvailableSchedule(List<AvailableScheduleDto> availableScheduleDtoList,
Set<Member> availableMems,
String start,
String end,
String weekday) {
List<Member> templist = new ArrayList<>();
for(Member mem : availableMems){
templist.add(mem);
}
AvailableScheduleDto dto = AvailableScheduleDto.builder()
.availableMember(templist)
.start(weekday+"+"+start)
.end(weekday+"+"+end)
.build();
availableScheduleDtoList.add(dto);
}

private void initializeCounter(Map<Member, Integer> memberCounter, List<Member> teamMembers) {
for(Member member : teamMembers){
memberCounter.put(member, 0);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import com.coderder.colorMeeting.dto.request.ScheduleRequestDto;
import com.coderder.colorMeeting.dto.request.TeamScheduleRequestDto;
import com.coderder.colorMeeting.dto.request.TeamTimeDto;
import com.coderder.colorMeeting.dto.response.PersonalScheduleDto;
import com.coderder.colorMeeting.dto.response.PersonalScheduleListDto;
import com.coderder.colorMeeting.dto.response.ScheduleBlockDto;
import com.coderder.colorMeeting.dto.response.TeamScheduleDto;
import com.coderder.colorMeeting.dto.response.*;
import com.coderder.colorMeeting.model.Member;

import java.util.List;
Expand All @@ -19,7 +16,6 @@ public interface ScheduleService {

List<ScheduleBlockDto> getBlockListByTeamIdWithoutOverlap(Long teamId);

List<ScheduleBlockDto> getTeamEmptyTimes(TeamTimeDto teamTimeDto);

void insertGroupSchedule(TeamScheduleRequestDto teamScheduleDto);

Expand All @@ -35,4 +31,6 @@ public interface ScheduleService {
void updateGroupSchedule(TeamScheduleRequestDto teamScheduleDto);

void deleteGroupSchedule(Long scheduleId);

RandomRecommendationDto getRandomRecommandation(Long teamId, Integer spanTime);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.coderder.colorMeeting.dto.request.TeamScheduleRequestDto;
import com.coderder.colorMeeting.dto.request.TeamTimeDto;
import com.coderder.colorMeeting.dto.response.*;
import com.coderder.colorMeeting.etc.ScheduleCalendar;
import com.coderder.colorMeeting.exception.ErrorCode;
import com.coderder.colorMeeting.exception.NotFoundException;
import com.coderder.colorMeeting.model.Member;
Expand All @@ -16,10 +17,8 @@

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ScheduleServiceImpl implements ScheduleService{
Expand Down Expand Up @@ -123,7 +122,6 @@ private List<ScheduleBlockDto> calendarToScheduleDto(boolean[][] calendar) {
return scheduleBlockDtoList;
}

@Override
public List<ScheduleBlockDto> getTeamEmptyTimes(TeamTimeDto teamTimeDto) {
List<Member> members = memberRepository.findAllWithTeamId(teamTimeDto.getTeamId());
List<PersonalSchedule> teamSchedules = personalScheduleRepository.findAllByMemberIn(members);
Expand Down Expand Up @@ -325,4 +323,39 @@ public void updateGroupSchedule(TeamScheduleRequestDto teamScheduleDto) {
public void deleteGroupSchedule(Long scheduleId) {
teamScheduleRepository.deleteById(scheduleId);
}

@Override
public RandomRecommendationDto getRandomRecommandation(Long teamId, Integer spanTime) {
List<AvailableScheduleDto> teamEmptyTimes = getMaxAvailableList(teamId, spanTime);

Random random = new Random();
AvailableScheduleDto randomSchedule = teamEmptyTimes.get(random.nextInt(teamEmptyTimes.size()));

List<String> availableMembers = randomSchedule.getAvailableMember()
.stream()
.map(Member::getNickname)
.collect(Collectors.toList());

RandomRecommendationDto randomRecommendationDto = RandomRecommendationDto.builder()
.start(randomSchedule.getStart())
.end(randomSchedule.getEnd())
.memberNickNames(availableMembers)
.build();

return randomRecommendationDto;
}

private List<AvailableScheduleDto> getMaxAvailableList(Long teamId, Integer spanTime) {
List<Member> members = memberRepository.findAllWithTeamId(teamId);
List<PersonalSchedule> teamSchedules = personalScheduleRepository.findAllByMemberIn(members);

List<AvailableScheduleDto> recommendationDtos = getMostEmptyTime(teamSchedules, members, spanTime, 2);
return recommendationDtos;
}

private List<AvailableScheduleDto> getMostEmptyTime(List<PersonalSchedule> teamSchedules, List<Member> members, Integer spanTime, int hourDividedBy) {
ScheduleCalendar calendar = ScheduleCalendar.createCalendar(teamSchedules, members, hourDividedBy);
List<AvailableScheduleDto> mostAvailableList = calendar.getMostAvailableList(spanTime, hourDividedBy);
return mostAvailableList;
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
spring.profiles.include=db-username,db-url,db-password,secret

# DB ddl
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.ddl-auto=none

# SQL DB
spring.jpa.properties.hibernate.format_sql=true
Expand Down