系统设计 考试系统离不开数据库系统的支持,不论是试题、答案,还是考生信息都需要存放在数据库中,而且数据库独立于程序而存在,具有较好的安全性。本系统使用的数据库软件为SQL Server 2000。首先建立一名为ksxt的数据库,主要表格介绍如下: 3.1.1 考生信息表(stuinfo) 列名 数据类型 长度 允许空 Id Nvarchar 10 Name Nvarchar 8 State Nvarchar 6 √ 该表主要存放考生的信息,其中Id表示考生的准考证号;Name表示考生的姓名;State表示考生状态,分为三种:已交卷、未交卷(正在考试中)、缺考。考生登录的时候输入准考证号,从该表中检查是否存在该准考证号,如果存在,显示该考生姓名,允许进入考试界面;否则显示“无此考生”。State字段有助于统计缺考人数。 3.1.2 各类试题表(xuanze,tiankong,panduan,chengxtk,chengxts,chengxsj) 主要包括选择题表、判断题表、概念填空题表、程序填空题表、程序调试题表、程序设计题表共6张表,每张表中存放了各类试题的题号和题目。下面以程序设计题表为例说明: 列名 数据类型 长度 允许空 TH Char 2 √ XTH Char 2 √ TM Ntext 16 √ Ole Image 16 √ 其中TH表示该试题在第几套题目中;XTH表示该试题的题号,即这套题目中的2个程序设计题中的第几题;TM表示该试题的题目描述;Ole字段存放的为考试时要读出来,解压,供考生下载的压缩文件。如果是选择题表,还有A、B、C、D四个字段分别表示该试题四个选项的内容。除了程序设计题以外,其他试题表没有Ole字段。之所以设TH字段,是因为试题是按套分的,每一套中又有若干题目。每套中的题目事先就定好的,但是每次抽到该套题目时,试题的顺序是打乱的,以减少出现一模一样试卷的概率。 3.1.3 考试信息表(testresult01—testresult99) 列名 数据类型 长度 允许空 Id Nvarchar 10 Xuanzth Char 2 √ Pandth Char 2 √ Tiankth Char 2 √ Chengxtkth Char 2 √ Chengxtsth Char 2 √ Chengxsjth Char 2 √ Xuanzda Nvarchar 40 √ Panda Nvarchar 20 √ Tiankda Nvarchar 100 √ Chengxtkda Nvarchar 100 √ Chengxtsda Image 16 √ chengxsjda Image 16 √ Lasttime Int 4 √ 考试信息表共有99张,根据考生准考证号后两位来决定把该考生的考试信息放入哪张表中,比如该考生准考证号末两位为28,则放入表testresult28中。其中Id表示考生的准考证号;Xuanzth、pandth、Tiankth、Chengxtkth、Chengxtsth、Chengxsjth分别表示选择题、判断题、概念填空题、程序填空题、程序调试题、程序设计题的题号;Xuanzda、pandda、Tiankda、Chengxtkda、Chengxtsda、Chengxsjda分别表示选择题、判断题、概念填空题、程序填空题、程序调试题、程序设计题的正确答案。Lasttime用于记录考试时间,如果时间到了还没有交卷,则回收答案,停止考试。 3.1.4 回收表(reclaim,result) 回收表共有两张,一张记录回收的答案,另一张记录回收是否成功。 表1 列名 数据类型 长度 允许空 Id Nvarchar 10 Xuanzth Char 2 √ Pandth Char 2 √ Tiankth Char 2 √ Chengxtkth Char 2 √ Chengxtsth Char 2 √ Chengxsjth Char 2 √ Xuanzda Nvarchar 40 √ Panda Nvarchar 20 √ Tiankda Nvarchar 100 √ Chengxtkda Nvarchar 100 √ Chengxtsda Image 16 √ chengxsjda Image 16 √ 这张表主要用来记录回收的答案,其中Xuanzth、Pandth、Tiankth、Chengxtkth、Chengxtsth、Chengxsjth分别表示选择题、判断题、概念填空题、程序填空题、程序调试题、程序设计题的题号,Xuanzda、Pandda、Tiankda、Chengxtkda、Chengxtsda、Chengxsjda分别表示考生的选择题、判断题、概念填空题、程序填空题、程序调试题、程序设计题的答案,可与考试信息表中各题的正确答案做比较。 表2 列名 数据类型 长度 允许空 Id Nvarchar 10 Name Nvarchar 8 √ Xuanze Char 2 √ Pand Char 2 √ Tiank Char 2 √ Chengxtk Char 2 √ Chengxts Char 2 √ Chengxsj Char 2 √ 这张表主要用来判断回收是否成功。其中Id表示考生的准考证号;Name表示考生的姓名;Xuanze、Pand、Tiank、Chengxtk、Chengxts、Chengxsj分别表示选择题、判断题、概念填空题、程序填空题、程序调试题、程序设计题是否回收成功,如果成功,则为OK,否则为空。 3.1.5管理表(setting) 列名 数据类型 长度 允许空 Dbname Nvarchar 10 √ Servername Nvarchar 10 √ Sqlpwd Nvarchar 10 Testdir Nvarchar 40 √ Testtype Nvarchar 4 √ Relaimdir Nvarchar 40 √ redopwd Nvarchar 10 其中Dbname表示数据库名称;Servername表示服务器名称;Sqlpwd表示SQL Server服务器密码;Testdir表示考试目录;Testtype表示考试类型;Relaimdir表示回收目录;redopwd表示重做密码。有些考生考试时可能会因为误操作而退出了系统,这时候要再次进入系统进行考试,就需要输入密码,以防止作弊行为。重做密码是在考生第一次进入系统时从该表中获得的。 该考试系统主要有6个模块构成,包括题库管理模块、身份验证模块、各类试题模块、监考管理模块、阅卷模块、缺考统计模块。各模块关系如图1所示。下面分别介绍这6个模块。 题库管理模块实现了试题管理与试卷形成功能。试题的管理主要包括试题编辑、试题修改。在该考试系统中,预计准备20套选择题、填空题、判断题、程序分析题和程序设计题,每套的题目都是事先定好的。每套试卷形成时,随机抽取各类试题的题号,可能两次抽到相同题号试题的概率是比较大的,但每次试题的顺序都是打乱的,以减少出现重复试卷的概率。 考生登录系统时,需要输入准考证号,根据准考证号到相应的数据库表(这里是“考生信息表”)中查找是否有该考生存在。如果有此准考证号,表示存在该考生,显示该考生的姓名;否则提示“没有该考生信息,请确认后重新输入”。当已经确认存在该考生时,还需要判断该考生是否第一次进入系统,如果是第一次,则进行组题,抽取题号;如果不是第一次,则进入另一个页面,要求输入重做密码,直到密码输入正确才能进入考试界面,并且考试的试题内容与顺序都和上次进入时的一样。重做密码是在考生第一次进入系统时获得的。流程图如图2所示。 1)选择题模块 初次进入选择题界面时,显示第一个题目的内容。可以用“上题”、“下题” 按钮来选择不同的题目,在选择“上题”或“下题”前,先要记录下本题的答案(在客户端执行)。可以用“保存”按钮来上传答案,即把考生的答案写入回收表reclaim中(在服务器端执行)。 2)判断题模块、概念填空题模块、程序填空题模块同上。 3)程序调试题模块 同样可以用“上题”、“下题” 按钮来选择不同的题目。可以用“下载”按钮来建立程序调试题存放的文件夹,并下载题目(是一个压缩文件);通过“上传”按钮把最终结果上传到指定的目录。 4)程序设计题模块同上 该模块提供考试用的操作界面,同时提供考试的操作指南,以供考生参考。考生的准考证号、姓名,始终显示在状态栏上,以便监考人员查验。 可查询考生的剩余时间、交卷否和是否正在考试等状态信息,在考试过程中,对考生的合法性和唯一性进行监控。考生如有疑问,可以“帮助”按钮来解决问题。 对考生的答案进行阅卷评分。目前这块没有实现。 统计有多少考生没有参加考试。可通过“考生信息表”中的State字段进行统计。通过这个字段还可以统计某一时刻有多少考生正在考试,有多少以已经交卷。 该考试系统采用三层结构,即数据库服务器、Web服务器、客户浏览器。因为它是在Internet网上进行测试,为了确保Web服务器安全,要求把数据库与Web服务器分离,也就是说采用子网内部的一台服务器作为数据库服务器。为了实现可用子网内的任何一台服务器作为数据库服务器的需求,该系统采用Web服务技术,即把Web服务装在Web服务器中,通过访问Web服务来进行数据库的访问。 该系统的Web服务描述如下: 系统实现 在该系统中,连接数据库的方法有两种,一种是通过SQL查询(利用SqlConnection类来连接SQL Server 2000),另一种是通过OLEDB技术(利用OleDbConnection类来连接几种不同类型的数据库)。前一种方法是专门针对SQL Server的,后一种方法是为了操作其他数据库,如Access、Foxpro等。当然,操作SQL Server也可以用后一种方法,但是这样做性能比较差。 程序调试题和程序设计题在数据库中是以文件的形式存放的,因此需要用二进制流写或读字段。在SQL和在Access中两者操作方式是不一样的。以读二进制字段为例。 4.1.1 在Access中读二进制字段 主要代码如下: DimPictureCol As Integer= 0 Dim cn As NewOleDbConnection(OleConnection) Dim cmdAs NewOleDbCommand() cmd.CommandText = "SELECT chengxtsdaFROM result WHERE id='" & idnumber & "'" Dim dr As OleDbDataReader = cmd.ExecuteReader() dr.Read() Dimb(dr.GetBytes(PictureCol, 0, Nothing, 0, Integer.MaxValue) - 1) AsByte dr.GetBytes(PictureCol, 0, b, 0,b.Length) Dim fs As NewSystem.IO.FileStream(DestFilePath,IO.FileMode.Create, IO.FileAccess.Write) fs.Write(b, 0, b.Length) 4.1.2 在SQLServer中读取二进制信息 主要代码如下: Dimmyconnection As SqlConnection = New SqlConnection(StrConnection) DimmyCommand As SqlCommand = New SqlCommand() Dimsqlrd As SqlDataReader myCommand.CommandText = "SELECT" & field & " FROM " & table & " WHEREid='" & thnumber & "'" sqlrd =myCommand.ExecuteReader(CommandBehavior.SingleRow) Dimbytedata() As Byte Whilesqlrd.Read() If Not (sqlrd.IsDBNull(0)) Then bytedata = sqlrd.GetValue(0) readblob = bytedata EndIf End While 前面提到,每套试卷形成时,随机抽取各类试题的题号,同一套试题中的题目每次出现的顺序都是不一样的,即序号是被打乱的。打乱序号算法的主要代码如下: Dimseq, Mainloop, ChosenNumber, n, i As Integer DimA(MaxNumber), B(MaxNumber) As Integer Dim rndAs New Random() For seq= 1 To MaxNumber B(seq) = seq Next ForMainloop = MaxNumber To 1 Step -1 ChosenNumber = rnd.Next(1,Mainloop) A(MaxNumber - Mainloop + 1) =B(ChosenNumber) B(ChosenNumber) = B(Mainloop) Next randomorder = A 做程序调试和程序设计题时,需要先下载题目,为一个压缩文件,下载时需要进行解压缩。当编程完毕后,需要上传答案,这时候又要对文件进行压缩,再传到指定目录。 解压缩文件算法的主要代码(其中fname为要解压缩的文件,unzipdir为解压之后的文件所存放的位置): Dim s As ZipInputStream = New ZipInputStream(File.OpenRead(fname)) Dim theEntry AsZipEntry = s.GetNextEntry() Try While (theEntry.Size >= 0) Dim directoryName As String = unzipdir &Path.GetDirectoryName(theEntry.Name) Dim fileName As String = Path.GetFileName(theEntry.Name) Directory.CreateDirectory(directoryName) If (fileName <> String.Empty)Then Dim streamWriter As FileStream streamWriter = File.Create(directoryName & "\" &fileName) Dim size AsInteger = 2048 Dim data(2048) AsByte While (True) size = s.Read(data, 0, data.Length) If (size > 0) Then streamWriter.Write(data, 0, size) Else Exit While End If End While streamWriter.Close() End If 压缩文件算法的主要代码(其中testdir指要压缩文件的位置,filename指压缩后文件的名字): Dim astrFileNames() As String = Directory.GetFiles(testdir) Dim strmZipOutputStream AsZipOutputStream strmZipOutputStream = NewZipOutputStream(File.Create(filename)) REM Compression Level: 0-9 REM 0: no(Compression) REM 9: maximum compression strmZipOutputStream.SetLevel(6) Dim objCrc32 As New Crc32() Dim strFile As String Dim strFold As String For Each strFile In astrFileNames Dim strmFile AsFileStream = File.OpenRead(strFile) Dim abyBuffer(strmFile.Length - 1) As Byte Dim substrfile As String = strFile.Substring(Len(testdir) + 1,Len(strFile) - Len(testdir) - 1) strmFile.Read(abyBuffer, 0, abyBuffer.Length) Dim objZipEntry AsZipEntry = New ZipEntry(substrfile) objZipEntry.DateTime =DateTime.Now objZipEntry.Size = strmFile.Length strmFile.Close() objCrc32.Reset() objCrc32.Update(abyBuffer) objZipEntry.Crc = objCrc32.Value strmZipOutputStream.PutNextEntry(objZipEntry) strmZipOutputStream.Write(abyBuffer, 0, abyBuffer.Length) Next DirSearch(testdir, strmZipOutputStream) 源文件
3.1 考试系统的数据库设计
3.2 考试系统的构成模块
3.2.1 题库管理模块
3.2.2身份验证模块
3.2.3各类试题模块
3.2.4监考管理模块
3.2.5阅卷模块
3.2.6缺考统计模块
3.3 考试系统的特点
数据库操作
4.2 打乱序号算法
4.3 文件的压缩与解压缩
版权所有© 帮我毕业网 并保留所有权利