Skip to content

Commit

Permalink
[FEAT, FIX] 표정 인식 미션 구현, 알람 생성 명세서 설명 추가 및 간단한 코드 수정 (#44)
Browse files Browse the repository at this point in the history
## ☀️구현 내용
- 알람 가져오기 API type 문자열 상수로 변경
- mission 관련 dto 네이밍 수정
- data.sql -> mission object icon 변경
- 물체 인식 객체 리스트 업데이트
- 표정 인식 미션 API 구현
- 알람 생성 명세서 설명 추가
  • Loading branch information
hye-on authored Sep 14, 2023
2 parents 7b955c8 + 8bb810a commit 8648d27
Show file tree
Hide file tree
Showing 15 changed files with 320 additions and 121 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.wakeUpTogetUp.togetUp.api.alarm;

import static com.wakeUpTogetUp.togetUp.common.Constant.GET_ALARM_MODE_GROUP;
import static com.wakeUpTogetUp.togetUp.common.Constant.GET_ALARM_MODE_PERSONAL;

import com.wakeUpTogetUp.togetUp.api.alarm.dto.response.GetAlarmRes;
import com.wakeUpTogetUp.togetUp.api.alarm.model.Alarm;
import com.wakeUpTogetUp.togetUp.exception.BaseException;
Expand Down Expand Up @@ -27,10 +30,10 @@ public List<GetAlarmRes> getAlarmsByUserId(Integer userId, String type) {
userRepository.findById(userId).orElseThrow(
() -> new BaseException(Status.USER_NOT_FOUND));

if (type.equals("personal")) {
if (type.equals(GET_ALARM_MODE_PERSONAL)) {
List<Alarm> alarmList = alarmRepository.findAllByUser_IdAndRoom_IdIsNull(userId);
return EntityDtoMapper.INSTANCE.toAlarmResList(alarmList);
} else if (type.equals("group")) {
} else if (type.equals(GET_ALARM_MODE_GROUP)) {
List<Alarm> alarmList = alarmRepository.findAllByUser_IdAndRoom_IdIsNotNull(userId);
return EntityDtoMapper.INSTANCE.toAlarmResList(alarmList);
} else
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.wakeUpTogetUp.togetUp.api.alarm.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import javax.validation.constraints.Pattern;
import lombok.*;

Expand All @@ -13,57 +14,57 @@
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class PostAlarmReq {
@Schema(description = "알람 이름", example = "기상")
@Schema(description = "알람 이름", requiredMode = RequiredMode.REQUIRED, example = "기상")
@NotBlank(message = "알람 이름은 공백일 수 없습니다.")
private String name;

@Schema(description = "아이콘", example = "⏰")
@Schema(description = "아이콘", defaultValue = "⏰", example = "⏰")
private String icon;

@Schema(description = "다시울림 간격", example = "5")
@Schema(description = "다시울림 간격", defaultValue = "5", example = "5")
private Integer snoozeInterval;

@Schema(description = "다시울림 횟수", example = "3")
@Schema(description = "다시울림 횟수", defaultValue = "3", example = "3")
private Integer snoozeCnt;

@Schema(description = "알람 시간", example = "06:00")
@Schema(description = "알람 시간", requiredMode = RequiredMode.REQUIRED, example = "06:00")
@NotNull(message = "알람 시간은 공백일 수 없습니다.")
@Pattern(regexp = "^([01]?[0-9]|2[0-3]):[0-5][0-9]$", message = "HH:mm 형식이 아닙니다.")
private String alarmTime;

@Schema(description = "월요일 울림 여부", example = "false")
@Schema(description = "월요일 울림 여부", defaultValue = "false", example = "false")
private Boolean monday;

@Schema(description = "화요일 울림 여부", example = "false")
@Schema(description = "화요일 울림 여부", defaultValue = "false", example = "false")
private Boolean tuesday;

@Schema(description = "수요일 울림 여부", example = "false")
@Schema(description = "수요일 울림 여부", defaultValue = "false", example = "false")
private Boolean wednesday;

@Schema(description = "목요일 울림 여부", example = "false")
@Schema(description = "목요일 울림 여부", defaultValue = "false", example = "false")
private Boolean thursday;

@Schema(description = "금요일 울림 여부", example = "false")
@Schema(description = "금요일 울림 여부", defaultValue = "false", example = "false")
private Boolean friday;

@Schema(description = "토요일 울림 여부", example = "false")
@Schema(description = "토요일 울림 여부", defaultValue = "false", example = "false")
private Boolean saturday;

@Schema(description = "일요일 울림 여부", example = "false")
@Schema(description = "일요일 울림 여부", defaultValue = "false", example = "false")
private Boolean sunday;

@Schema(description = "다시울림 활성화 여부", example = "true", defaultValue = "true")
@Schema(description = "다시울림 활성화 여부", defaultValue = "true", example = "true")
private Boolean isSnoozeActivated;

@Schema(description = "진동 활성화 여부", example = "true")
@Schema(description = "진동 활성화 여부", defaultValue = "true", example = "true")
private Boolean isVibrate;

@Schema(description = "미션 id", example = "2")
@Schema(description = "미션 id", requiredMode = RequiredMode.REQUIRED, example = "2")
private Integer missionId;

@Schema(description = "미션 객체 id", example = "1")
@Schema(description = "미션 객체 id", requiredMode = RequiredMode.REQUIRED, example = "1")
private Integer missionObjectId;

@Schema(description = "그룹 id", example = "1")
@Schema(description = "그룹 id", requiredMode = RequiredMode.REQUIRED, example = "1")
private Integer roomId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import com.wakeUpTogetUp.togetUp.api.file.FileService;
import com.wakeUpTogetUp.togetUp.api.mission.dto.request.PostMissionLogReq;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.GetMissionWithObjectListRes;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.MissionLogRes;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.PostObjectRecognitionRes;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.GetMissionLogRes;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.PostPerformMissionRes;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand All @@ -30,24 +30,25 @@ public class MissionController {
private final MissionService missionService;
private final FileService fileService;

@Operation(summary = "미션 목록 가져오기", description = "missionId\n- 객체인식 : 2\n- 표정인식 : 3")
@Operation(summary = "미션 목록 가져오기")
@GetMapping("/{missionId}")
BaseResponse<GetMissionWithObjectListRes> getObjectDetectionMissions(
@PathVariable(value = "missionId") int missionId
@Parameter(required = true, description = "- 객체인식 : 2\n- 표정인식 : 3") @PathVariable(value = "missionId") int missionId
) {
return new BaseResponse(Status.SUCCESS, missionProvider.getMission(missionId));
}

@Operation(summary = "객체 탐지 미션")
@PostMapping(value = "/object-detection/{objectName}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.CREATED)
public BaseResponse<PostObjectRecognitionRes> recognizeObject(
public BaseResponse<PostPerformMissionRes> recognizeObject(
@Parameter(hidden = true) @AuthUser Integer userId,
@Parameter(description = "미션 수행 사진") @RequestPart MultipartFile missionImage,
@Parameter(description = "탐지할 객체") @PathVariable String objectName
@Parameter(required = true, description = "미션 수행 사진") @RequestPart MultipartFile missionImage,
@Parameter(required = true, description = "탐지할 객체") @PathVariable String objectName
) throws Exception {
long startTime = System.currentTimeMillis();

System.out.println("missionImage = " + missionImage.getOriginalFilename());
missionService.recognizeObject(objectName, missionImage);
String filePath = fileService.uploadFile(missionImage, "mission");

Expand All @@ -56,13 +57,34 @@ public BaseResponse<PostObjectRecognitionRes> recognizeObject(
long timeElapsed = endTime - startTime;
System.out.println("Execution time in milliseconds: " + timeElapsed);

return new BaseResponse(Status.MISSION_SUCCESS, new PostObjectRecognitionRes(filePath));
return new BaseResponse(Status.MISSION_SUCCESS, new PostPerformMissionRes(filePath));
}

@Operation(summary = "표정 인식 미션")
@PostMapping(value = "/face-recognition/{objectName}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.CREATED)
public BaseResponse<PostPerformMissionRes> recognizeFaceExpression(
@Parameter(hidden = true) @AuthUser Integer userId,
@Parameter(required = true, description = "미션 수행 사진") @RequestPart MultipartFile missionImage,
@Parameter(required = true, description = "탐지할 객체") @PathVariable String objectName
) throws Exception {
long startTime = System.currentTimeMillis();

missionService.recognizeEmotion(objectName, missionImage);
String filePath = fileService.uploadFile(missionImage, "mission");

// 걸린 시간 계산
long endTime = System.currentTimeMillis();
long timeElapsed = endTime - startTime;
System.out.println("Execution time in milliseconds: " + timeElapsed);

return new BaseResponse(Status.MISSION_SUCCESS, new PostPerformMissionRes(filePath));
}

@Operation(summary = "미션 수행 기록 생성")
@PostMapping("/complete")
@ResponseStatus(HttpStatus.CREATED)
public BaseResponse<MissionLogRes> postMissionLog(
public BaseResponse<GetMissionLogRes> postMissionLog(
@Parameter(hidden = true) @AuthUser Integer userId,
@RequestBody @Valid PostMissionLogReq postMissionLogReq
) {
Expand All @@ -76,7 +98,7 @@ public BaseResponse<MissionLogRes> postMissionLog(
@Operation(summary = "미션 수행 기록 가져오기")
@GetMapping("/logs")
@ResponseStatus(HttpStatus.OK)
public BaseResponse<List<MissionLogRes>> getMissionCompleteLogsByUserId(
public BaseResponse<List<GetMissionLogRes>> getMissionCompleteLogsByUserId(
@Parameter(hidden = true) @AuthUser Integer userId
) {
return new BaseResponse(Status.SUCCESS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.wakeUpTogetUp.togetUp.common.Status;
import com.wakeUpTogetUp.togetUp.exception.BaseException;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.GetMissionWithObjectListRes;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.MissionLogRes;
import com.wakeUpTogetUp.togetUp.api.mission.dto.response.GetMissionLogRes;
import com.wakeUpTogetUp.togetUp.utils.mapper.EntityDtoMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -23,15 +23,15 @@ public GetMissionWithObjectListRes getMission(int missionId) {
return EntityDtoMapper.INSTANCE.toGetMissionRes(mission);
}

public MissionLogRes getMissionLog(Integer missionCompleteLogId){
public GetMissionLogRes getMissionLog(Integer missionCompleteLogId){
MissionLog missionLog = missionLogRepository.findById(missionCompleteLogId)
.orElseThrow(
() -> new BaseException(Status.INTERNAL_SERVER_ERROR));

return EntityDtoMapper.INSTANCE.toMissionLogRes(missionLog);
}

public List<MissionLogRes> getMissionCompleteLogsByUserId(Integer userId) {
public List<GetMissionLogRes> getMissionCompleteLogsByUserId(Integer userId) {
List<MissionLog> missionLogList = missionLogRepository.findAllByUserId(userId);

return EntityDtoMapper.INSTANCE.toMissionLogResList(missionLogList);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.wakeUpTogetUp.togetUp.api.mission;

import com.wakeUpTogetUp.togetUp.api.mission.objectDetection.NaverObjectDetectionService;
import com.wakeUpTogetUp.togetUp.api.mission.objectDetection.NaverAiService;
import com.wakeUpTogetUp.togetUp.api.mission.objectDetection.ObjectDetectionService;
import com.wakeUpTogetUp.togetUp.api.mission.objectDetection.dto.response.FaceRecognitionRes;
import com.wakeUpTogetUp.togetUp.api.mission.objectDetection.dto.response.FaceRecognitionRes.Face;
import com.wakeUpTogetUp.togetUp.api.mission.objectDetection.dto.response.FaceRecognitionRes.Face.EmotionValue;
import com.wakeUpTogetUp.togetUp.api.mission.objectDetection.dto.response.ObjectDetectionRes;
import com.wakeUpTogetUp.togetUp.api.room.RoomRepository;
import com.wakeUpTogetUp.togetUp.api.room.model.Room;
import com.wakeUpTogetUp.togetUp.api.mission.model.Mission;
Expand All @@ -21,52 +25,55 @@
@RequiredArgsConstructor
public class MissionService {
private final ObjectDetectionService objectDetectionService;
private final NaverObjectDetectionService naverObjectDetectionService;
private final NaverAiService naverAiService;
private final MissionRepository missionRepository;
private final MissionLogRepository missionLogRepository;
private final UserRepository userRepository;
private final RoomRepository roomRepository;

// 객체 인식
public boolean recognizeObject(String object, MultipartFile missionImage) {
// 일치 여부 확인
boolean isConsistent = false;
for(String objectDetected : naverObjectDetectionService.detectObject(missionImage)
.getPredictions().get(0)
.getDetection_names()){
ObjectDetectionRes objectDetectionRes = naverAiService.detectObject(missionImage);

if(objectDetectionRes.getPredictions().get(0).getNum_detections() == 0)
throw new BaseException(Status.MISSION_OBJECT_NOT_FOUND);

for(String objectDetected : objectDetectionRes.getPredictions().get(0).getDetection_names()){
System.out.println("objectDetected = " + objectDetected);

if (objectDetected.equals(object)) {
isConsistent = true;
break;
}
if (objectDetected.equals(object))
return true;
}

// 일치하지 않으면
if(!isConsistent)
throw new BaseException(Status.MISSION_FAILURE);
else
return isConsistent;
throw new BaseException(Status.MISSION_FAILURE);
}

public boolean recognizeObjectByModel(String object, MultipartFile missionImage) {
// 일치 여부 확인
boolean isConsistent = false;
for(String objectDetected : objectDetectionService.detectObject(missionImage)){

System.out.println("objectDetected = " + objectDetected);

if (objectDetected.equals(object)) {
isConsistent = true;
break;
}
if (objectDetected.equals(object))
return true;
}

throw new BaseException(Status.MISSION_FAILURE);
}

// 표정 인식
public boolean recognizeEmotion(String object, MultipartFile missionImage) {
FaceRecognitionRes faceRecognitionRes = naverAiService.recognizeFace(missionImage);

if(faceRecognitionRes.getInfo().getFaceCount() == 0)
throw new BaseException(Status.MISSION_OBJECT_NOT_FOUND);

for(Face face : faceRecognitionRes.getFaces()) {
System.out.println("face.getEmotion().getValue() = " + face.getEmotion().getValue());

if(face.getEmotion().getValue().equals(EmotionValue.valueOf(object)))
return true;
}

// 일치하지 않으면
if(!isConsistent)
throw new BaseException(Status.MISSION_FAILURE);
else
return isConsistent;
throw new BaseException(Status.MISSION_FAILURE);
}

// 미션 수행 기록하기
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Getter
@Setter
@NoArgsConstructor
public class MissionLogRes {
public class GetMissionLogRes {
@Schema(description = "미션 수행 기록 id")
private Integer id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PostObjectRecognitionRes {
public class PostPerformMissionRes {
private String filePath;
}
Loading

0 comments on commit 8648d27

Please sign in to comment.