Skip to content
Merged
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
@@ -0,0 +1,48 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.controller;

import java.util.List;

import jakarta.validation.Valid;

import org.springframework.http.ResponseEntity;
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;
import org.springframework.web.bind.annotation.RestController;

import com.pbl.insaroad.domain.hangulsign.dto.request.QuizCreateRequest;
import com.pbl.insaroad.domain.hangulsign.dto.response.QuizCreateResponse;
import com.pbl.insaroad.domain.hangulsign.service.HangulSignQuizService;
import com.pbl.insaroad.global.response.BaseResponse;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

@Tag(name = "HangulSignQuizAdmin", description = "한글 간판 퀴즈 관리자 API")
@RestController
@RequestMapping("/api/admin")
@RequiredArgsConstructor
public class HangulSignQuizAdminController {

private final HangulSignQuizService quizService;

@Operation(summary = "퀴즈 생성", description = "관리자가 새로운 한글 간판 퀴즈를 생성합니다.")
@PostMapping("/quizzes")
public ResponseEntity<BaseResponse<QuizCreateResponse>> createQuiz(
@Valid @RequestBody QuizCreateRequest request) {
QuizCreateResponse response = quizService.createQuiz(request);
return ResponseEntity.ok(BaseResponse.success("퀴즈 생성 성공", response));
}

@Operation(summary = "전체 퀴즈 조회", description = "관리자가 등록된 모든 퀴즈를 조회합니다.")
@GetMapping("/quizzes")
public ResponseEntity<BaseResponse<List<QuizCreateResponse>>> getAllQuizzes() {
List<QuizCreateResponse> response = quizService.getAllQuizzes();
return ResponseEntity.ok(BaseResponse.success("전체 퀴즈 조회 성공", response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.controller;

import jakarta.validation.Valid;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;

import com.pbl.insaroad.domain.hangulsign.dto.request.AnswerRequest;
import com.pbl.insaroad.domain.hangulsign.dto.response.AnswerResponse;
import com.pbl.insaroad.domain.hangulsign.dto.response.QuizResponse;
import com.pbl.insaroad.domain.hangulsign.service.HangulSignQuizService;
import com.pbl.insaroad.global.response.BaseResponse;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

@Tag(name = "HangulSignQuiz", description = "한글 간판 퀴즈 API")
@RestController
@RequestMapping("/api/hangul-sign/quizzes")
@RequiredArgsConstructor
public class HangulSignQuizController {

private final HangulSignQuizService quizService;

@Operation(summary = "랜덤 퀴즈 조회", description = "한글 간판 퀴즈를 랜덤으로 조회합니다.")
@GetMapping("/random")
public ResponseEntity<BaseResponse<QuizResponse>> getRandomQuiz() {
QuizResponse response = quizService.getRandomQuiz();
return ResponseEntity.ok(BaseResponse.success("랜덤 퀴즈 조회 성공", response));
}

@Operation(summary = "퀴즈 정답 제출", description = "사용자가 선택한 답을 제출하고 정답 여부를 확인합니다.")
@PostMapping("/{quizId}/answer")
public ResponseEntity<BaseResponse<AnswerResponse>> submitAnswer(
@PathVariable Long quizId, @Valid @RequestBody AnswerRequest request) {
AnswerResponse response = quizService.submitAnswer(quizId, request);
return ResponseEntity.ok(BaseResponse.success("정답 제출 완료", response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.dto.request;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class AnswerRequest {

@NotBlank(message = "사용자 코드는 필수입니다.")
@Schema(description = "사용자 코드 (3자리)", example = "123")
private String userCode;

@NotNull(message = "선택지는 필수입니다.") @Min(value = 1, message = "선택지는 1, 2, 3 중 하나여야 합니다.")
@Max(value = 3, message = "선택지는 1, 2, 3 중 하나여야 합니다.")
@Schema(description = "사용자가 선택한 답 (1, 2, 3)", example = "1")
private Integer userAnswer;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.dto.request;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class QuizCreateRequest {

@NotBlank(message = "문제 이미지 URL은 필수입니다.")
@Schema(description = "문제 이미지 URL", example = "https://example.com/question.jpg")
private String questionImageUrl;

@NotBlank(message = "정답 이미지 URL은 필수입니다.")
@Schema(description = "정답 이미지 URL", example = "https://example.com/answer.jpg")
private String answerImageUrl;

@NotBlank(message = "선택지 1은 필수입니다.")
@Schema(description = "선택지 1", example = "스타벅수")
private String choice1;

@NotBlank(message = "선택지 2는 필수입니다.")
@Schema(description = "선택지 2", example = "스타벅스")
private String choice2;

@NotBlank(message = "선택지 3은 필수입니다.")
@Schema(description = "선택지 3", example = "스타벜스")
private String choice3;

@NotNull(message = "정답 선택지는 필수입니다.") @Min(value = 1, message = "정답 선택지는 1, 2, 3 중 하나여야 합니다.")
@Max(value = 3, message = "정답 선택지는 1, 2, 3 중 하나여야 합니다.")
@Schema(description = "정답 선택지 번호", example = "2")
private Integer correctChoice;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AnswerResponse {

@Schema(description = "정답 여부", example = "true")
private Boolean isCorrect;

@Schema(description = "정답 이미지 URL (정답인 경우에만 제공)", example = "https://example.com/answer.jpg")
private String answerImageUrl;

@Schema(description = "현재 스테이지", example = "3")
private Integer currentStage;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class QuizCreateResponse {

@Schema(description = "문제 이미지 URL", example = "https://example.com/question.jpg")
private String questionImageUrl;

@Schema(description = "정답 이미지 URL", example = "https://example.com/answer.jpg")
private String answerImageUrl;

@Schema(description = "선택지 1", example = "김밥천국")
private String choice1;

@Schema(description = "선택지 2", example = "김밥나라")
private String choice2;

@Schema(description = "선택지 3", example = "김밥왕국")
private String choice3;

@Schema(description = "정답 선택지 번호", example = "1")
private Integer correctChoice;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class QuizResponse {

@Schema(description = "퀴즈 ID", example = "1")
private Long id;

@Schema(description = "문제 이미지 URL", example = "https://example.com/question.jpg")
private String questionImageUrl;

@Schema(description = "선택지 1", example = "김밥천국")
private String choice1;

@Schema(description = "선택지 2", example = "김밥나라")
private String choice2;

@Schema(description = "선택지 3", example = "김밥왕국")
private String choice3;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import com.pbl.insaroad.global.common.BaseTimeEntity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "hangul_sign_quizzes")
public class HangulSignQuiz extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "question_image_url", nullable = false, length = 255)
private String questionImageUrl;

@Column(name = "answer_image_url", nullable = false, length = 255)
private String answerImageUrl;

@Column(name = "choice1", nullable = false, length = 20)
private String choice1;

@Column(name = "choice2", nullable = false, length = 20)
private String choice2;

@Column(name = "choice3", nullable = false, length = 20)
private String choice3;

@Column(name = "correct_choice", nullable = false, columnDefinition = "TINYINT")
private Integer correctChoice;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) SKU PBL Team4
*/
package com.pbl.insaroad.domain.hangulsign.exception;

import org.springframework.http.HttpStatus;

import com.pbl.insaroad.global.exception.model.BaseErrorCode;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum HangulSignQuizErrorCode implements BaseErrorCode {
QUIZ_NOT_FOUND("QUIZ_4041", "퀴즈를 찾을 수 없습니다.", HttpStatus.NOT_FOUND),
USER_NOT_FOUND("QUIZ_4042", "사용자를 찾을 수 없습니다.", HttpStatus.NOT_FOUND),
INVALID_CHOICE("QUIZ_4001", "유효하지 않은 선택지입니다. (1, 2, 3 중 선택)", HttpStatus.BAD_REQUEST);

private final String code;
private final String message;
private final HttpStatus status;
}
Loading
Loading