diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/2024-2-SCS4031-4tune_2.iml b/.idea/2024-2-SCS4031-4tune_2.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/2024-2-SCS4031-4tune_2.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..033ceb7
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..0e5fb15
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..fdc392f
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..e307c8b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..1972af5
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/Eyesee.main.iml b/.idea/modules/Eyesee.main.iml
new file mode 100644
index 0000000..9a59fee
--- /dev/null
+++ b/.idea/modules/Eyesee.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/sonarlint/issuestore/2/0/20044058591931fd0315592ef1ff8f49b30c56a8 b/.idea/sonarlint/issuestore/2/0/20044058591931fd0315592ef1ff8f49b30c56a8
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/5/6/56dd6cb47a598105230d8373b803c1298611167e b/.idea/sonarlint/issuestore/5/6/56dd6cb47a598105230d8373b803c1298611167e
new file mode 100644
index 0000000..bb94f84
--- /dev/null
+++ b/.idea/sonarlint/issuestore/5/6/56dd6cb47a598105230d8373b803c1298611167e
@@ -0,0 +1,3 @@
+
+R
+java:S1068"5Remove this unused "sessionRepository" private field.(ñ”ó8»ñü¡±2
\ No newline at end of file
diff --git a/.idea/sonarlint/issuestore/6/b/6b7c031c5e32db2c4ce5b88cff90cfee6c383e7c b/.idea/sonarlint/issuestore/6/b/6b7c031c5e32db2c4ce5b88cff90cfee6c383e7c
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/6/c/6c8ab44c3fafe8176dc7da142dfd25fba5934395 b/.idea/sonarlint/issuestore/6/c/6c8ab44c3fafe8176dc7da142dfd25fba5934395
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/7/a/7a4d608efaccfd4f4468751068d2deb4bb30812a b/.idea/sonarlint/issuestore/7/a/7a4d608efaccfd4f4468751068d2deb4bb30812a
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/9/4/94dd8408f801d98d978be361720708fbbc21c4ea b/.idea/sonarlint/issuestore/9/4/94dd8408f801d98d978be361720708fbbc21c4ea
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/a/5/a53dedd8a6394e7a1ea8b78f3a6a5ffa5eb5b725 b/.idea/sonarlint/issuestore/a/5/a53dedd8a6394e7a1ea8b78f3a6a5ffa5eb5b725
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/a/e/ae75e7400ba8be4928ee309dfea9b853dfff89c1 b/.idea/sonarlint/issuestore/a/e/ae75e7400ba8be4928ee309dfea9b853dfff89c1
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/c/3/c3cd8952bb3a7af153b678349a64d1a3e6275432 b/.idea/sonarlint/issuestore/c/3/c3cd8952bb3a7af153b678349a64d1a3e6275432
new file mode 100644
index 0000000..a1917c6
--- /dev/null
+++ b/.idea/sonarlint/issuestore/c/3/c3cd8952bb3a7af153b678349a64d1a3e6275432
@@ -0,0 +1,6 @@
+
+_
+java:S6813"BRemove this field injection and use constructor injection instead.(êæÄÞ8ûÕ…¢±2
+X java:S125"
+
+
+
+
+
\ No newline at end of file
diff --git a/src/backend/Eyesee/build.gradle b/src/backend/Eyesee/build.gradle
index 0ce4d86..e846d63 100644
--- a/src/backend/Eyesee/build.gradle
+++ b/src/backend/Eyesee/build.gradle
@@ -29,6 +29,10 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.springframework.boot:spring-boot-starter-security'
+
+ // ëžœë¤ ì½”ë“œ ìƒì„±
+ implementation 'org.apache.commons:commons-lang3:3.12.0'
+
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
diff --git a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/common/response/BaseResponseCode.java b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/common/response/BaseResponseCode.java
index 214ede5..6c3a259 100644
--- a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/common/response/BaseResponseCode.java
+++ b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/common/response/BaseResponseCode.java
@@ -42,13 +42,10 @@ public enum BaseResponseCode {
// Exam Errors
NOT_FOUND_EXAM("E0001", HttpStatus.NOT_FOUND, "ì‹œí—˜ì„ ì°¾ì„ ìˆ˜ 없습니다."),
NOT_FOUND_EXAM_CODE("E0002", HttpStatus.NOT_FOUND, "시험 코드를 ì°¾ì„ ìˆ˜ 없습니다."),
-
- // Exam Errors
- EXAM_NOT_FOUND("E0001", HttpStatus.NOT_FOUND, "ì‹œí—˜ì„ ì°¾ì„ ìˆ˜ 없습니다."),
- SESSION_NOT_FOUND("E0002", HttpStatus.NOT_FOUND, "ì„¸ì…˜ì„ ì°¾ì„ ìˆ˜ 없습니다."),
- EXAM_ALREADY_EXISTS("E0003", HttpStatus.CONFLICT, "ì´ë¯¸ 존재하는 시험입니다."),
- INVALID_EXAM_STATUS("E0004", HttpStatus.BAD_REQUEST, "ìœ íš¨í•˜ì§€ ì•Šì€ ì‹œí—˜ ìƒíƒœìž…니다."),
- EXAM_ACCESS_DENIED("E0005", HttpStatus.FORBIDDEN, "ì‹œí—˜ì— ì ‘ê·¼í• ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."),
+ NOT_FOUND_SESSION("E0003", HttpStatus.NOT_FOUND, "ì„¸ì…˜ì„ ì°¾ì„ ìˆ˜ 없습니다."),
+ EXAM_ALREADY_EXISTS("E0004", HttpStatus.CONFLICT, "ì´ë¯¸ 존재하는 시험입니다."),
+ INVALID_EXAM_STATUS("E0005", HttpStatus.BAD_REQUEST, "ìœ íš¨í•˜ì§€ ì•Šì€ ì‹œí—˜ ìƒíƒœìž…니다."),
+ EXAM_ACCESS_DENIED("E0006", HttpStatus.FORBIDDEN, "ì‹œí—˜ì— ì ‘ê·¼í• ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."),
// 기타 추가 오류 코드 ...
diff --git a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/controller/ExamController.java b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/controller/ExamController.java
index efb1291..4aaefeb 100644
--- a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/controller/ExamController.java
+++ b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/controller/ExamController.java
@@ -3,10 +3,7 @@
import com.fortune.eyesee.common.exception.BaseException;
import com.fortune.eyesee.common.response.BaseResponse;
import com.fortune.eyesee.common.response.BaseResponseCode;
-import com.fortune.eyesee.dto.ExamCodeRequestDTO;
-import com.fortune.eyesee.dto.ExamResponseDTO;
-import com.fortune.eyesee.dto.UserDetailResponseDTO;
-import com.fortune.eyesee.dto.UserListResponseDTO;
+import com.fortune.eyesee.dto.*;
import com.fortune.eyesee.enums.ExamStatus;
import com.fortune.eyesee.service.ExamService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -15,7 +12,10 @@
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpSession;
+
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@RestController
@RequestMapping("/api/exams")
@@ -58,6 +58,35 @@ public class ExamController {
// return ResponseEntity.ok(new BaseResponse<>(examList));
// }
+ // 시험 등ë¡
+// @PostMapping
+// public ResponseEntity> registerExam(@RequestBody ExamRequestDTO examRequestDTO, HttpSession session) {
+// Integer adminId = (Integer) session.getAttribute("adminId");
+// if (adminId == null) {
+// // 로그ì¸ë˜ì§€ ì•Šì€ ê²½ìš° 예외처리
+// throw new BaseException(BaseResponseCode.UNAUTHORIZED);
+// }
+//
+// // 시험 ìƒì„± ë° ëžœë¤ ì½”ë“œ ìƒì„±
+// ExamResponseDTO response = examService.registerExam(adminId, examRequestDTO);
+// return ResponseEntity.ok(new BaseResponse<>(response, "시험 등ë¡ì— 성공했습니다."));
+// }
+ @PostMapping
+ public ResponseEntity>> registerExam(@RequestBody ExamRequestDTO examRequestDTO, HttpSession session) {
+ Integer adminId = (Integer) session.getAttribute("adminId");
+ if (adminId == null) {
+ throw new BaseException(BaseResponseCode.UNAUTHORIZED);
+ }
+
+ ExamResponseDTO response = examService.registerExam(adminId, examRequestDTO);
+
+ // examRandomCode만 í¬í•¨ëœ ì‘답 ìƒì„±
+ Map responseData = new HashMap<>();
+ responseData.put("examRandomCode", response.getExamRandomCode());
+
+ return ResponseEntity.ok(new BaseResponse<>(responseData, "시험 등ë¡ì— 성공했습니다."));
+ }
+
// "before" ìƒíƒœì˜ Exam 리스트 조회
@GetMapping("/before")
public ResponseEntity>> getBeforeExams() {
@@ -127,4 +156,4 @@ public ResponseEntity> getUserDetailByExamId
UserDetailResponseDTO response = examService.getUserDetailByExamIdAndUserId(examId, userId);
return ResponseEntity.ok(new BaseResponse<>(response, "í•™ìƒ ìƒì„¸ ì •ë³´ 조회 성공"));
}
-}
+}
\ No newline at end of file
diff --git a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/controller/SessionController.java b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/controller/SessionController.java
new file mode 100644
index 0000000..2c7adaf
--- /dev/null
+++ b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/controller/SessionController.java
@@ -0,0 +1,35 @@
+package com.fortune.eyesee.controller;
+
+import com.fortune.eyesee.common.response.BaseResponse;
+import com.fortune.eyesee.dto.ExamCodeRequestDTO;
+import com.fortune.eyesee.dto.UserInfoRequestDTO;
+import com.fortune.eyesee.service.SessionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api/sessions")
+public class SessionController {
+
+ private final SessionService sessionService;
+
+ @Autowired
+ public SessionController(SessionService sessionService) {
+ this.sessionService = sessionService;
+ }
+
+ // 시험 세션 입장
+ @PostMapping("/join")
+ public ResponseEntity> joinExam(@RequestBody ExamCodeRequestDTO examCodeRequestDTO) {
+ sessionService.joinExamSession(examCodeRequestDTO.getExamCode());
+ return ResponseEntity.ok(new BaseResponse<>("시험 세션 ìž…ìž¥ì— ì„±ê³µí–ˆìŠµë‹ˆë‹¤."));
+ }
+
+ // ì‚¬ìš©ìž ì •ë³´ ìž…ë ¥
+ @PostMapping("/student")
+ public ResponseEntity> addUserInfo(@RequestBody UserInfoRequestDTO userInfoRequestDTO) {
+ sessionService.addUserInfo(userInfoRequestDTO);
+ return ResponseEntity.ok(new BaseResponse<>("ì‚¬ìš©ìž ì •ë³´ ìž…ë ¥ì— ì„±ê³µí–ˆìŠµë‹ˆë‹¤."));
+ }
+}
\ No newline at end of file
diff --git a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/dto/ExamRequestDTO.java b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/dto/ExamRequestDTO.java
new file mode 100644
index 0000000..8888337
--- /dev/null
+++ b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/dto/ExamRequestDTO.java
@@ -0,0 +1,20 @@
+package com.fortune.eyesee.dto;
+
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+
+@Data
+public class ExamRequestDTO {
+ private String examName;
+ private String examSemester;
+ private Integer examStudentNumber;
+ private String examLocation;
+ private LocalDate examDate;
+ private LocalTime examStartTime;
+ private Integer examDuration;
+ private Integer examQuestionNumber;
+ private Integer examTotalScore;
+ private String examNotice;
+}
\ No newline at end of file
diff --git a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/dto/UserInfoRequestDTO.java b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/dto/UserInfoRequestDTO.java
new file mode 100644
index 0000000..2536b2c
--- /dev/null
+++ b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/dto/UserInfoRequestDTO.java
@@ -0,0 +1,12 @@
+
+package com.fortune.eyesee.dto;
+
+import lombok.Data;
+
+@Data
+public class UserInfoRequestDTO {
+ private String name; // ì‚¬ìš©ìž ì´ë¦„
+ private String department; // 학과
+ private Integer userNum; // 학번
+ private Integer seatNum; // ì¢Œì„ ë²ˆí˜¸
+}
diff --git a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/service/ExamService.java b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/service/ExamService.java
index cd80265..012a7a6 100644
--- a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/service/ExamService.java
+++ b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/service/ExamService.java
@@ -2,12 +2,14 @@
import com.fortune.eyesee.common.exception.BaseException;
import com.fortune.eyesee.common.response.BaseResponseCode;
+import com.fortune.eyesee.dto.ExamRequestDTO;
import com.fortune.eyesee.dto.ExamResponseDTO;
import com.fortune.eyesee.dto.UserDetailResponseDTO;
import com.fortune.eyesee.dto.UserListResponseDTO;
import com.fortune.eyesee.entity.*;
import com.fortune.eyesee.enums.ExamStatus;
import com.fortune.eyesee.repository.*;
+import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -26,6 +28,7 @@ public class ExamService {
private final VideoRecordingRepository videoRecordingRepository;
private final DetectedCheatingRepository detectedCheatingRepository;
private final CheatingTypeRepository cheatingTypeRepository;
+ private final AdminRepository adminRepository;
@Autowired
public ExamService(ExamRepository examRepository,
@@ -34,7 +37,7 @@ public ExamService(ExamRepository examRepository,
CheatingStatisticsRepository cheatingStatisticsRepository,
VideoRecordingRepository videoRecordingRepository,
DetectedCheatingRepository detectedCheatingRepository,
- CheatingTypeRepository cheatingTypeRepository) {
+ CheatingTypeRepository cheatingTypeRepository, AdminRepository adminRepository) {
this.examRepository = examRepository;
this.userRepository = userRepository;
this.sessionRepository = sessionRepository;
@@ -42,6 +45,55 @@ public ExamService(ExamRepository examRepository,
this.videoRecordingRepository = videoRecordingRepository;
this.detectedCheatingRepository = detectedCheatingRepository;
this.cheatingTypeRepository = cheatingTypeRepository;
+ this.adminRepository = adminRepository;
+ }
+ // 시험 ë“±ë¡ ë©”ì„œë“œ
+ public ExamResponseDTO registerExam(Integer adminId, ExamRequestDTO examRequestDTO) {
+ Admin admin = adminRepository.findById(adminId)
+ .orElseThrow(() -> new BaseException(BaseResponseCode.UNAUTHORIZED));
+
+ // 10ìžë¦¬ ëžœë¤ ì˜ìˆ«ìž 코드 ìƒì„±
+ String examRandomCode = RandomStringUtils.randomAlphanumeric(10);
+
+ // Exam ìƒì„±
+ Exam exam = new Exam();
+ exam.setAdmin(admin);
+ exam.setExamName(examRequestDTO.getExamName());
+ exam.setExamSemester(examRequestDTO.getExamSemester());
+ exam.setExamStudentNumber(examRequestDTO.getExamStudentNumber());
+ exam.setExamLocation(examRequestDTO.getExamLocation());
+ exam.setExamDate(examRequestDTO.getExamDate());
+ exam.setExamStartTime(examRequestDTO.getExamStartTime());
+ exam.setExamDuration(examRequestDTO.getExamDuration());
+ exam.setExamQuestionNumber(examRequestDTO.getExamQuestionNumber());
+ exam.setExamTotalScore(examRequestDTO.getExamTotalScore());
+ exam.setExamNotice(examRequestDTO.getExamNotice());
+ exam.setExamStatus(ExamStatus.BEFORE);
+ exam.setExamRandomCode(examRandomCode);
+
+ // Exam ì €ìž¥ 후 ID ìƒì„±
+ examRepository.save(exam);
+
+ // ExamId를 사용해 Session ìƒì„± ë° ì„¤ì •
+ Session session = new Session();
+ session.setSessionId(exam.getExamId()); // ExamId와 ë™ì¼í•˜ê²Œ ì„¤ì •
+ session.setExam(exam);
+ sessionRepository.save(session);
+
+ return new ExamResponseDTO(
+ exam.getExamId(),
+ exam.getExamName(),
+ exam.getExamSemester(),
+ exam.getExamStudentNumber(),
+ exam.getExamLocation(),
+ exam.getExamDate(),
+ exam.getExamStartTime(),
+ exam.getExamDuration(),
+ exam.getExamStatus(),
+ exam.getExamNotice(),
+ session.getSessionId(),
+ exam.getExamRandomCode()
+ );
}
// íŠ¹ì • 시험 IDë¡œ 존재 여부 확ì¸
diff --git a/src/backend/Eyesee/src/main/java/com/fortune/eyesee/service/SessionService.java b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/service/SessionService.java
new file mode 100644
index 0000000..ae40e62
--- /dev/null
+++ b/src/backend/Eyesee/src/main/java/com/fortune/eyesee/service/SessionService.java
@@ -0,0 +1,50 @@
+package com.fortune.eyesee.service;
+
+import com.fortune.eyesee.common.exception.BaseException;
+import com.fortune.eyesee.common.response.BaseResponseCode;
+import com.fortune.eyesee.dto.ExamCodeRequestDTO;
+import com.fortune.eyesee.dto.UserInfoRequestDTO;
+import com.fortune.eyesee.entity.Exam;
+import com.fortune.eyesee.entity.User;
+import com.fortune.eyesee.repository.ExamRepository;
+import com.fortune.eyesee.repository.UserRepository;
+import com.fortune.eyesee.repository.SessionRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SessionService {
+
+ private final ExamRepository examRepository;
+ private final UserRepository userRepository;
+ private final SessionRepository sessionRepository;
+
+ @Autowired
+ public SessionService(ExamRepository examRepository, UserRepository userRepository, SessionRepository sessionRepository) {
+ this.examRepository = examRepository;
+ this.userRepository = userRepository;
+ this.sessionRepository = sessionRepository;
+ }
+
+ public boolean joinExamSession(String examCode) {
+ Exam exam = examRepository.findByExamRandomCode(examCode);
+ if (exam == null) {
+ throw new BaseException(BaseResponseCode.NOT_FOUND_EXAM_CODE);
+ }
+ if (exam.getSession() == null) {
+ throw new BaseException(BaseResponseCode.NOT_FOUND_SESSION);
+ }
+ return true;
+ }
+
+ // ì‚¬ìš©ìž ì •ë³´ ì €ìž¥
+ public void addUserInfo(UserInfoRequestDTO userInfoRequestDTO) {
+ User user = new User();
+ user.setUserName(userInfoRequestDTO.getName());
+ user.setDepartment(userInfoRequestDTO.getDepartment());
+ user.setUserNum(userInfoRequestDTO.getUserNum());
+ user.setSeatNum(userInfoRequestDTO.getSeatNum());
+
+ userRepository.save(user);
+ }
+}
\ No newline at end of file