cslms-api/internal/controllers/paper.go

427 lines
10 KiB
Go

package controllers
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"time"
"learnsteam/cslms-api/internal/models"
"learnsteam/cslms-api/internal/services"
"github.com/gin-gonic/gin"
"github.com/google/go-cmp/cmp"
"gorm.io/datatypes"
)
type PaperController interface {
List(*gin.Context)
Find(*gin.Context)
Start(*gin.Context)
Finish(*gin.Context)
QuizList(*gin.Context)
QuizFind(*gin.Context)
QuizAnswer(*gin.Context)
}
type paperController struct {
service services.PaperService
paperQuizService services.PaperQuizService
userService services.UserService
quizService services.QuizService
quizPaperService services.QuizPaperService
userQuizService services.UserQuizService
}
func NewPaperController(
service services.PaperService,
paperQuizService services.PaperQuizService,
quizService services.QuizService,
quizPaperService services.QuizPaperService,
userService services.UserService,
userQuizServie services.UserQuizService,
) PaperController {
return &paperController{
service: service,
paperQuizService: paperQuizService,
userService: userService,
quizService: quizService,
quizPaperService: quizPaperService,
userQuizService: userQuizServie,
}
}
// Paper List
//
// @Summary 목록 가져오기
// @Description 목록을 가져옵니다.
// @Tags 페이퍼
//
// @Accept json
// @Produce json
//
// @Security Bearer
//
// @Param q query string false "검색어"
// @Param page query int false "페이지"
// @Param limit query int false "페이지 사이즈"
//
// @Success 200 {object} models.PaperListResponse
// @Router /paper [get]
func (controller *paperController) List(c *gin.Context) {
q := c.DefaultQuery("q", "")
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user_id := c.GetInt64("sub")
result, err := controller.service.List(user_id, q, page, limit)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
totalNumber, err := controller.service.Total(user_id, q)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
totalPage := int64(totalNumber/int64(limit) + 1)
response := models.PaperListResponse{
Data: *result,
Total: totalNumber,
Page: page,
TotalPage: totalPage,
PageSize: limit,
}
c.JSON(http.StatusOK, response)
}
// Get paper
//
// @Summary 페이퍼 정보 가져오기
// @Description ID로 페이퍼 정보를 가져옵니다.
// @Tags 페이퍼
//
// @Accept json
// @Produce json
//
// @Security Bearer
//
// @Param paper_id path int64 true "Paper ID"
//
// @Success 200 {object} models.PaperResponse
// @Router /paper/{paper_id} [get]
func (controller *paperController) Find(c *gin.Context) {
paper_id, err := strconv.ParseInt(c.Param("paper_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := controller.service.Find(paper_id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// Start Paper
//
// @Summary 퀴즈 시작
// @Description 퀴즈 시작합니다.
// @Tags 페이퍼
//
// @Accept json
// @Produce json
//
// @Security Bearer
//
// @Param paper_id path int64 true "Paper ID"
//
// @Success 200 {object} models.Paper
// @Router /paper/{paper_id}/start [patch]
func (controller *paperController) Start(c *gin.Context) {
paper_id, err := strconv.ParseInt(c.Param("paper_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
paper, err := controller.service.Get(paper_id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if paper.Status != "ready" {
c.JSON(http.StatusBadRequest, gin.H{"error": "퀴즈를 시작할 수 없습니다."})
return
}
now := time.Now()
paper.Status = "start"
paper.StartAt = &now
result, err := controller.service.Update(paper)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// Finish Paper
//
// @Summary 퀴즈 종료
// @Description 퀴즈 종료합니다.
// @Tags 페이퍼
//
// @Accept json
// @Produce json
//
// @Security Bearer
//
// @Param paper_id path int64 true "Paper ID"
//
// @Success 200 {object} models.Paper
// @Router /paper/{paper_id}/finish [patch]
func (controller *paperController) Finish(c *gin.Context) {
paper_id, err := strconv.ParseInt(c.Param("paper_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
paper, err := controller.service.Get(paper_id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if paper.Status != "start" {
c.JSON(http.StatusBadRequest, gin.H{"error": "퀴즈를 종료할 수 없습니다."})
return
}
now := time.Now()
paper.Status = "done"
paper.DoneAt = &now
result, err := controller.service.Update(paper)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// Quiz List
//
// @Summary 퀴즈페이퍼 퀴즈 목록 가져오기
// @Description 퀴즈페이퍼 퀴즈 목록을 가져옵니다.
// @Tags 페이퍼
//
// @Accept json
// @Produce json
//
// @Security Bearer
//
// @Param paper_id path int64 true "퀴즈페이퍼 ID"
// @Param page query int false "페이지"
// @Param limit query int false "페이지 사이즈"
//
// @Success 200 {object} models.PaperQuizListResponse
// @Router /paper/{paper_id}/quiz [get]
func (controller *paperController) QuizList(c *gin.Context) {
paper_id, err := strconv.ParseInt(c.Param("paper_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
if err != nil {
fmt.Println("error : page")
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
if err != nil {
fmt.Println("error : limit")
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := controller.paperQuizService.List(paper_id, page, limit)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
totalNumber, err := controller.paperQuizService.Total(paper_id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
totalPage := int64(totalNumber/int64(limit) + 1)
c.JSON(http.StatusOK, gin.H{"data": result, "total": totalNumber, "page": page, "totalPage": totalPage, "pageSize": limit})
}
// Get Quiz
//
// @Summary 퀴즈페이퍼 퀴즈 가져오기
// @Description ID로 퀴즈를 가져옵니다.
// @Tags 페이퍼
//
// @Accept json
// @Produce json
//
// @Security Bearer
//
// @Param paper_id path string true "Paper ID"
// @Param quiz_id path string true "사용자퀴즈 ID"
//
// @Success 200 {object} models.PaperQuizResponse
// @Router /paper/{paper_id}/quiz/{quiz_id} [get]
func (controller *paperController) QuizFind(c *gin.Context) {
paper_id, err := strconv.ParseInt(c.Param("paper_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
quiz_id, err := strconv.ParseInt(c.Param("quiz_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := controller.paperQuizService.Find(quiz_id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if paper_id != result.UserQuizPaperID {
c.JSON(http.StatusBadRequest, gin.H{"error": "퀴즈시트와 퀴즈가 일치하지 않습니다."})
return
}
c.JSON(http.StatusOK, result)
}
// Answer Quiz
//
// @Summary 퀴즈 답변
// @Description 퀴즈 답변을 제출합니다..
// @Tags 페이퍼
//
// @Accept json
// @Produce json
//
// @Security Bearer
//
// @Param paper_id path int64 true "Paper ID"
// @Param quiz_id path int64 true "Quiz ID"
// @Param quizBody body models.AnswerQuizRequest true "Answer Body"
//
// @Router /paper/{paper_id}/quiz/{quiz_id}/answer [patch]
func (controller *paperController) QuizAnswer(c *gin.Context) {
paper_id, err := strconv.ParseInt(c.Param("paper_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
id, err := strconv.ParseInt(c.Param("quiz_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var request models.AnswerQuizRequest
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
userquiz, err := controller.userQuizService.Find(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if paper_id != userquiz.UserQuizPaperID {
c.JSON(http.StatusBadRequest, gin.H{"error": "퀴즈시트와 퀴즈가 일치하지 않습니다."})
return
}
user_id := c.GetInt64("sub")
if user_id != userquiz.UserID {
c.JSON(http.StatusBadRequest, gin.H{"error": "Wrong user"})
return
}
if userquiz.Status != "ready" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Answered"})
return
}
quiz, err := controller.quizService.Find(userquiz.QuizID)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var userAnswer datatypes.JSON
userAnswer, err = json.Marshal(request.Answer)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
isCorrect := cmp.Equal(quiz.Answer.String(), userAnswer.String())
var score float32 = 0.0
var correction string = "fail"
if isCorrect {
score = 1.0
correction = "success"
}
userquiz.Answer = userAnswer
userquiz.Status = "done"
userquiz.Result = correction
userquiz.Score = score
_, err = controller.userQuizService.Update(userquiz)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
_, err = controller.service.UpdateScore(userquiz.UserQuizPaperID)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "success"})
}