論某教育機構考試系統設計

clipboard.png

前言

近期在作一套答題系統,參考了某教育機構的設計。本章跟你們聊聊考試系統中的核心 - 如何考試?mysql

簡單點說,所謂考試系統就是答題系統,經過答題完成進行判分後返回其答題結果即完成整個流程。web

固然過程當中有些數據須要存儲,有些則可在後期查詢計算(我的理解),若有誤導請速噴sql

clipboard.png

如上圖所示,一套試卷有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;

這只是一份簡單的設計,具體要看實際需求,若是是考試相關需求須要添加異步

  • 考試時間 (time)
  • 考試及格分數 (grade)

而相似字段實際不該加在試卷上,上面已經說過了試卷與考試是多對多的關係,因此上述字段應加入在考試表中。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綁定對應試卷。編碼

clipboard.png

題庫

題庫與試卷沒有關係,是以試題爲對象的分類管理罷了。將試題歸類後在添加試卷動做時選擇試題比較方便。spa

clipboard.png
固然,他也是一個多對多的關係。設計

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寫的太複雜,其後者則是擴展性不夠強,低版本不兼容。

clipboard.png

判分

到判分這步算是整個考試完成了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)

clipboard.png

考試畢竟不是一道題那麼簡單,你能夠選擇迭代去完成。若是題目數量比較大。或者用戶相對集中,建議仍是使用隊列去異步完成判分操做並經過socket或者其餘方式通知到客戶端(web端)更保險一些。

致謝

本章的內容到此結束,感謝你看到這裏,但願本篇能夠幫到你。謝謝!

相關文章
相關標籤/搜索