乐趣区

论某教育机构考试系统设计

前言
近期在做一套答题系统,参考了某教育机构的设计。本章跟大家聊聊考试系统中的核心 – 如何考试?
简单点说,所谓考试系统就是答题系统,通过答题完成进行判分后返回其答题结果即完成整个流程。
当然过程中有些数据需要存储,有些则可在后期查询计算(个人理解),如有误导请速喷

如上图所示,一套试卷有 N 道试题,每道试题又是由题干与选项、答案组成,这样才汇聚了完整的一套答题(考试)系统。
试卷
一次考试(问卷)则使用一套试卷,考试(问卷)与考试则为一对一的关系,而试卷与考试(问卷)则是多对多的关系
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)

而类似字段实际不应加在试卷上,上面已经说过了试卷与考试是多对多的关系,所以上述字段应加入在考试表中。
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 绑定对应试卷。

题库
题库与试卷没有关系,是以试题为对象的分类管理罢了。将试题归类后在添加试卷动作时选择试题比较方便。
当然,他也是一个多对多的关系。
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 端) 更保险一些。
致谢
本章的内容到此结束,感谢你看到这里,希望本篇可以帮到你。谢谢!

退出移动版