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"}) }