Chinh sua UI
This commit is contained in:
parent
8f144c1a8b
commit
8cca84ceec
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6,29 +6,45 @@
|
|||||||
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form1.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form1.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form2.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form2.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form2.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form2.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form1.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\response\\quiz.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form1.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:response\\quiz.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\response\\questionoption.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:response\\questionoption.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\service\\executeexcelservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:service\\executeexcelservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\response\\question.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:response\\question.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\dbhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:dbhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\service\\datautil.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\service\\datautil.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:service\\datautil.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:service\\datautil.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|E:\\QuizMaster\\QuizMaster\\form1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form",
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\service\\excelvalidator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}|Form"
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:service\\excelvalidator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form2.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\form2.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||||
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form2.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:form2.designer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|e:\\quizmaster\\quizmaster\\dbhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{582DBFA6-720D-44B4-B48C-909F4DD98783}|QuizMaster.csproj|solutionrelative:dbhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"DocumentGroupContainers": [
|
"DocumentGroupContainers": [
|
||||||
@ -48,7 +64,7 @@
|
|||||||
"RelativeDocumentMoniker": "Form1.cs",
|
"RelativeDocumentMoniker": "Form1.cs",
|
||||||
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form1.cs",
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form1.cs",
|
||||||
"RelativeToolTip": "Form1.cs",
|
"RelativeToolTip": "Form1.cs",
|
||||||
"ViewState": "AQIAAAYEAAAAAAAAAAAcwBEEAAApAAAA",
|
"ViewState": "AQIAAE8AAAAAAAAAAAAuwGUAAABVAAAA",
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
"WhenOpened": "2025-05-26T01:54:54.164Z",
|
"WhenOpened": "2025-05-26T01:54:54.164Z",
|
||||||
"IsPinned": true,
|
"IsPinned": true,
|
||||||
@ -56,28 +72,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$type": "Document",
|
"$type": "Document",
|
||||||
"DocumentIndex": 1,
|
"DocumentIndex": 2,
|
||||||
"Title": "Form2.cs",
|
"Title": "Form2.cs",
|
||||||
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Form2.cs",
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Form2.cs",
|
||||||
"RelativeDocumentMoniker": "Form2.cs",
|
"RelativeDocumentMoniker": "Form2.cs",
|
||||||
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form2.cs",
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form2.cs",
|
||||||
"RelativeToolTip": "Form2.cs",
|
"RelativeToolTip": "Form2.cs",
|
||||||
"ViewState": "AQIAAGMAAAAAAAAAAAAAAGwAAAAxAAAA",
|
"ViewState": "AQIAAF0AAAAAAAAAAAAIwG8AAAAUAAAA",
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
"WhenOpened": "2025-10-02T06:28:48.666Z",
|
"WhenOpened": "2025-10-02T06:28:48.666Z",
|
||||||
"IsPinned": true,
|
"IsPinned": true
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 4,
|
|
||||||
"Title": "Form1.cs [Design]",
|
|
||||||
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Form1.cs",
|
|
||||||
"RelativeDocumentMoniker": "Form1.cs",
|
|
||||||
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form1.cs [Design]",
|
|
||||||
"RelativeToolTip": "Form1.cs [Design]",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-08T02:47:37.753Z"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$type": "Bookmark",
|
"$type": "Bookmark",
|
||||||
@ -95,52 +99,111 @@
|
|||||||
"$type": "Bookmark",
|
"$type": "Bookmark",
|
||||||
"Name": "ST:17:0:{e8034f19-ab72-4f06-83fd-f6832b41aa63}"
|
"Name": "ST:17:0:{e8034f19-ab72-4f06-83fd-f6832b41aa63}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$type": "Document",
|
||||||
|
"DocumentIndex": 6,
|
||||||
|
"Title": "Question.cs",
|
||||||
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Response\\Question.cs",
|
||||||
|
"RelativeDocumentMoniker": "Response\\Question.cs",
|
||||||
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Response\\Question.cs",
|
||||||
|
"RelativeToolTip": "Response\\Question.cs",
|
||||||
|
"ViewState": "AQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||||
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
|
"WhenOpened": "2025-10-14T06:24:38.262Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$type": "Document",
|
"$type": "Document",
|
||||||
"DocumentIndex": 3,
|
"DocumentIndex": 3,
|
||||||
|
"Title": "Quiz.cs",
|
||||||
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Response\\Quiz.cs",
|
||||||
|
"RelativeDocumentMoniker": "Response\\Quiz.cs",
|
||||||
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Response\\Quiz.cs",
|
||||||
|
"RelativeToolTip": "Response\\Quiz.cs",
|
||||||
|
"ViewState": "AQIAAAAAAAAAAAAAAAAAAA0AAAAWAAAA",
|
||||||
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
|
"WhenOpened": "2025-10-13T08:59:40.254Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$type": "Document",
|
||||||
|
"DocumentIndex": 5,
|
||||||
|
"Title": "ExecuteExcelService.cs",
|
||||||
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Service\\ExecuteExcelService.cs",
|
||||||
|
"RelativeDocumentMoniker": "Service\\ExecuteExcelService.cs",
|
||||||
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Service\\ExecuteExcelService.cs",
|
||||||
|
"RelativeToolTip": "Service\\ExecuteExcelService.cs",
|
||||||
|
"ViewState": "AQIAAA8AAAAAAAAAAAAAADAAAAAAAAAA",
|
||||||
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
|
"WhenOpened": "2025-10-13T03:41:10.651Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$type": "Document",
|
||||||
|
"DocumentIndex": 4,
|
||||||
|
"Title": "QuestionOption.cs",
|
||||||
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Response\\QuestionOption.cs",
|
||||||
|
"RelativeDocumentMoniker": "Response\\QuestionOption.cs",
|
||||||
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Response\\QuestionOption.cs",
|
||||||
|
"RelativeToolTip": "Response\\QuestionOption.cs",
|
||||||
|
"ViewState": "AQIAAAAAAAAAAAAAAAAAAAYAAAAWAAAA",
|
||||||
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
|
"WhenOpened": "2025-10-10T06:59:55.277Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$type": "Document",
|
||||||
|
"DocumentIndex": 9,
|
||||||
|
"Title": "ExcelValidator.cs",
|
||||||
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Service\\ExcelValidator.cs",
|
||||||
|
"RelativeDocumentMoniker": "Service\\ExcelValidator.cs",
|
||||||
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Service\\ExcelValidator.cs",
|
||||||
|
"RelativeToolTip": "Service\\ExcelValidator.cs",
|
||||||
|
"ViewState": "AQIAAFcAAAAAAAAAAAAQwEwAAAAJAAAA",
|
||||||
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
|
"WhenOpened": "2025-10-10T03:12:07.301Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$type": "Document",
|
||||||
|
"DocumentIndex": 8,
|
||||||
"Title": "DataUtil.cs",
|
"Title": "DataUtil.cs",
|
||||||
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Service\\DataUtil.cs",
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Service\\DataUtil.cs",
|
||||||
"RelativeDocumentMoniker": "Service\\DataUtil.cs",
|
"RelativeDocumentMoniker": "Service\\DataUtil.cs",
|
||||||
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Service\\DataUtil.cs",
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Service\\DataUtil.cs",
|
||||||
"RelativeToolTip": "Service\\DataUtil.cs",
|
"RelativeToolTip": "Service\\DataUtil.cs",
|
||||||
"ViewState": "AQIAABsBAAAAAAAAAAAwwEABAAAAAAAA",
|
"ViewState": "AQIAAAAAAAAAAAAAAAAAABEAAAAJAAAA",
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
"WhenOpened": "2025-05-29T01:45:12.308Z"
|
"WhenOpened": "2025-05-29T01:45:12.308Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$type": "Document",
|
"$type": "Document",
|
||||||
"DocumentIndex": 2,
|
"DocumentIndex": 1,
|
||||||
"Title": "Form1.Designer.cs",
|
"Title": "Form1.Designer.cs",
|
||||||
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Form1.Designer.cs",
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Form1.Designer.cs",
|
||||||
"RelativeDocumentMoniker": "Form1.Designer.cs",
|
"RelativeDocumentMoniker": "Form1.Designer.cs",
|
||||||
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form1.Designer.cs",
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form1.Designer.cs",
|
||||||
"RelativeToolTip": "Form1.Designer.cs",
|
"RelativeToolTip": "Form1.Designer.cs",
|
||||||
"ViewState": "AQIAABoBAAAAAAAAAAAYwCcBAAAwAAAA",
|
"ViewState": "AQIAAE8AAAAAAAAAAAAuwGUAAAAxAAAA",
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
"WhenOpened": "2025-09-30T04:14:48.709Z",
|
"WhenOpened": "2025-09-30T04:14:48.709Z"
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$type": "Document",
|
"$type": "Document",
|
||||||
"DocumentIndex": 5,
|
"DocumentIndex": 10,
|
||||||
"Title": "Form2.Designer.cs",
|
"Title": "Form2.Designer.cs",
|
||||||
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Form2.Designer.cs",
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\Form2.Designer.cs",
|
||||||
"RelativeDocumentMoniker": "Form2.Designer.cs",
|
"RelativeDocumentMoniker": "Form2.Designer.cs",
|
||||||
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form2.Designer.cs",
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\Form2.Designer.cs",
|
||||||
"RelativeToolTip": "Form2.Designer.cs",
|
"RelativeToolTip": "Form2.Designer.cs",
|
||||||
"ViewState": "AQIAAAAAAAAAAAAAAAAAACcAAAAbAAAA",
|
"ViewState": "AQIAAAAAAAAAAAAAAAAAADYAAAAgAAAA",
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
"WhenOpened": "2025-10-02T06:23:49.946Z"
|
"WhenOpened": "2025-10-02T06:23:49.946Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$type": "Document",
|
"$type": "Document",
|
||||||
"DocumentIndex": 6,
|
"DocumentIndex": 7,
|
||||||
"Title": "DbHelper.cs",
|
"Title": "DbHelper.cs",
|
||||||
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\DbHelper.cs",
|
"DocumentMoniker": "E:\\QuizMaster\\QuizMaster\\DbHelper.cs",
|
||||||
"RelativeDocumentMoniker": "DbHelper.cs",
|
"RelativeDocumentMoniker": "DbHelper.cs",
|
||||||
"ToolTip": "E:\\QuizMaster\\QuizMaster\\DbHelper.cs",
|
"ToolTip": "E:\\QuizMaster\\QuizMaster\\DbHelper.cs",
|
||||||
"RelativeToolTip": "DbHelper.cs",
|
"RelativeToolTip": "DbHelper.cs",
|
||||||
"ViewState": "AQIAADAAAAAAAAAAAAAYwBIAAAAPAAAA",
|
"ViewState": "AQIAADYAAAAAAAAAAAAYwBIAAAAPAAAA",
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||||
"WhenOpened": "2025-05-26T01:35:21.294Z"
|
"WhenOpened": "2025-05-26T01:35:21.294Z"
|
||||||
}
|
}
|
||||||
|
|||||||
8
QuizMaster/Form1.Designer.cs
generated
8
QuizMaster/Form1.Designer.cs
generated
@ -98,8 +98,8 @@
|
|||||||
panelcb.BorderStyle = BorderStyle.FixedSingle;
|
panelcb.BorderStyle = BorderStyle.FixedSingle;
|
||||||
panelcb.Location = new Point(50, 50);
|
panelcb.Location = new Point(50, 50);
|
||||||
panelcb.Name = "panelcb";
|
panelcb.Name = "panelcb";
|
||||||
panelcb.Size = new Size(600, 300);
|
panelcb.Size = new Size(770, 200);
|
||||||
panelcb.MaximumSize = new Size(600, 300);
|
panelcb.MaximumSize = new Size(770, 400);
|
||||||
panelcb.TabIndex = 1;
|
panelcb.TabIndex = 1;
|
||||||
panelcb.AutoScroll = true;
|
panelcb.AutoScroll = true;
|
||||||
panelcb.AutoSize = true;
|
panelcb.AutoSize = true;
|
||||||
@ -113,8 +113,8 @@
|
|||||||
panelop.Controls.Add(lblNumberOfCopies);
|
panelop.Controls.Add(lblNumberOfCopies);
|
||||||
panelop.Controls.Add(txtNumberOfCopies);
|
panelop.Controls.Add(txtNumberOfCopies);
|
||||||
panelop.Name = "panelop";
|
panelop.Name = "panelop";
|
||||||
panelop.Size = new Size(600, 100);
|
panelop.Size = new Size(770, 100);
|
||||||
panelop.MaximumSize = new Size(600, 300);
|
panelop.MaximumSize = new Size(770, 300);
|
||||||
panelop.TabIndex = 2;
|
panelop.TabIndex = 2;
|
||||||
panelop.AutoScroll = true;
|
panelop.AutoScroll = true;
|
||||||
panelop.AutoSize = true;
|
panelop.AutoSize = true;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
3
QuizMaster/Form2.Designer.cs
generated
3
QuizMaster/Form2.Designer.cs
generated
@ -35,6 +35,7 @@
|
|||||||
this.txtResult.Location = new System.Drawing.Point(0, 0);
|
this.txtResult.Location = new System.Drawing.Point(0, 0);
|
||||||
this.txtResult.Name = "txtResult";
|
this.txtResult.Name = "txtResult";
|
||||||
this.txtResult.Size = new System.Drawing.Size(800, 450);
|
this.txtResult.Size = new System.Drawing.Size(800, 450);
|
||||||
|
this.txtResult.WordWrap = true;
|
||||||
this.txtResult.TabIndex = 0;
|
this.txtResult.TabIndex = 0;
|
||||||
//
|
//
|
||||||
//btnExoortWord
|
//btnExoortWord
|
||||||
@ -49,8 +50,8 @@
|
|||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(800, 450);
|
this.ClientSize = new System.Drawing.Size(800, 450);
|
||||||
this.Controls.Add(this.txtResult);
|
|
||||||
this.Controls.Add(this.btnExportWord);
|
this.Controls.Add(this.btnExportWord);
|
||||||
|
this.Controls.Add(this.txtResult);
|
||||||
this.Name = "Form2";
|
this.Name = "Form2";
|
||||||
this.Text = "Kết quả Generate";
|
this.Text = "Kết quả Generate";
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|||||||
@ -4,7 +4,6 @@ using System.Windows.Forms;
|
|||||||
using Xceed.Words.NET;
|
using Xceed.Words.NET;
|
||||||
using Xceed.Document.NET;
|
using Xceed.Document.NET;
|
||||||
|
|
||||||
|
|
||||||
namespace QuizMaster
|
namespace QuizMaster
|
||||||
{
|
{
|
||||||
public partial class Form2 : Form
|
public partial class Form2 : Form
|
||||||
@ -16,7 +15,7 @@ namespace QuizMaster
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_content = content;
|
_content = content;
|
||||||
txtResult.Text = content;
|
txtResult.Text = _content.Replace("\n", Environment.NewLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnExportWord_Click(object sender, EventArgs e)
|
private void btnExportWord_Click(object sender, EventArgs e)
|
||||||
|
|||||||
Binary file not shown.
@ -6,5 +6,7 @@
|
|||||||
public string Question { get; set; }
|
public string Question { get; set; }
|
||||||
public string Option { get; set; }
|
public string Option { get; set; }
|
||||||
public int IsCorrect { get; set; } // 1 = đúng, 0 = sai
|
public int IsCorrect { get; set; } // 1 = đúng, 0 = sai
|
||||||
|
public string DoKho { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ namespace QuizMaster.Response
|
|||||||
public string? B { get; set; }
|
public string? B { get; set; }
|
||||||
public string? C { get; set; }
|
public string? C { get; set; }
|
||||||
public string? D { get; set; }
|
public string? D { get; set; }
|
||||||
public required string DapAn { get; set; }
|
public required List<string> DapAn { get; set; } = new List<string>();
|
||||||
|
public string DoKho { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace QuizMaster.Service
|
|||||||
|
|
||||||
// 1. Kiểm tra xem câu hỏi đã tồn tại chưa
|
// 1. Kiểm tra xem câu hỏi đã tồn tại chưa
|
||||||
var questionIdCmd = new NpgsqlCommand(@"
|
var questionIdCmd = new NpgsqlCommand(@"
|
||||||
SELECT id FROM question WHERE content = @content AND category_id = @category_id;
|
SELECT id FROM question WHERE content = @content AND category_id = @category_id;
|
||||||
", conn);
|
", conn);
|
||||||
|
|
||||||
questionIdCmd.Parameters.AddWithValue("content", questionContent);
|
questionIdCmd.Parameters.AddWithValue("content", questionContent);
|
||||||
@ -42,9 +42,9 @@ namespace QuizMaster.Service
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cmd = new NpgsqlCommand(@"
|
var cmd = new NpgsqlCommand(@"
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM category
|
FROM category
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
", conn);
|
", conn);
|
||||||
|
|
||||||
await using var reader = await cmd.ExecuteReaderAsync();
|
await using var reader = await cmd.ExecuteReaderAsync();
|
||||||
@ -75,11 +75,11 @@ namespace QuizMaster.Service
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cmd = new NpgsqlCommand(@"
|
var cmd = new NpgsqlCommand(@"
|
||||||
SELECT c.name
|
SELECT c.name
|
||||||
FROM category c
|
FROM category c
|
||||||
INNER JOIN department d ON c.department_id = d.id
|
INNER JOIN department d ON c.department_id = d.id
|
||||||
WHERE d.name = @departmentName
|
WHERE d.name = @departmentName
|
||||||
ORDER BY c.name;
|
ORDER BY c.name;
|
||||||
", conn);
|
", conn);
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("departmentName", departmentName);
|
cmd.Parameters.AddWithValue("departmentName", departmentName);
|
||||||
@ -103,6 +103,48 @@ namespace QuizMaster.Service
|
|||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<List<CategoryInfo>> GetTotalOptionQuestionsAsync(List<string> lstCategory, string DoKho)
|
||||||
|
{
|
||||||
|
var categories = new List<CategoryInfo>();
|
||||||
|
if (lstCategory == null || lstCategory.Count == 0)
|
||||||
|
{
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
string whereCate = string.Join(",", lstCategory.Select(c => $"'{c.Replace("'", "''")}'"));
|
||||||
|
await using var conn = new NpgsqlConnection(DbHelper.connectionString);
|
||||||
|
await conn.OpenAsync();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cmd = new NpgsqlCommand($@"
|
||||||
|
SELECT c.name, COUNT(q.id) AS Total
|
||||||
|
FROM question q
|
||||||
|
INNER JOIN category c ON q.category_id = c.id
|
||||||
|
WHERE c.name IN ({whereCate})
|
||||||
|
AND q.level = '{DoKho}'
|
||||||
|
GROUP BY c.name
|
||||||
|
ORDER BY c.name;
|
||||||
|
", conn);
|
||||||
|
|
||||||
|
await using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await reader.ReadAsync())
|
||||||
|
{
|
||||||
|
categories.Add(new CategoryInfo
|
||||||
|
{
|
||||||
|
Category = reader.GetString(0),
|
||||||
|
Total = reader.GetInt32(1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Lỗi khi lấy danh sách số câu khó: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<List<CategoryInfo>> GetTotalCategoriesAsync(List<string> lstCategory)
|
public static async Task<List<CategoryInfo>> GetTotalCategoriesAsync(List<string> lstCategory)
|
||||||
{
|
{
|
||||||
var categories = new List<CategoryInfo>();
|
var categories = new List<CategoryInfo>();
|
||||||
@ -117,12 +159,12 @@ namespace QuizMaster.Service
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cmd = new NpgsqlCommand($@"
|
var cmd = new NpgsqlCommand($@"
|
||||||
SELECT c.name, COUNT(q.id) AS Total
|
SELECT c.name, COUNT(q.id) AS Total
|
||||||
FROM question q
|
FROM question q
|
||||||
INNER JOIN category c ON q.category_id = c.id
|
INNER JOIN category c ON q.category_id = c.id
|
||||||
WHERE c.name IN ({whereCate})
|
WHERE c.name IN ({whereCate})
|
||||||
GROUP BY c.name
|
GROUP BY c.name
|
||||||
ORDER BY c.name;
|
ORDER BY c.name;
|
||||||
", conn);
|
", conn);
|
||||||
|
|
||||||
await using var reader = await cmd.ExecuteReaderAsync();
|
await using var reader = await cmd.ExecuteReaderAsync();
|
||||||
@ -144,7 +186,6 @@ namespace QuizMaster.Service
|
|||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static async Task<List<QuestionOption>> getAllQA(string Category)
|
public static async Task<List<QuestionOption>> getAllQA(string Category)
|
||||||
{
|
{
|
||||||
var questionOption = new List<QuestionOption>();
|
var questionOption = new List<QuestionOption>();
|
||||||
@ -154,13 +195,12 @@ namespace QuizMaster.Service
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cmd = new NpgsqlCommand(@"
|
var cmd = new NpgsqlCommand(@"SELECT q.id, q.content, q.level, o.option_text, o.is_correct
|
||||||
SELECT q.id, q.content, o.option_text, o.is_correct
|
FROM question q
|
||||||
FROM question q
|
INNER JOIN question_option o ON o.question_id = q.id
|
||||||
INNER JOIN question_option o ON o.question_id = q.id
|
INNER JOIN category c ON q.category_id = c.id
|
||||||
INNER JOIN category c ON q.category_id = c.id
|
WHERE c.name = @category
|
||||||
WHERE c.name = @category
|
ORDER BY q.id, o.id
|
||||||
ORDER BY q.id, o.id;
|
|
||||||
", conn);
|
", conn);
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("category", Category);
|
cmd.Parameters.AddWithValue("category", Category);
|
||||||
@ -170,10 +210,11 @@ namespace QuizMaster.Service
|
|||||||
{
|
{
|
||||||
questionOption.Add(new QuestionOption
|
questionOption.Add(new QuestionOption
|
||||||
{
|
{
|
||||||
QuestionId = reader.IsDBNull(0) ? 0 : reader.GetInt32(0),
|
QuestionId = reader.GetInt32(0),
|
||||||
Question = reader.IsDBNull(1) ? string.Empty : reader.GetString(1),
|
Question = reader.GetString(1),
|
||||||
Option = reader.IsDBNull(2) ? string.Empty : reader.GetString(2),
|
DoKho = reader.IsDBNull(2) ? "" : reader.GetString(2),
|
||||||
IsCorrect = reader.IsDBNull(3) ? 0 : reader.GetInt32(3)
|
Option = reader.IsDBNull(3) ? string.Empty : reader.GetString(3),
|
||||||
|
IsCorrect = reader.IsDBNull(4) ? 0 : reader.GetInt32(4)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,37 +227,78 @@ namespace QuizMaster.Service
|
|||||||
return questionOption;
|
return questionOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static async Task<bool> InsertQuestionAndOptionsAsync(List<Quiz> questions)
|
public static async Task<bool> InsertQuestionAndOptionsAsync(List<Quiz> questions)
|
||||||
{
|
{
|
||||||
|
if (questions == null || questions.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
await using var conn = new NpgsqlConnection(DbHelper.connectionString);
|
await using var conn = new NpgsqlConnection(DbHelper.connectionString);
|
||||||
await conn.OpenAsync();
|
await conn.OpenAsync();
|
||||||
await using var transaction = await conn.BeginTransactionAsync();
|
await using var transaction = await conn.BeginTransactionAsync();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// --- 1. Cache categoryId ---
|
||||||
|
var categoryCache = new Dictionary<string, int>();
|
||||||
foreach (var q in questions)
|
foreach (var q in questions)
|
||||||
{
|
{
|
||||||
// Lấy category_id
|
if (!categoryCache.ContainsKey(q.LinhVuc))
|
||||||
var cmdCategory = new NpgsqlCommand("SELECT id FROM category WHERE name = @name", conn, transaction);
|
{
|
||||||
cmdCategory.Parameters.AddWithValue("name", q.LinhVuc);
|
var cmdCategory = new NpgsqlCommand(
|
||||||
var categoryIdObj = await cmdCategory.ExecuteScalarAsync();
|
"SELECT id FROM category WHERE name = @name", conn, transaction);
|
||||||
if (categoryIdObj == null)
|
cmdCategory.Parameters.AddWithValue("name", q.LinhVuc);
|
||||||
throw new Exception($"Category '{q.LinhVuc}' không tồn tại.");
|
var categoryIdObj = await cmdCategory.ExecuteScalarAsync();
|
||||||
|
if (categoryIdObj == null)
|
||||||
|
throw new Exception($"Category '{q.LinhVuc}' không tồn tại.");
|
||||||
|
categoryCache[q.LinhVuc] = (int)categoryIdObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int categoryId = (int)categoryIdObj;
|
// --- 2. Batch insert questions ---
|
||||||
|
var batchQuestions = new NpgsqlBatch(conn, transaction);
|
||||||
|
foreach (var q in questions)
|
||||||
|
{
|
||||||
|
var cmd = new NpgsqlBatchCommand(@"
|
||||||
|
INSERT INTO question (content, category_id, level)
|
||||||
|
VALUES (@content, @categoryId, @level)
|
||||||
|
RETURNING id;
|
||||||
|
");
|
||||||
|
cmd.Parameters.AddWithValue("content", q.CauHoi);
|
||||||
|
cmd.Parameters.AddWithValue("categoryId", categoryCache[q.LinhVuc]);
|
||||||
|
cmd.Parameters.AddWithValue("level", q.DoKho);
|
||||||
|
batchQuestions.BatchCommands.Add(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
// Insert Question
|
// --- 3. Execute batch question và lấy questionId ---
|
||||||
var cmdQuestion = new NpgsqlCommand(@"
|
var questionIds = new List<int>();
|
||||||
INSERT INTO question (content, category_id)
|
await using (var reader = await batchQuestions.ExecuteReaderAsync())
|
||||||
VALUES (@content, @categoryId)
|
{
|
||||||
RETURNING id;
|
foreach (var _ in questions)
|
||||||
", conn, transaction);
|
{
|
||||||
cmdQuestion.Parameters.AddWithValue("content", q.CauHoi);
|
if (!await reader.ReadAsync())
|
||||||
cmdQuestion.Parameters.AddWithValue("categoryId", categoryId);
|
throw new Exception("Không lấy đủ questionId từ batch.");
|
||||||
|
questionIds.Add(reader.GetInt32(0));
|
||||||
|
|
||||||
|
// Chuyển sang result set tiếp theo (mỗi INSERT RETURNING tạo 1 result set)
|
||||||
|
await reader.NextResultAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 4. Batch insert options ---
|
||||||
|
var batchOptions = new NpgsqlBatch(conn, transaction);
|
||||||
|
for (int i = 0; i < questions.Count; i++)
|
||||||
|
{
|
||||||
|
var q = questions[i];
|
||||||
|
var qid = questionIds[i];
|
||||||
|
|
||||||
|
if (q.DapAn == null || q.DapAn.Count == 0 || q.DapAn.Any(a => !"ABCD".Contains(a)))
|
||||||
|
{
|
||||||
|
var dapAnStr = q.DapAn != null ? string.Join(",", q.DapAn) : "(null)";
|
||||||
|
throw new Exception($"Câu hỏi '{q.CauHoi}' có đáp án không hợp lệ: {dapAnStr}");
|
||||||
|
}
|
||||||
|
|
||||||
int questionId = (int)await cmdQuestion.ExecuteScalarAsync();
|
|
||||||
|
|
||||||
// Insert QuestionOption
|
|
||||||
var options = new Dictionary<string, string?>
|
var options = new Dictionary<string, string?>
|
||||||
{
|
{
|
||||||
{ "A", q.A },
|
{ "A", q.A },
|
||||||
@ -227,19 +309,20 @@ namespace QuizMaster.Service
|
|||||||
|
|
||||||
foreach (var opt in options)
|
foreach (var opt in options)
|
||||||
{
|
{
|
||||||
var cmdOption = new NpgsqlCommand(@"
|
var cmdOption = new NpgsqlBatchCommand(@"
|
||||||
INSERT INTO question_option (question_id, option_text, is_correct)
|
INSERT INTO question_option (question_id, option_text, is_correct)
|
||||||
VALUES (@questionId, @optionText, @isCorrect);
|
VALUES (@questionId, @optionText, @isCorrect);
|
||||||
", conn, transaction);
|
");
|
||||||
|
cmdOption.Parameters.AddWithValue("questionId", qid);
|
||||||
cmdOption.Parameters.AddWithValue("questionId", questionId);
|
|
||||||
cmdOption.Parameters.AddWithValue("optionText", opt.Value ?? (object)DBNull.Value);
|
cmdOption.Parameters.AddWithValue("optionText", opt.Value ?? (object)DBNull.Value);
|
||||||
cmdOption.Parameters.AddWithValue("isCorrect", opt.Key == q.DapAn ? 1 : 0);
|
cmdOption.Parameters.AddWithValue("isCorrect", q.DapAn.Contains(opt.Key) ? 1 : 0);
|
||||||
|
batchOptions.BatchCommands.Add(cmdOption);
|
||||||
await cmdOption.ExecuteNonQueryAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- 5. Execute batch options ---
|
||||||
|
await batchOptions.ExecuteNonQueryAsync();
|
||||||
|
|
||||||
await transaction.CommitAsync();
|
await transaction.CommitAsync();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -250,6 +333,7 @@ namespace QuizMaster.Service
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static async Task<int> GetTotalQuestionCount()
|
public static async Task<int> GetTotalQuestionCount()
|
||||||
{
|
{
|
||||||
string query = "SELECT COUNT(*) FROM Question";
|
string query = "SELECT COUNT(*) FROM Question";
|
||||||
@ -267,26 +351,6 @@ namespace QuizMaster.Service
|
|||||||
return Convert.ToInt32(result);
|
return Convert.ToInt32(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//public static async Task<List<Question>> GetRandomQuestions(int requestedCount)
|
|
||||||
//{
|
|
||||||
// int totalCount = await GetTotalQuestionCount();
|
|
||||||
|
|
||||||
// if (requestedCount <= 0)
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("Vui lòng nhập số lượng lớn hơn 0.", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
||||||
// return new List<Question>();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (requestedCount > totalCount)
|
|
||||||
// {
|
|
||||||
// MessageBox.Show($"Chỉ có {totalCount} câu hỏi trong cơ sở dữ liệu.", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
||||||
// return new List<Question>();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// string query = $"SELECT * FROM Question ORDER BY RANDOM() LIMIT {requestedCount}";
|
|
||||||
// return await DbHelper.ExecuteSelectQuery<Question>(query);
|
|
||||||
//}
|
|
||||||
|
|
||||||
public static async Task<List<string>> GetDepartmentsAsync()
|
public static async Task<List<string>> GetDepartmentsAsync()
|
||||||
{
|
{
|
||||||
List<string> deplist = new List<string>();
|
List<string> deplist = new List<string>();
|
||||||
@ -316,5 +380,6 @@ namespace QuizMaster.Service
|
|||||||
return deplist;
|
return deplist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using OfficeOpenXml;
|
using OfficeOpenXml;
|
||||||
|
using Xceed.Document.NET;
|
||||||
|
|
||||||
namespace QuizMaster.Service
|
namespace QuizMaster.Service
|
||||||
{
|
{
|
||||||
@ -11,7 +13,7 @@ namespace QuizMaster.Service
|
|||||||
{
|
{
|
||||||
private static readonly List<string> ExpectedHeaders = new()
|
private static readonly List<string> ExpectedHeaders = new()
|
||||||
{
|
{
|
||||||
"Lĩnh vực", "Câu hỏi", "A", "B", "C", "D", "Đáp án"
|
"Lĩnh vực", "Câu hỏi", "A", "B", "C", "D", "Đáp án", "Độ khó"
|
||||||
};
|
};
|
||||||
|
|
||||||
public sealed class RowData
|
public sealed class RowData
|
||||||
@ -23,11 +25,14 @@ namespace QuizMaster.Service
|
|||||||
public string B { get; init; } = string.Empty;
|
public string B { get; init; } = string.Empty;
|
||||||
public string C { get; init; } = string.Empty;
|
public string C { get; init; } = string.Empty;
|
||||||
public string D { get; init; } = string.Empty;
|
public string D { get; init; } = string.Empty;
|
||||||
public string Answer { get; init; } = string.Empty;
|
public List<string> Answers { get; init; } = new List<string>();
|
||||||
|
public string Level { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<string> ValidateHeaders(OfficeOpenXml.ExcelWorksheet worksheet)
|
public static List<string> ValidateHeaders(OfficeOpenXml.ExcelWorksheet worksheet)
|
||||||
{
|
{
|
||||||
var errors = new List<string>();
|
var errors = new List<string>();
|
||||||
for (int i = 0; i < ExpectedHeaders.Count; i++)
|
for (int i = 0; i < ExpectedHeaders.Count; i++)
|
||||||
@ -50,6 +55,9 @@ namespace QuizMaster.Service
|
|||||||
if (string.IsNullOrWhiteSpace(data.Question))
|
if (string.IsNullOrWhiteSpace(data.Question))
|
||||||
errors.Add($"Dòng {data.Row}: 'Câu hỏi' không được trống");
|
errors.Add($"Dòng {data.Row}: 'Câu hỏi' không được trống");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(data.Level))
|
||||||
|
errors.Add($"Dòng {data.Row}: 'Độ khó' không được trống");
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,31 +79,40 @@ namespace QuizMaster.Service
|
|||||||
public static List<string> ValidateRowAnswer(RowData data)
|
public static List<string> ValidateRowAnswer(RowData data)
|
||||||
{
|
{
|
||||||
var errors = new List<string>();
|
var errors = new List<string>();
|
||||||
if (string.IsNullOrWhiteSpace(data.Answer))
|
|
||||||
|
if (data.Answers == null || data.Answers.Count == 0)
|
||||||
{
|
{
|
||||||
errors.Add($"Dòng {data.Row}: 'Đáp án' không được trống");
|
errors.Add($"Dòng {data.Row}: 'Đáp án' không được trống");
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
var valid = new[] { "A", "B", "C", "D" };
|
var validOptions = new HashSet<string> { "A", "B", "C", "D" };
|
||||||
if (!valid.Contains(data.Answer))
|
|
||||||
{
|
|
||||||
errors.Add($"Dòng {data.Row}: 'Đáp án' phải là A, B, C hoặc D (hiện tại là '{data.Answer}')");
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool answerPointsToEmpty = (data.Answer == "A" && string.IsNullOrWhiteSpace(data.A)) ||
|
foreach (var ans in data.Answers)
|
||||||
(data.Answer == "B" && string.IsNullOrWhiteSpace(data.B)) ||
|
|
||||||
(data.Answer == "C" && string.IsNullOrWhiteSpace(data.C)) ||
|
|
||||||
(data.Answer == "D" && string.IsNullOrWhiteSpace(data.D));
|
|
||||||
if (answerPointsToEmpty)
|
|
||||||
{
|
{
|
||||||
errors.Add($"Dòng {data.Row}: 'Đáp án' {data.Answer} không hợp lệ vì phương án {data.Answer} đang trống");
|
if (!validOptions.Contains(ans))
|
||||||
|
{
|
||||||
|
errors.Add($"Dòng {data.Row}: 'Đáp án' phải là A, B, C hoặc D (phát hiện '{ans}')");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmptyOption =
|
||||||
|
(ans == "A" && string.IsNullOrWhiteSpace(data.A)) ||
|
||||||
|
(ans == "B" && string.IsNullOrWhiteSpace(data.B)) ||
|
||||||
|
(ans == "C" && string.IsNullOrWhiteSpace(data.C)) ||
|
||||||
|
(ans == "D" && string.IsNullOrWhiteSpace(data.D));
|
||||||
|
|
||||||
|
if (isEmptyOption)
|
||||||
|
{
|
||||||
|
errors.Add($"Dòng {data.Row}: 'Đáp án' {ans} không hợp lệ vì phương án {ans} đang trống");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//________________________________________________________________________________________________
|
||||||
|
|
||||||
public static List<string> ValidateRowDuplicate(RowData data, Dictionary<string, int> questionOptionDict)
|
public static List<string> ValidateRowDuplicate(RowData data, Dictionary<string, int> questionOptionDict)
|
||||||
{
|
{
|
||||||
var errors = new List<string>();
|
var errors = new List<string>();
|
||||||
@ -134,6 +151,12 @@ namespace QuizMaster.Service
|
|||||||
var firstCell = worksheet.Cells[row, 1];
|
var firstCell = worksheet.Cells[row, 1];
|
||||||
if (string.IsNullOrWhiteSpace(firstCell.Text)) break; // Dòng trống → kết thúc
|
if (string.IsNullOrWhiteSpace(firstCell.Text)) break; // Dòng trống → kết thúc
|
||||||
|
|
||||||
|
var answerText = worksheet.Cells[row, 7].Text.Trim().ToUpper();
|
||||||
|
var answers = Regex.Matches(answerText.ToUpper(), "[ABCD]")
|
||||||
|
.Select(m => m.Value.Trim())
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var data = new RowData
|
var data = new RowData
|
||||||
{
|
{
|
||||||
Row = row,
|
Row = row,
|
||||||
@ -143,7 +166,8 @@ namespace QuizMaster.Service
|
|||||||
B = worksheet.Cells[row, 4].Text.Trim(),
|
B = worksheet.Cells[row, 4].Text.Trim(),
|
||||||
C = worksheet.Cells[row, 5].Text.Trim(),
|
C = worksheet.Cells[row, 5].Text.Trim(),
|
||||||
D = worksheet.Cells[row, 6].Text.Trim(),
|
D = worksheet.Cells[row, 6].Text.Trim(),
|
||||||
Answer = worksheet.Cells[row, 7].Text.Trim().ToUpper()
|
Answers = answers,
|
||||||
|
Level = worksheet.Cells[row, 8].Text.Trim()
|
||||||
};
|
};
|
||||||
|
|
||||||
errors.AddRange(ValidateRowRequired(data));
|
errors.AddRange(ValidateRowRequired(data));
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using OfficeOpenXml;
|
using OfficeOpenXml;
|
||||||
using QuizMaster.Response;
|
using QuizMaster.Response;
|
||||||
@ -21,6 +22,8 @@ namespace QuizMaster.Service
|
|||||||
|
|
||||||
for (int row = 2; row <= rowCount; row++) // Bắt đầu từ dòng 2, bỏ dòng tiêu đề
|
for (int row = 2; row <= rowCount; row++) // Bắt đầu từ dòng 2, bỏ dòng tiêu đề
|
||||||
{
|
{
|
||||||
|
var answerText = worksheet.Cells[row, 7].Text.Trim().ToUpper();
|
||||||
|
|
||||||
var ch = new Quiz
|
var ch = new Quiz
|
||||||
{
|
{
|
||||||
LinhVuc = worksheet.Cells[row, 1].Text,
|
LinhVuc = worksheet.Cells[row, 1].Text,
|
||||||
@ -29,13 +32,16 @@ namespace QuizMaster.Service
|
|||||||
B = worksheet.Cells[row, 4].Text,
|
B = worksheet.Cells[row, 4].Text,
|
||||||
C = worksheet.Cells[row, 5].Text,
|
C = worksheet.Cells[row, 5].Text,
|
||||||
D = worksheet.Cells[row, 6].Text,
|
D = worksheet.Cells[row, 6].Text,
|
||||||
DapAn = worksheet.Cells[row, 7].Text
|
|
||||||
};
|
|
||||||
|
|
||||||
|
DapAn = Regex.Matches(answerText.ToUpper(), "[ABCD]")
|
||||||
|
.Select(m => m.Value.Trim())
|
||||||
|
.Distinct()
|
||||||
|
.ToList(),
|
||||||
|
DoKho = worksheet.Cells[row, 8].Text
|
||||||
|
};
|
||||||
result.Add(ch);
|
result.Add(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user