diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4a3848d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // IntelliSense를 사용하여 가능한 특성에 대해 알아보세요. + // 기존 특성에 대한 설명을 보려면 가리킵니다. + // 자세한 내용을 보려면 https://go.microsoft.com/fwlink/?linkid=830387을(를) 방문하세요. + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${fileDirname}" + } + ] +} \ No newline at end of file diff --git a/docs/docs.go b/docs/docs.go index 64e92e9..b2dcf40 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -273,6 +273,304 @@ const docTemplate = `{ } } }, + "/paper": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "목록을 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "목록 가져오기", + "parameters": [ + { + "type": "string", + "description": "검색어", + "name": "q", + "in": "query" + }, + { + "type": "integer", + "description": "페이지", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "페이지 사이즈", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.PaperListResponse" + } + } + } + } + }, + "/paper/{paper_id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "ID로 페이퍼 정보를 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "페이퍼 정보 가져오기", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.PaperResponse" + } + } + } + } + }, + "/paper/{paper_id}/finish": { + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈 종료합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈 종료", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.Paper" + } + } + } + } + }, + "/paper/{paper_id}/quiz": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈페이퍼 퀴즈 목록을 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈페이퍼 퀴즈 목록 가져오기", + "parameters": [ + { + "type": "integer", + "description": "퀴즈페이퍼 ID", + "name": "paper_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "페이지", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "페이지 사이즈", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.UserQuizListResponse" + } + } + } + } + }, + "/paper/{paper_id}/quiz/{quiz_id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "ID로 퀴즈를 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈페이퍼 퀴즈 가져오기", + "parameters": [ + { + "type": "string", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "사용자퀴즈 ID", + "name": "quiz_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.UserQuizResponse" + } + } + } + } + }, + "/paper/{paper_id}/quiz/{quiz_id}/answer": { + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈 답변을 제출합니다..", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈 답변", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Quiz ID", + "name": "quiz_id", + "in": "path", + "required": true + }, + { + "description": "Answer Body", + "name": "quizBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.AnswerQuizRequest" + } + } + ], + "responses": {} + } + }, + "/paper/{paper_id}/start": { + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈 시작합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈 시작", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.Paper" + } + } + } + } + }, "/quiz": { "get": { "security": [ @@ -982,6 +1280,43 @@ const docTemplate = `{ } } } + }, + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "사용자퀴즈 답변을 제출합니다..", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "사용자퀴즈" + ], + "summary": "사용자퀴즈 답변", + "parameters": [ + { + "type": "integer", + "description": "Quiz ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Answer Body", + "name": "quizBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.AnswerQuizRequest" + } + } + ], + "responses": {} } }, "/userquizpaper": { @@ -1199,6 +1534,21 @@ const docTemplate = `{ } }, "definitions": { + "learnsteam_cslms-api_internal_models.AnswerQuizRequest": { + "type": "object", + "properties": { + "answer": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "option1", + "option4" + ] + } + } + }, "learnsteam_cslms-api_internal_models.Center": { "type": "object", "properties": { @@ -1329,6 +1679,138 @@ const docTemplate = `{ } } }, + "learnsteam_cslms-api_internal_models.Paper": { + "type": "object", + "properties": { + "center_id": { + "type": "integer", + "example": 1000015 + }, + "done_at": { + "type": "string" + }, + "guid_id": { + "type": "string", + "example": "7f9329f5-2e36-4638-92d2-73064b7291a4" + }, + "id": { + "type": "integer", + "example": 1000015 + }, + "quiz_paper_id": { + "type": "integer", + "example": 1000001 + }, + "start_at": { + "type": "string" + }, + "status": { + "type": "string", + "example": "wating" + }, + "total_score": { + "type": "number", + "example": 100 + }, + "user_id": { + "type": "integer", + "example": 1000002 + }, + "user_score": { + "type": "number", + "example": 5 + } + } + }, + "learnsteam_cslms-api_internal_models.PaperListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.PaperResponse" + } + }, + "page": { + "type": "integer", + "example": 1 + }, + "pageSize": { + "type": "integer", + "example": 10 + }, + "total": { + "type": "integer", + "example": 999 + }, + "totalPage": { + "type": "integer", + "example": 99 + } + } + }, + "learnsteam_cslms-api_internal_models.PaperResponse": { + "type": "object", + "properties": { + "category": { + "type": "string", + "example": "파이썬기본" + }, + "center_id": { + "type": "integer", + "example": 1000015 + }, + "created_at": { + "type": "string" + }, + "done_at": { + "type": "string" + }, + "first_name": { + "type": "string", + "example": "길순" + }, + "guid_id": { + "type": "string", + "example": "7f9329f5-2e36-4638-92d2-73064b7291a4" + }, + "id": { + "type": "integer", + "example": 1000015 + }, + "last_name": { + "type": "string", + "example": "홍" + }, + "quiz_paper_id": { + "type": "integer", + "example": 1000001 + }, + "start_at": { + "type": "string" + }, + "status": { + "type": "string", + "example": "wating" + }, + "title": { + "type": "string", + "example": "출력 Print" + }, + "total_score": { + "type": "number", + "example": 100 + }, + "user_id": { + "type": "integer", + "example": 1000002 + }, + "user_score": { + "type": "number", + "example": 5 + } + } + }, "learnsteam_cslms-api_internal_models.Quiz": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 8c7218c..a03fa05 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -265,6 +265,304 @@ } } }, + "/paper": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "목록을 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "목록 가져오기", + "parameters": [ + { + "type": "string", + "description": "검색어", + "name": "q", + "in": "query" + }, + { + "type": "integer", + "description": "페이지", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "페이지 사이즈", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.PaperListResponse" + } + } + } + } + }, + "/paper/{paper_id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "ID로 페이퍼 정보를 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "페이퍼 정보 가져오기", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.PaperResponse" + } + } + } + } + }, + "/paper/{paper_id}/finish": { + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈 종료합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈 종료", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.Paper" + } + } + } + } + }, + "/paper/{paper_id}/quiz": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈페이퍼 퀴즈 목록을 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈페이퍼 퀴즈 목록 가져오기", + "parameters": [ + { + "type": "integer", + "description": "퀴즈페이퍼 ID", + "name": "paper_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "페이지", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "페이지 사이즈", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.UserQuizListResponse" + } + } + } + } + }, + "/paper/{paper_id}/quiz/{quiz_id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "ID로 퀴즈를 가져옵니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈페이퍼 퀴즈 가져오기", + "parameters": [ + { + "type": "string", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "사용자퀴즈 ID", + "name": "quiz_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.UserQuizResponse" + } + } + } + } + }, + "/paper/{paper_id}/quiz/{quiz_id}/answer": { + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈 답변을 제출합니다..", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈 답변", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Quiz ID", + "name": "quiz_id", + "in": "path", + "required": true + }, + { + "description": "Answer Body", + "name": "quizBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.AnswerQuizRequest" + } + } + ], + "responses": {} + } + }, + "/paper/{paper_id}/start": { + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "퀴즈 시작합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "페이퍼" + ], + "summary": "퀴즈 시작", + "parameters": [ + { + "type": "integer", + "description": "Paper ID", + "name": "paper_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.Paper" + } + } + } + } + }, "/quiz": { "get": { "security": [ @@ -974,6 +1272,43 @@ } } } + }, + "patch": { + "security": [ + { + "Bearer": [] + } + ], + "description": "사용자퀴즈 답변을 제출합니다..", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "사용자퀴즈" + ], + "summary": "사용자퀴즈 답변", + "parameters": [ + { + "type": "integer", + "description": "Quiz ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Answer Body", + "name": "quizBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.AnswerQuizRequest" + } + } + ], + "responses": {} } }, "/userquizpaper": { @@ -1191,6 +1526,21 @@ } }, "definitions": { + "learnsteam_cslms-api_internal_models.AnswerQuizRequest": { + "type": "object", + "properties": { + "answer": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "option1", + "option4" + ] + } + } + }, "learnsteam_cslms-api_internal_models.Center": { "type": "object", "properties": { @@ -1321,6 +1671,138 @@ } } }, + "learnsteam_cslms-api_internal_models.Paper": { + "type": "object", + "properties": { + "center_id": { + "type": "integer", + "example": 1000015 + }, + "done_at": { + "type": "string" + }, + "guid_id": { + "type": "string", + "example": "7f9329f5-2e36-4638-92d2-73064b7291a4" + }, + "id": { + "type": "integer", + "example": 1000015 + }, + "quiz_paper_id": { + "type": "integer", + "example": 1000001 + }, + "start_at": { + "type": "string" + }, + "status": { + "type": "string", + "example": "wating" + }, + "total_score": { + "type": "number", + "example": 100 + }, + "user_id": { + "type": "integer", + "example": 1000002 + }, + "user_score": { + "type": "number", + "example": 5 + } + } + }, + "learnsteam_cslms-api_internal_models.PaperListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/learnsteam_cslms-api_internal_models.PaperResponse" + } + }, + "page": { + "type": "integer", + "example": 1 + }, + "pageSize": { + "type": "integer", + "example": 10 + }, + "total": { + "type": "integer", + "example": 999 + }, + "totalPage": { + "type": "integer", + "example": 99 + } + } + }, + "learnsteam_cslms-api_internal_models.PaperResponse": { + "type": "object", + "properties": { + "category": { + "type": "string", + "example": "파이썬기본" + }, + "center_id": { + "type": "integer", + "example": 1000015 + }, + "created_at": { + "type": "string" + }, + "done_at": { + "type": "string" + }, + "first_name": { + "type": "string", + "example": "길순" + }, + "guid_id": { + "type": "string", + "example": "7f9329f5-2e36-4638-92d2-73064b7291a4" + }, + "id": { + "type": "integer", + "example": 1000015 + }, + "last_name": { + "type": "string", + "example": "홍" + }, + "quiz_paper_id": { + "type": "integer", + "example": 1000001 + }, + "start_at": { + "type": "string" + }, + "status": { + "type": "string", + "example": "wating" + }, + "title": { + "type": "string", + "example": "출력 Print" + }, + "total_score": { + "type": "number", + "example": 100 + }, + "user_id": { + "type": "integer", + "example": 1000002 + }, + "user_score": { + "type": "number", + "example": 5 + } + } + }, "learnsteam_cslms-api_internal_models.Quiz": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 6430072..028cb45 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,4 +1,14 @@ definitions: + learnsteam_cslms-api_internal_models.AnswerQuizRequest: + properties: + answer: + example: + - option1 + - option4 + items: + type: string + type: array + type: object learnsteam_cslms-api_internal_models.Center: properties: center_name: @@ -92,6 +102,101 @@ definitions: user: $ref: '#/definitions/learnsteam_cslms-api_internal_models.User' type: object + learnsteam_cslms-api_internal_models.Paper: + properties: + center_id: + example: 1000015 + type: integer + done_at: + type: string + guid_id: + example: 7f9329f5-2e36-4638-92d2-73064b7291a4 + type: string + id: + example: 1000015 + type: integer + quiz_paper_id: + example: 1000001 + type: integer + start_at: + type: string + status: + example: wating + type: string + total_score: + example: 100 + type: number + user_id: + example: 1000002 + type: integer + user_score: + example: 5 + type: number + type: object + learnsteam_cslms-api_internal_models.PaperListResponse: + properties: + data: + items: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.PaperResponse' + type: array + page: + example: 1 + type: integer + pageSize: + example: 10 + type: integer + total: + example: 999 + type: integer + totalPage: + example: 99 + type: integer + type: object + learnsteam_cslms-api_internal_models.PaperResponse: + properties: + category: + example: 파이썬기본 + type: string + center_id: + example: 1000015 + type: integer + created_at: + type: string + done_at: + type: string + first_name: + example: 길순 + type: string + guid_id: + example: 7f9329f5-2e36-4638-92d2-73064b7291a4 + type: string + id: + example: 1000015 + type: integer + last_name: + example: 홍 + type: string + quiz_paper_id: + example: 1000001 + type: integer + start_at: + type: string + status: + example: wating + type: string + title: + example: 출력 Print + type: string + total_score: + example: 100 + type: number + user_id: + example: 1000002 + type: integer + user_score: + example: 5 + type: number + type: object learnsteam_cslms-api_internal_models.Quiz: properties: answer: @@ -886,6 +991,194 @@ paths: summary: 센터 수정 tags: - 센터 + /paper: + get: + consumes: + - application/json + description: 목록을 가져옵니다. + parameters: + - description: 검색어 + in: query + name: q + type: string + - description: 페이지 + in: query + name: page + type: integer + - description: 페이지 사이즈 + in: query + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.PaperListResponse' + security: + - Bearer: [] + summary: 목록 가져오기 + tags: + - 페이퍼 + /paper/{paper_id}: + get: + consumes: + - application/json + description: ID로 페이퍼 정보를 가져옵니다. + parameters: + - description: Paper ID + in: path + name: paper_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.PaperResponse' + security: + - Bearer: [] + summary: 페이퍼 정보 가져오기 + tags: + - 페이퍼 + /paper/{paper_id}/finish: + patch: + consumes: + - application/json + description: 퀴즈 종료합니다. + parameters: + - description: Paper ID + in: path + name: paper_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.Paper' + security: + - Bearer: [] + summary: 퀴즈 종료 + tags: + - 페이퍼 + /paper/{paper_id}/quiz: + get: + consumes: + - application/json + description: 퀴즈페이퍼 퀴즈 목록을 가져옵니다. + parameters: + - description: 퀴즈페이퍼 ID + in: path + name: paper_id + required: true + type: integer + - description: 페이지 + in: query + name: page + type: integer + - description: 페이지 사이즈 + in: query + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.UserQuizListResponse' + security: + - Bearer: [] + summary: 퀴즈페이퍼 퀴즈 목록 가져오기 + tags: + - 페이퍼 + /paper/{paper_id}/quiz/{quiz_id}: + get: + consumes: + - application/json + description: ID로 퀴즈를 가져옵니다. + parameters: + - description: Paper ID + in: path + name: paper_id + required: true + type: string + - description: 사용자퀴즈 ID + in: path + name: quiz_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.UserQuizResponse' + security: + - Bearer: [] + summary: 퀴즈페이퍼 퀴즈 가져오기 + tags: + - 페이퍼 + /paper/{paper_id}/quiz/{quiz_id}/answer: + patch: + consumes: + - application/json + description: 퀴즈 답변을 제출합니다.. + parameters: + - description: Paper ID + in: path + name: paper_id + required: true + type: integer + - description: Quiz ID + in: path + name: quiz_id + required: true + type: integer + - description: Answer Body + in: body + name: quizBody + required: true + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.AnswerQuizRequest' + produces: + - application/json + responses: {} + security: + - Bearer: [] + summary: 퀴즈 답변 + tags: + - 페이퍼 + /paper/{paper_id}/start: + patch: + consumes: + - application/json + description: 퀴즈 시작합니다. + parameters: + - description: Paper ID + in: path + name: paper_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.Paper' + security: + - Bearer: [] + summary: 퀴즈 시작 + tags: + - 페이퍼 /quiz: get: consumes: @@ -1306,6 +1599,30 @@ paths: summary: 사용자퀴즈 가져오기 tags: - 사용자퀴즈 + patch: + consumes: + - application/json + description: 사용자퀴즈 답변을 제출합니다.. + parameters: + - description: Quiz ID + in: path + name: id + required: true + type: integer + - description: Answer Body + in: body + name: quizBody + required: true + schema: + $ref: '#/definitions/learnsteam_cslms-api_internal_models.AnswerQuizRequest' + produces: + - application/json + responses: {} + security: + - Bearer: [] + summary: 사용자퀴즈 답변 + tags: + - 사용자퀴즈 put: consumes: - application/json diff --git a/go.mod b/go.mod index a43b386..733851a 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,17 @@ module learnsteam/cslms-api -go 1.21 +go 1.22 require ( github.com/apex/gateway v1.1.2 github.com/gin-contrib/cors v1.4.0 github.com/golang-jwt/jwt/v5 v5.1.0 + github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.4.0 github.com/stretchr/testify v1.8.4 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 + github.com/swaggo/swag v1.16.2 golang.org/x/crypto v0.15.0 gorm.io/datatypes v1.2.0 gorm.io/driver/mysql v1.5.2 @@ -34,7 +36,6 @@ require ( github.com/go-playground/validator/v10 v10.16.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -48,7 +49,6 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/swaggo/swag v1.16.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect golang.org/x/arch v0.6.0 // indirect diff --git a/go.sum b/go.sum index 1bd1196..00862ab 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/internal/controllers/paper.go b/internal/controllers/paper.go new file mode 100644 index 0000000..d7eb8c6 --- /dev/null +++ b/internal/controllers/paper.go @@ -0,0 +1,426 @@ +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 = "finish" + 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.UserQuizListResponse +// @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.UserQuizResponse +// @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 = "wrong" + if isCorrect { + score = 1.0 + correction = "correct" + } + + userquiz.Answer = userAnswer + userquiz.Status = "answer" + 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"}) +} diff --git a/internal/controllers/userquiz.go b/internal/controllers/userquiz.go index 1057d66..4558ad4 100644 --- a/internal/controllers/userquiz.go +++ b/internal/controllers/userquiz.go @@ -11,6 +11,7 @@ import ( "learnsteam/cslms-api/internal/services" "github.com/gin-gonic/gin" + "github.com/google/go-cmp/cmp" "github.com/google/uuid" "gorm.io/datatypes" ) @@ -20,15 +21,20 @@ type UserQuizController interface { Find(*gin.Context) Create(*gin.Context) Update(*gin.Context) + Answer(*gin.Context) } type userQuizController struct { - service services.UserQuizService + service services.UserQuizService + quizService services.QuizService + userquizpaperService services.UserQuizPaperService } -func NewUserQuizController(service services.UserQuizService) UserQuizController { +func NewUserQuizController(service services.UserQuizService, quizService services.QuizService, userquizpaperService services.UserQuizPaperService) UserQuizController { return &userQuizController{ - service: service, + service: service, + quizService: quizService, + userquizpaperService: userquizpaperService, } } @@ -154,7 +160,7 @@ func (controller *userQuizController) Create(c *gin.Context) { return } - quiz := &models.UserQuiz{ + userquiz := &models.UserQuiz{ GUID: uuid.NewString(), CenterID: request.CenterID, UserQuizPaperID: request.UserQuizPaperID, @@ -168,7 +174,7 @@ func (controller *userQuizController) Create(c *gin.Context) { CreatedAt: time.Now(), } - result, err := controller.service.Create(quiz) + result, err := controller.service.Create(userquiz) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -212,18 +218,6 @@ func (controller *userQuizController) Update(c *gin.Context) { return } - // CenterID int64 `json:"center_id" example:"1000001"` - // UserQuizPaperID int64 `json:"quiz_paper_id" example:"1000001"` - // UserID int64 `json:"user_id" example:"1000001"` - // No int `json:"vol_no" example:"1"` - // QuestionType string `json:"question_type" example:"choice"` - // Question string `json:"question" example:"질문입니다."` - // Content datatypes.JSON `json:"content"` - // Answer datatypes.JSON `json:"answer"` - // Status string `json:"status" example:"waiting"` - // Result string `json:"result" example:"success"` - // Score float32 `json:"score" example:"10"` - var content datatypes.JSON content, err = json.Marshal(request.Content) if err != nil { @@ -256,3 +250,91 @@ func (controller *userQuizController) Update(c *gin.Context) { c.JSON(http.StatusOK, result) } + +// Answer Quiz +// +// @Summary 사용자퀴즈 답변 +// @Description 사용자퀴즈 답변을 제출합니다.. +// @Tags 사용자퀴즈 +// +// @Accept json +// @Produce json +// +// @Security Bearer +// +// @Param id path int64 true "Quiz ID" +// @Param quizBody body models.AnswerQuizRequest true "Answer Body" +// +// @Router /userquiz/{id} [patch] +func (controller *userQuizController) Answer(c *gin.Context) { + id, err := strconv.ParseInt(c.Param("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.service.Find(id) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.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 = "wrong" + if isCorrect { + score = 1.0 + correction = "correct" + } + + userquiz.Answer = userAnswer + userquiz.Status = "answer" + userquiz.Result = correction + userquiz.Score = score + + _, err = controller.service.Update(userquiz) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + _, err = controller.userquizpaperService.UpdateScore(userquiz.UserQuizPaperID) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + // fmt.Println("userscore : ", result.UserScore) + + c.JSON(http.StatusOK, gin.H{"message": "success"}) +} diff --git a/internal/models/paper.go b/internal/models/paper.go new file mode 100644 index 0000000..0ec81b3 --- /dev/null +++ b/internal/models/paper.go @@ -0,0 +1,59 @@ +package models + +import ( + "time" +) + +type Paper struct { + ID int64 `json:"id" db:"id" example:"1000015" gorm:"column:id;primary_key;"` + GUID string `json:"guid_id" db:"guid_id" example:"7f9329f5-2e36-4638-92d2-73064b7291a4" gorm:"column:guid_id;size:255;uniqueIndex"` + CenterID int64 `json:"center_id" db:"center_id" example:"1000015" gorm:"column:center_id;index;"` + QuizPaperID int64 `json:"quiz_paper_id" db:"quiz_paper_id" example:"1000001" gorm:"column:quiz_paper_id;index;"` + UserID int64 `json:"user_id" db:"user_id" example:"1000002" gorm:"column:user_id;index;"` + UserScore float32 `json:"user_score" db:"user_score" example:"5" gorm:"column:user_score;"` + TotalScore float32 `json:"total_score" db:"total_score" example:"100" gorm:"column:total_score;"` + Status string `json:"status" example:"wating" gorm:"column:status;size:10;index;"` + StartAt *time.Time `json:"start_at" gorm:"column:start_at;index;"` + DoneAt *time.Time `json:"done_at" gorm:"column:done_at;index;"` + UpdatedAt time.Time `json:"-" gorm:"column:updated_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;index;->:false"` + CreatedAt time.Time `json:"-" gorm:"column:created_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false;<-:create"` +} + +// 테이블이름 정의 +func (Paper) TableName() string { + return "UserQuizPapers" +} + +type PaperResponse struct { + ID int64 `json:"id" db:"id" example:"1000015"` + GUID string `json:"guid_id" db:"guid_id" example:"7f9329f5-2e36-4638-92d2-73064b7291a4"` + CenterID int64 `json:"center_id" db:"center_id" example:"1000015"` + QuizPaperID int64 `json:"quiz_paper_id" db:"quiz_paper_id" example:"1000001"` + UserID int64 `json:"user_id" db:"user_id" example:"1000002"` + FirstName string `json:"first_name" db:"first_name" example:"길순"` + LastName string `json:"last_name" db:"last_name" example:"홍"` + UserScore float32 `json:"user_score" db:"user_score" example:"5"` + TotalScore float32 `json:"total_score" db:"total_score" example:"100"` + Status string `json:"status" example:"wating"` + Category string `json:"category" example:"파이썬기본"` + Title string `json:"title" example:"출력 Print"` + StartAt *time.Time `json:"start_at"` + DoneAt *time.Time `json:"done_at"` + CreatedAt *time.Time `json:"created_at"` +} + +type PaperPatchRequest struct { + UserScore float32 `json:"user_score" example:"4"` + TotalScore float32 `json:"total_score" example:"80"` + Status string `json:"status" example:"ready"` + StartAt string `json:"start_at,omitempty" example:"2023-11-10T13:10:00+09:00"` + DoneAt string `json:"done_at,omitempty" example:"2023-11-10T13:25:00+09:00"` +} + +type PaperListResponse struct { + Data []PaperResponse `json:"data"` + Total int64 `json:"total" example:"999"` + Page int `json:"page" example:"1"` + TotalPage int64 `json:"totalPage" example:"99"` + PageSize int `json:"pageSize" example:"10"` +} diff --git a/internal/models/paperquiz.go b/internal/models/paperquiz.go new file mode 100644 index 0000000..08a967d --- /dev/null +++ b/internal/models/paperquiz.go @@ -0,0 +1,54 @@ +package models + +import ( + "time" + + "gorm.io/datatypes" +) + +type PaperQuiz struct { + ID int64 `json:"id" db:"id" example:"1000001" gorm:"column:id;primary_key;"` + GUID string `json:"guid_id" db:"guid_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6" gorm:"column:guid_id;size:255;index;"` + CenterID int64 `json:"center_id" db:"center_id" example:"100001" gorm:"column:center_id;index;"` + UserQuizPaperID int64 `json:"user_quiz_paper_id" db:"user_quiz_paper_id" example:"1000001" gorm:"column:user_quiz_paper_id;index;"` + UserID int64 `json:"user_id" db:"user_id" example:"1000001" gorm:"column:user_id;index;"` + QuizID int64 `json:"quiz_id" db:"quiz_id" example:"1000001" gorm:"column:quiz_id;index;"` + No int `json:"vol_no" db:"vol_no" example:"5" gorm:"column:vol_no;index;"` + QuestionType string `json:"question_type" db:"question_type" example:"choice" gorm:"column:question_type;size:10;index;"` + Question string `json:"question" db:"question" example:"퀴즈 질문입니다." gorm:"column:question;size:512;"` + Content datatypes.JSON `json:"content" db:"content" gorm:"column:content;"` + Status string `json:"status" db:"status" example:"waiting" gorm:"column:status;size:10;index;"` + Result string `json:"result" db:"result" example:"success" gorm:"column:result;size:10;index;"` + Score float32 `json:"score" db:"score" example:"10" gorm:"column:score;"` + UpdatedAt time.Time `json:"-" gorm:"column:updated_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;index;->:false"` + CreatedAt time.Time `json:"-" gorm:"column:created_at;type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;index;->:false;<-:create"` +} + +// 테이블이름 정의 +func (PaperQuiz) TableName() string { + return "UserQuizs" +} + +type PaperQuizResponse struct { + ID int64 `json:"id" example:"1000001"` + GUID string `json:"guid_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6"` + CenterD string `json:"center_id" example:"2036023a-fb56-4b6c-b3bb-c787c681ada6"` + UserQuizPaperID int64 `json:"user_quiz_paper_id" example:"1000001"` + UserID int64 `json:"user_id" example:"1000001"` + QuizID int64 `json:"quiz_id" example:"1000001"` + No int `json:"vol_no" example:"5"` + QuestionType string `json:"question_type" example:"check"` + Question string `json:"question" example:"퀴즈 질문입니다."` + Content QuizContent `json:"content"` + Status string `json:"status" example:"waiting"` + Result string `json:"result" example:"success"` + Score float32 `json:"score" example:"10"` +} + +type PaperQuizListResponse struct { + Data []UserQuizResponse `json:"data"` + Total int64 `json:"total" example:"5"` + Page int `json:"page" example:"1"` + TotalPage int64 `json:"totalPage" example:"1"` + PageSize int `json:"pageSize" example:"10"` +} diff --git a/internal/models/userquiz.go b/internal/models/userquiz.go index 4a60c39..9d2be49 100644 --- a/internal/models/userquiz.go +++ b/internal/models/userquiz.go @@ -69,3 +69,7 @@ type UserQuizListResponse struct { TotalPage int64 `json:"totalPage" example:"1"` PageSize int `json:"pageSize" example:"10"` } + +type AnswerQuizRequest struct { + Answer []string `json:"answer" example:"option1,option4"` +} diff --git a/internal/repositories/paper.go b/internal/repositories/paper.go new file mode 100644 index 0000000..8655747 --- /dev/null +++ b/internal/repositories/paper.go @@ -0,0 +1,101 @@ +package repositories + +import ( + "learnsteam/cslms-api/internal/models" + + "gorm.io/gorm" +) + +type paperRepository struct { + DB *gorm.DB +} + +func NewPaperRepository(db *gorm.DB) PaperRepository { + return &paperRepository{ + DB: db, + } +} + +type PaperRepository interface { + List(int64, string, int, int) (*[]models.PaperResponse, error) + Total(int64, string) (int64, error) + + Find(int64) (*models.PaperResponse, error) + Get(int64) (*models.Paper, error) + Update(*models.Paper) (*models.Paper, error) +} + +func (r *paperRepository) List(user_id int64, q string, page int, limit int) (*[]models.PaperResponse, error) { + var rows *[]models.PaperResponse + var err error + offset := limit * (page - 1) + if q != "" { + err = r.DB.Offset(offset).Limit(limit).Order("UserQuizPapers.created_at DESC"). + Table("UserQuizPapers"). + Select("UserQuizPapers.*", "Users.first_name", "Users.last_name", "QuizPapers.title", "QuizPapers.category"). + Joins("LEFT JOIN Users ON Users.id = UserQuizPapers.user_id"). + Joins("LEFT JOIN QuizPapers ON QuizPapers.id = UserQuizPapers.quiz_paper_id"). + Where("QuizPapers.title LIKE ? OR QuizPapers.category LIKE ? OR CONCAT(first_name, last_name) LIKE ?", "%"+q+"%", "%"+q+"%", "%"+q+"%"). + Where("UserQuizPapers.user_id = ?", user_id). + Find(&rows).Error + } else { + err = r.DB.Offset(offset).Limit(limit).Order("UserQuizPapers.created_at DESC"). + Table("UserQuizPapers"). + Select("UserQuizPapers.*", "Users.first_name", "Users.last_name", "QuizPapers.title", "QuizPapers.category"). + Joins("LEFT JOIN Users ON Users.id = UserQuizPapers.user_id"). + Joins("LEFT JOIN QuizPapers ON QuizPapers.id = UserQuizPapers.quiz_paper_id"). + Where("UserQuizPapers.user_id = ?", user_id). + Find(&rows).Error + } + return rows, err +} + +func (r *paperRepository) Total(user_id int64, q string) (int64, error) { + var total int64 + var err error + if q != "" { + err = r.DB.Model(&models.Paper{}). + Joins("LEFT JOIN Users ON Users.id = UserQuizPapers.user_id"). + Joins("LEFT JOIN QuizPapers ON QuizPapers.id = UserQuizPapers.quiz_paper_id"). + Where("QuizPapers.title LIKE ? OR QuizPapers.category LIKE ? OR CONCAT(first_name, last_name) LIKE ?", "%"+q+"%", "%"+q+"%", "%"+q+"%"). + Where("UserQuizPapers.user_id = ?", user_id). + Count(&total). + Error + } else { + err = r.DB.Model(&models.Paper{}). + Where("user_id = ?", user_id). + Count(&total). + Error + } + + return total, err +} + +func (r *paperRepository) Find(id int64) (*models.PaperResponse, error) { + var row *models.PaperResponse + err := r.DB. + Table("UserQuizPapers"). + Select("UserQuizPapers.*", "Users.first_name", "Users.last_name", "QuizPapers.title", "QuizPapers.category"). + Joins("LEFT JOIN Users ON Users.id = UserQuizPapers.user_id"). + Joins("LEFT JOIN QuizPapers ON QuizPapers.id = UserQuizPapers.quiz_paper_id"). + Where("UserQuizPapers.id = ?", id).First(&row).Error + return row, err +} + +func (r *paperRepository) Get(id int64) (*models.Paper, error) { + var row *models.Paper + if err := r.DB.Where("id=?", id).First(&row).Error; err != nil { + return nil, err + } + return row, nil +} + +func (r *paperRepository) Update(paper *models.Paper) (*models.Paper, error) { + var row *models.Paper + if err := r.DB.Where("id=?", paper.ID).First(&row).Error; err != nil { + return nil, err + } + + err := r.DB.Model(&row).Select("*").Updates(&paper).Error + return row, err +} diff --git a/internal/repositories/paperquiz.go b/internal/repositories/paperquiz.go new file mode 100644 index 0000000..016ebcc --- /dev/null +++ b/internal/repositories/paperquiz.go @@ -0,0 +1,89 @@ +package repositories + +import ( + "learnsteam/cslms-api/internal/models" + + "gorm.io/gorm" +) + +type paperQuizRepository struct { + DB *gorm.DB +} + +func NewPaperQuizRepository(db *gorm.DB) PaperQuizRepository { + return &paperQuizRepository{ + DB: db, + } +} + +type PaperQuizRepository interface { + List(int64, int, int) (*[]models.PaperQuiz, error) + Total(int64) (int64, error) + + Find(int64) (*models.PaperQuiz, error) + Update(*models.PaperQuiz) (*models.PaperQuiz, error) + Delete(int64) error + SumScore(int64) (float32, error) +} + +func (r *paperQuizRepository) List(paper_id int64, page int, limit int) (*[]models.PaperQuiz, error) { + var rows *[]models.PaperQuiz + var err error + offset := limit * (page - 1) + if paper_id > 0 { + err = r.DB.Offset(offset).Limit(limit).Order("vol_no ASC").Where("user_quiz_paper_id = ?", paper_id).Find(&rows).Error + } else { + err = r.DB.Offset(offset).Limit(limit).Find(&rows).Error + } + return rows, err +} + +func (r *paperQuizRepository) Total(paper_id int64) (int64, error) { + var total int64 + var err error + if paper_id > 0 { + err = r.DB.Model(&models.PaperQuiz{}).Where("user_quiz_paper_id = ?", paper_id).Count(&total).Error + } else { + err = r.DB.Model(&models.PaperQuiz{}).Count(&total).Error + } + + return total, err +} + +func (r *paperQuizRepository) Find(id int64) (*models.PaperQuiz, error) { + var row *models.PaperQuiz + err := r.DB.Where("id = ?", id).First(&row).Error + return row, err +} + +func (r *paperQuizRepository) Update(quiz *models.PaperQuiz) (*models.PaperQuiz, error) { + var row *models.PaperQuiz + if err := r.DB.Where("id=?", quiz.ID).First(&row).Error; err != nil { + return nil, err + } + + err := r.DB.Model(&row).Select("*").Updates(&quiz).Error + return row, err +} + +func (r *paperQuizRepository) Delete(id int64) error { + var row *models.PaperQuiz + if err := r.DB.Where("id=?", id).First(&row).Error; err != nil { + return err + } + err := r.DB.Delete(&row).Error + return err +} + +func (r *paperQuizRepository) SumScore(paper_id int64) (float32, error) { + var result struct { + Score float32 + } + + if err := r.DB.Model(&models.PaperQuiz{}).Select("SUM(score) AS score"). + Where("user_quiz_paper_id = ?", paper_id). + Scan(&result).Error; err != nil { + return 0, err + } + return result.Score, nil +} diff --git a/internal/repositories/userquiz.go b/internal/repositories/userquiz.go index 03250a1..7c27a99 100644 --- a/internal/repositories/userquiz.go +++ b/internal/repositories/userquiz.go @@ -26,6 +26,7 @@ type UserQuizRepository interface { Insert([]models.UserQuiz) ([]models.UserQuiz, error) Update(*models.UserQuiz) (*models.UserQuiz, error) Delete(int64) error + SumScore(int64) (float32, error) } func (r *userQuizRepository) List(user_quiz_paper_id int64, page int, limit int) (*[]models.UserQuiz, error) { @@ -86,3 +87,16 @@ func (r *userQuizRepository) Delete(id int64) error { err := r.DB.Delete(&row).Error return err } + +func (r *userQuizRepository) SumScore(userquizpaper_id int64) (float32, error) { + var result struct { + Score float32 + } + + if err := r.DB.Model(&models.UserQuiz{}).Select("SUM(score) AS score"). + Where("user_quiz_paper_id = ?", userquizpaper_id). + Scan(&result).Error; err != nil { + return 0, err + } + return result.Score, nil +} diff --git a/internal/routers/paper.go b/internal/routers/paper.go new file mode 100644 index 0000000..9a47005 --- /dev/null +++ b/internal/routers/paper.go @@ -0,0 +1,89 @@ +package routers + +import ( + "learnsteam/cslms-api/internal/controllers" + "learnsteam/cslms-api/internal/middleware" + "learnsteam/cslms-api/internal/repositories" + "learnsteam/cslms-api/internal/services" + + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +func InitPaperRouter(db *gorm.DB, router *gin.Engine) { + r := NewPaperRouter(db, router) + r.SetPaperRouter() +} + +type PaperRouter interface { + SetRouter(db *gorm.DB, router *gin.Engine) +} + +type paperRouter struct { + db *gorm.DB + repository repositories.PaperRepository + paperQuizRepository repositories.PaperQuizRepository + quizRepository repositories.QuizRepository + quizPaperRepository repositories.QuizPaperRepository + userRepository repositories.UserRepository + userQuizRepository repositories.UserQuizRepository + service services.PaperService + paperQuizService services.PaperQuizService + quizService services.QuizService + quizPaperService services.QuizPaperService + userService services.UserService + userQuizService services.UserQuizService + controller controllers.PaperController + router *gin.Engine +} + +func NewPaperRouter(db *gorm.DB, router *gin.Engine) *paperRouter { + repository := repositories.NewPaperRepository(db) + paperQuizRepository := repositories.NewPaperQuizRepository(db) + quizRepository := repositories.NewQuizRepository(db) + quizPaperRepository := repositories.NewQuizPaperRepository(db) + tokenRepository := repositories.NewTokenRepository(db) + userRepository := repositories.NewUserRepository(db) + userQuizRepository := repositories.NewUserQuizRepository(db) + + service := services.NewPaperService(repository, paperQuizRepository) + paperQuizService := services.NewPaperQuizService(paperQuizRepository) + quizService := services.NewQuizService(quizRepository) + quizPaperService := services.NewQuizPaperService(quizPaperRepository) + userService := services.NewUserService(userRepository, tokenRepository) + userQuizService := services.NewUserQuizService(userQuizRepository, quizRepository) + + controller := controllers.NewPaperController(service, paperQuizService, quizService, quizPaperService, userService, userQuizService) + + return &paperRouter{ + db: db, + repository: repository, + quizRepository: quizRepository, + quizPaperRepository: quizPaperRepository, + userRepository: userRepository, + userQuizRepository: userQuizRepository, + + service: service, + paperQuizService: paperQuizService, + quizService: quizService, + quizPaperService: quizPaperService, + userService: userService, + userQuizService: userQuizService, + + controller: controller, + + router: router, + } +} + +func (r *paperRouter) SetPaperRouter() { + group := r.router.Group("/paper") + group.GET("", middleware.Auth("member"), r.controller.List) + group.GET("/:paper_id", middleware.Auth("member"), r.controller.Find) + group.PATCH("/:paper_id/start", middleware.Auth("member"), r.controller.Start) + group.PATCH("/:paper_id/finish", middleware.Auth("member"), r.controller.Finish) + + group.GET("/:paper_id/quiz", middleware.Auth("member"), r.controller.QuizList) + group.GET("/:paper_id/quiz/:quiz_id", middleware.Auth("member"), r.controller.QuizFind) + group.PATCH("/:paper_id/quiz/:quiz_id/answer", middleware.Auth("member"), r.controller.QuizAnswer) +} diff --git a/internal/routers/router.go b/internal/routers/router.go index 076a7ab..b39a29b 100644 --- a/internal/routers/router.go +++ b/internal/routers/router.go @@ -25,6 +25,7 @@ func Init() { InitAuthRouter(maindb, Router) InitCenterRouter(maindb, Router) + InitPaperRouter(maindb, Router) InitQuizPaperRouter(maindb, Router) InitQuizRouter(maindb, Router) InitTokenRouter(maindb, Router) diff --git a/internal/routers/userquiz.go b/internal/routers/userquiz.go index b80a649..4055ca2 100644 --- a/internal/routers/userquiz.go +++ b/internal/routers/userquiz.go @@ -20,27 +20,42 @@ type UserQuizRouter interface { } type userQuizRouter struct { - db *gorm.DB - repository repositories.UserQuizRepository - quizRepository repositories.QuizRepository - service services.UserQuizService - controller controllers.UserQuizController - router *gin.Engine + db *gorm.DB + repository repositories.UserQuizRepository + quizRepository repositories.QuizRepository + userquizRepository repositories.UserQuizRepository + userquizpaperRepository repositories.UserQuizPaperRepository + service services.UserQuizService + quizService services.QuizService + userquizService services.UserQuizService + userquizpaperService services.UserQuizPaperService + controller controllers.UserQuizController + router *gin.Engine } func NewUserQuizRouter(db *gorm.DB, router *gin.Engine) *userQuizRouter { repository := repositories.NewUserQuizRepository(db) quizRepostory := repositories.NewQuizRepository(db) + userquizRepository := repositories.NewUserQuizRepository(db) + userquizpaperRepository := repositories.NewUserQuizPaperRepository(db) service := services.NewUserQuizService(repository, quizRepostory) - controller := controllers.NewUserQuizController(service) + quizService := services.NewQuizService(quizRepostory) + userquizService := services.NewUserQuizService(userquizRepository, quizRepostory) + userquizpaperService := services.NewUserQuizPaperService(userquizpaperRepository, userquizRepository) + controller := controllers.NewUserQuizController(service, quizService, userquizpaperService) return &userQuizRouter{ - db: db, - repository: repository, - quizRepository: quizRepostory, - service: service, - controller: controller, - router: router, + db: db, + repository: repository, + quizRepository: quizRepostory, + userquizpaperRepository: userquizpaperRepository, + userquizRepository: userquizRepository, + service: service, + quizService: quizService, + userquizpaperService: userquizpaperService, + userquizService: userquizService, + controller: controller, + router: router, } } @@ -50,4 +65,5 @@ func (r *userQuizRouter) SetUserQuizRouter() { group.GET("/:id", middleware.Auth("admin"), r.controller.Find) group.POST("", middleware.Auth("admin"), r.controller.Create) group.PUT("/:id", middleware.Auth("admin"), r.controller.Update) + group.PATCH("/:id", middleware.Auth("member"), r.controller.Answer) } diff --git a/internal/routers/userquizpaper.go b/internal/routers/userquizpaper.go index 998b83f..4275a1a 100644 --- a/internal/routers/userquizpaper.go +++ b/internal/routers/userquizpaper.go @@ -42,7 +42,7 @@ func NewUserQuizPaperRouter(db *gorm.DB, router *gin.Engine) *userQuizPaperRoute userRepository := repositories.NewUserRepository(db) userQuizRepository := repositories.NewUserQuizRepository(db) - service := services.NewUserQuizPaperService(repository) + service := services.NewUserQuizPaperService(repository, userQuizRepository) quizService := services.NewQuizService(quizRepository) quizPaperService := services.NewQuizPaperService(quizPaperRepository) userService := services.NewUserService(userRepository, tokenRepository) diff --git a/internal/services/paper.go b/internal/services/paper.go new file mode 100644 index 0000000..589991d --- /dev/null +++ b/internal/services/paper.go @@ -0,0 +1,66 @@ +package services + +import ( + "learnsteam/cslms-api/internal/models" + "learnsteam/cslms-api/internal/repositories" +) + +type paperService struct { + repository repositories.PaperRepository + paperQuizRepository repositories.PaperQuizRepository +} + +type PaperService interface { + List(int64, string, int, int) (*[]models.PaperResponse, error) + Total(int64, string) (int64, error) + + Find(int64) (*models.PaperResponse, error) + Get(int64) (*models.Paper, error) + Update(*models.Paper) (*models.Paper, error) + + UpdateScore(int64) (*models.Paper, error) +} + +func NewPaperService(repository repositories.PaperRepository, paperQuizRepository repositories.PaperQuizRepository) PaperService { + return &paperService{ + repository: repository, + paperQuizRepository: paperQuizRepository, + } +} + +func (s *paperService) List(user_id int64, q string, page int, limit int) (*[]models.PaperResponse, error) { + return s.repository.List(user_id, q, page, limit) +} + +func (s *paperService) Total(user_id int64, q string) (int64, error) { + return s.repository.Total(user_id, q) +} + +func (s *paperService) Find(id int64) (*models.PaperResponse, error) { + return s.repository.Find(id) +} + +func (s *paperService) Get(id int64) (*models.Paper, error) { + return s.repository.Get(id) +} + +func (s *paperService) Update(paper *models.Paper) (*models.Paper, error) { + result, err := s.repository.Update(paper) + + return result, err +} + +func (s *paperService) UpdateScore(userquizpaper_id int64) (*models.Paper, error) { + score, err := s.paperQuizRepository.SumScore(userquizpaper_id) + if err != nil { + return nil, err + } + + userquizpaper, err := s.repository.Get(userquizpaper_id) + if err != nil { + return nil, err + } + + userquizpaper.UserScore = score + return s.repository.Update(userquizpaper) +} diff --git a/internal/services/paperquiz.go b/internal/services/paperquiz.go new file mode 100644 index 0000000..2eb6a7e --- /dev/null +++ b/internal/services/paperquiz.go @@ -0,0 +1,43 @@ +package services + +import ( + "learnsteam/cslms-api/internal/models" + "learnsteam/cslms-api/internal/repositories" +) + +type paperQuizService struct { + repository repositories.PaperQuizRepository + quizRepository repositories.QuizRepository +} + +type PaperQuizService interface { + List(int64, int, int) (*[]models.PaperQuiz, error) + Total(int64) (int64, error) + + Find(int64) (*models.PaperQuiz, error) + Update(*models.PaperQuiz) (*models.PaperQuiz, error) +} + +func NewPaperQuizService(repository repositories.PaperQuizRepository) PaperQuizService { + return &paperQuizService{ + repository: repository, + } +} + +func (s *paperQuizService) List(user_quiz_paper_id int64, page int, limit int) (*[]models.PaperQuiz, error) { + return s.repository.List(user_quiz_paper_id, page, limit) +} + +func (s *paperQuizService) Total(user_quiz_paper_id int64) (int64, error) { + return s.repository.Total(user_quiz_paper_id) +} + +func (s *paperQuizService) Find(id int64) (*models.PaperQuiz, error) { + return s.repository.Find(id) +} + +func (s *paperQuizService) Update(quiz *models.PaperQuiz) (*models.PaperQuiz, error) { + result, err := s.repository.Update(quiz) + + return result, err +} diff --git a/internal/services/userquiz.go b/internal/services/userquiz.go index a0530e1..e08ae20 100644 --- a/internal/services/userquiz.go +++ b/internal/services/userquiz.go @@ -84,6 +84,7 @@ func (s *userQuizService) Generate(quiz_paper_id int64, userQuizPaper *models.Us QuestionType: quiz.QuestionType, Question: quiz.Question, Content: quiz.Content, + Status: "ready", } fmt.Println(userQuiz.Content) diff --git a/internal/services/userquizpaper.go b/internal/services/userquizpaper.go index 8c3357c..e90f925 100644 --- a/internal/services/userquizpaper.go +++ b/internal/services/userquizpaper.go @@ -1,6 +1,7 @@ package services import ( + "fmt" "learnsteam/cslms-api/internal/models" "learnsteam/cslms-api/internal/repositories" @@ -8,7 +9,8 @@ import ( ) type userQuizPaperService struct { - repository repositories.UserQuizPaperRepository + repository repositories.UserQuizPaperRepository + userquizRepository repositories.UserQuizRepository } type UserQuizPaperService interface { @@ -22,11 +24,13 @@ type UserQuizPaperService interface { Update(*models.UserQuizPaper) (*models.UserQuizPaper, error) Delete(string) error Generate([]int64, *models.QuizPaper) []models.UserQuizPaper + UpdateScore(int64) (*models.UserQuizPaper, error) } -func NewUserQuizPaperService(repository repositories.UserQuizPaperRepository) UserQuizPaperService { +func NewUserQuizPaperService(repository repositories.UserQuizPaperRepository, userquizRepository repositories.UserQuizRepository) UserQuizPaperService { return &userQuizPaperService{ - repository: repository, + repository: repository, + userquizRepository: userquizRepository, } } @@ -79,6 +83,7 @@ func (s *userQuizPaperService) Generate(users []int64, quizPaper *models.QuizPap CenterID: quizPaper.CenterID, UserID: user_id, QuizPaperID: quizPaper.ID, + Status: "ready", } userQuizPapers = append(userQuizPapers, userQuizPaper) @@ -86,3 +91,19 @@ func (s *userQuizPaperService) Generate(users []int64, quizPaper *models.QuizPap return userQuizPapers } + +func (s *userQuizPaperService) UpdateScore(userquizpaper_id int64) (*models.UserQuizPaper, error) { + score, err := s.userquizRepository.SumScore(userquizpaper_id) + if err != nil { + return nil, err + } + + userquizpaper, err := s.repository.Get(userquizpaper_id) + if err != nil { + return nil, err + } + + fmt.Println("score", score) + userquizpaper.UserScore = score + return s.repository.Update(userquizpaper) +} diff --git a/test/test.db b/test/test.db new file mode 100644 index 0000000..e69de29 diff --git a/test/token_test.go b/test/token_test.go index 50d79da..c2006b4 100644 --- a/test/token_test.go +++ b/test/token_test.go @@ -1,6 +1,7 @@ package learsteam_quiz_test import ( + "encoding/json" "fmt" config "learnsteam/cslms-api/configs" "learnsteam/cslms-api/internal/controllers" @@ -10,8 +11,10 @@ import ( "time" "github.com/golang-jwt/jwt/v5" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/suite" "github.com/tj/assert" + "gorm.io/datatypes" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/schema" @@ -295,3 +298,24 @@ func (suite *TokenTestSuite) TestVerifyExpiredToken() { assert.Error(suite.T(), err) assert.False(suite.T(), jwtToken.Valid) } + +func (suite *TokenTestSuite) TestCompareJSON() { + // a := `["a","b","c"]` + // b := `["a","b","c"]` + a := `{"x":1,"y":2}` + b := `{"y":2,"x":1}` + + var json1 datatypes.JSON + json1, err := json.Marshal(a) + assert.NoError(suite.T(), err) + + var json2 datatypes.JSON + json2, err = json.Marshal(b) + assert.NoError(suite.T(), err) + + assert.Equal(suite.T(), json2.String(), "") + + compare := cmp.Equal(json1.String(), json2.String()) + + assert.Equal(suite.T(), true, compare) +}