近期在作一套答題系統,參考了某教育機構的設計。本章跟你們聊聊考試系統中的核心 - 如何考試?mysql
簡單點說,所謂考試系統就是答題系統,經過答題完成進行判分後返回其答題結果即完成整個流程。web
固然過程當中有些數據須要存儲,有些則可在後期查詢計算(我的理解),若有誤導請速噴sql
如上圖所示,一套試卷有N道試題,每道試題又是由題干與選項、答案組成,這樣才匯聚了完整的一套答題(考試)系統。json
一次考試(問卷)則使用一套試卷,考試(問卷)與考試則爲一對一的關係,而試卷與考試(問卷)則是多對多的關係數組
CREATE TABLE `company_paper` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '試卷名稱', `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
這只是一份簡單的設計,具體要看實際需求,若是是考試相關需求須要添加異步
而相似字段實際不該加在試卷上,上面已經說過了試卷與考試是多對多的關係,因此上述字段應加入在考試表中。socket
CREATE TABLE `company_examine` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `paper_id` int(11) NOT NULL COMMENT '試卷編碼', `start_time` int(11) NOT NULL COMMENT '開考時間', `time_limit` int(11) NOT NULL COMMENT '限時', `score` double NOT NULL COMMENT '經過分數', `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
上述爲考試表,考試表經過paper_id綁定對應試卷。編碼
題庫與試卷沒有關係,是以試題爲對象的分類管理罷了。將試題歸類後在添加試卷動做時選擇試題比較方便。spa
固然,他也是一個多對多的關係。設計
CREATE TABLE `company_question_database` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '題庫名稱', `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
如上述表結構,題庫即爲分類,因此沒有過分設計。
試題應該算是整個系統設計過程當中比較繁瑣的一部分了。先來看下數據表
CREATE TABLE `company_question` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `database_id` int(11) NOT NULL COMMENT '所屬題庫', `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '題目', `option` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '選項', `answer` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '答案', `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '類型 0單選 1多選', `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
首先按照傳統考試的試卷將試題分爲三大部分
這三大部分彙總爲一道題,這裏的option與answer選擇使用序列化方式去存儲
// 選項 >>> serialize (["A"=>"選項A","B"=>"選項B"]) => "a:2:{s:1:"A";s:7:"選項A";s:1:"B";s:7:"選項B";}" // 答案 >>> serialize (["A"]) => "a:1:{i:0;s:1:"A";}"
沒有使用json方式存儲有倆點緣由,自認爲mysql對json的查詢作的不夠完善,sql寫的太複雜,其後者則是擴展性不夠強,低版本不兼容。
到判分這步算是整個考試完成了80%,那是不可能的,實際完成了不到50%的功能。依舊引用電商相關文章的那句話
把能存儲的所有存起來
判分這裏是這樣作的
CREATE TABLE `company_user_paper` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT '用戶編碼', `paper_id` int(11) NOT NULL COMMENT '試卷編碼', `answer` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '答案', `score` double(8,2) NOT NULL DEFAULT '0.00' COMMENT '得分', `correct` double(8,2) NOT NULL DEFAULT '0.00' COMMENT '正確率', `date_length` int(11) NOT NULL DEFAULT '0' COMMENT '考試用時長', `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
見上表,將用戶每次考試的動做細節所有記錄,方便查詢,答案這塊依舊使用的序列化的方式。在檢查答案時,直接反序列化計算數組差集既完成判分,獲取交集也是沒問題的。
$answerArr = unserialize($answer) $successAnswerArr = unserialize($successAnswer) array_diff($answerArr,$successAnswerArr)
考試畢竟不是一道題那麼簡單,你能夠選擇迭代去完成。若是題目數量比較大。或者用戶相對集中,建議仍是使用隊列去異步完成判分操做並經過socket或者其餘方式通知到客戶端(web端)更保險一些。
本章的內容到此結束,感謝你看到這裏,但願本篇能夠幫到你。謝謝!