金強 王亮 方春華
摘 要:本文詳細地闡述了基于PHP、Mysql、Smarty技術的大學計算機信息技術課程在線考試系統的設計與實現,作者以一次正式考試的流程介紹了系統數據庫中主要幾個數據表的設計和作用,剖析了在線考試組卷的方法及過程,闡述了從考生登錄、考試頁面生成、考試中頁面的檢查、試卷的提交、答案的保存、考試的評分到成績的查詢等全部過程的設計方法,以圖文并茂的方式介紹了系統前、后臺頁面功能設計,并對整個考試系統的性能進行了測試與完善。
關鍵詞:計算機信息技術;PHP;Mysql;Smarty;在線考試
中圖分類號:TP311.5 文獻標識碼:A
文章編號:2096-1472(2018)-11-59-04
1 引言(Introduction)
當今,計算機與信息技術的應用已滲透到幾乎所有的學科和專業,“計算機信息處理”已成為高等學校普遍開設的公共基礎課[1],江蘇省每位大學生都需要參加省計算機一級統考,但由于省考練習系統機考理論部分沒有評分系統,學生在做了理論題后不知道對錯,更沒有答案解析,因此有必要設計一個考試系統,把歷年考試的理論試題,按照題型、分值、答案、必要的解析和最后的評分融合在一起,用這個系統對學生進行理論知識的強化訓練,使學生較好地掌握理論知識、通過考試,隨著互聯網技術的不斷發展,基于Web的在線考試系統應運而生[2],從開發技術的角度進行劃分,目前的web網頁可以分為前端開發和后臺的開發[3],本系統基于PHP、Mysql和Smarty技術,采用B/S模式,前后臺通過PHP和Smarty模板進行數據庫操作和頁面的生成,能夠實現在線考試及評分。
2 在線考試系統的設計(Design of online examination system)
2.1 數據庫設計
數據庫名為db_online,它主要包含以下數據表:用戶表(tb_user)、正式考試考生表(tb_examination_user)、正式考試試卷表(tb_examination)、模擬考試考生表(tb_mockexaminations_user)、模擬考試試卷表(tb_mockexaminations)、在線考生表(tb_onlineuser)、課程分類表(tb_types_course)、卷面題型分配模板表(tb_problemtemplate)、卷面總分、及格分數線表(tb_examattribute)、試題表(tb_exam_problem)、試卷題型表(tb_exam_type)、難度系數表(tb_degree)、單項練習表(tb_useranswer)它們之間的關系如下圖所示:
圖1中所有表的text類型和varchar類型的字段編碼均為utf8_unicode_ci,數據庫存儲引擎為MyISAM,下面以計算機基礎課程的一次正式考試流程來介紹幾個主要數據表(以下簡稱試題表、試卷表、模板表、考生表)的內容:管理員在后臺使用試題表(包含`id`,`content`,`search_list`,`answer`,`fraction`,`pro_type`,`pro_class`,`upload_date`,`resolve`,`isactive`,`degreeid`,`sound`,`mustknown`字段)手工添加試題,表中`id`字段是每條試題的試題號,int類型,自動增長,具有唯一性,`content`字段填寫試題內容,text類型,`search_list`字段填寫每種題型的選項個數,整型,本課程單選題(radio)、多選題(checkbox)個數取4,判斷題(judgment)和填空題(fill)取0,`answer`字段填寫每題正確答案,text類型,`fraction`字段填寫每題分值,int類型,`pro_type`字段填寫題型,varchar類型,`pro_class`字段填寫課程類別,int類型,`upload_date`字段填寫試題添加或更新日期,date類型,`resolve`字段填寫試題解析,text類型,`isactive`字段填寫試題是否啟用或禁用,varchar類型,`degreeid`字段填寫難度系數,int類型,對應難度系數表中的較易、中等、較難3個選項,`mustknown`字段填寫是否必須掌握,int類型,默認為1(必須掌握),`sound`字段填寫語音上傳文件(可選),varchar類型。由于信息技術課程只有單選、判斷和填空三種題型,因此試題表中無需添加多選題,當數據庫中添加了一定數量不同題型的試題后,管理員便可隨機生成試卷表(包含`id`,`radio`,`checkbox`,`fill`,`judgment`,`title`,`pro_class`,`exam_user`,`start_exam`,`over_exam`,`dates`,`templateid`字段),表中的`id`字段填寫的是生成的試卷號,int類型,自動增長,具有唯一性,`radio`、`fill`、`judgment`三個字段分別填寫的是由隨機選出的3種不同題型的試題號組成的字符串,text類型,每個試題號對應于試題表的`id`字段值,每種題型由試題號之間的@符號連接而成,譬如`radio`字段:9475@9493@9494@9495,數字9475代表試題表中某條試題的`id`值,而非試題內容,字符串的長度或者準確說每種題型的個數依據`templateid`字段值,`title`字段填寫試卷標題,text類型,`pro_class`字段填寫課程類別,int類型,`exam_user`字段填寫參加考試人員,text類型,其值是一組由@符號組成的字符串,譬如90@88@89,數字90表示用戶表中的`id`用戶,`start_exam`字段填寫開考準確時間,`over_exam`填寫考試結束時間,兩個字段均為varchar類型,`dates`填寫試卷生成的日期,date類型,`templateid`字段填寫試卷模板,int類型,其值等于模板表(包含`id`,`name`,`emattrid`,`typedistribute`,`degreedistribute`字段)的`id`字段值,譬如信息技術課程的`templateid`值為29,其值就是模板表id為29的值,管理員在隨機生成試卷時,首先要選擇課程類別和試卷模版,試卷模板依據模板表的`typedistribute`字段,譬如信息課程的模板為radio@50@checkbox@0@fill@20@judgment@30,表示單選題50分,填空題20分,判斷題30分,無多選題。模板表中`id`字段表示試卷模板號,int類型,自動增長,具有唯一性,`name`字段填寫模板名稱,varchar類型,`emattrid`字段填寫與總分、及格分數線表關聯的`id`值,int類型,`typedistribute`字段填寫題型分配,`degreedistribute`字段填寫難度系數分配,二者均為varchar類型。每場考試完畢,系統要把考試結果填寫到考生表(包含`id`,`title`,`examination_id`,`name`,`admission`,`pro_class`,`fraction`,`sub_answer`,`sub_time`,`nameid`字段)中,表中`id`字段填寫考試編號,int類型,自動增長、唯一,`title`字段填寫試卷標題,varchar類型,examination_id`字段填寫試卷`id`號,int類型,其值與試卷表的`id`相關聯,`name`字段、`admission`字段,分別填寫考生姓名、準考證號,varchar類型,`pro_class`字段填寫課程類別、`fraction`字段填寫成績總分,int類型,`sub_answer`字段填寫考試答案,text類型,其值是形如*9541@radio@A@A@1*9491...@judgment@正確@正確@1*...*9517@fill@路由器@路由器@1*...的一個長字符串,每條試題答案之間用“*”連接,`sub_time`字段填寫試卷提交日期和時間,datetime類型,`nameid`字段填寫考生`id`,int類型,其值與用戶表的`id`相關聯。
2.2 組卷過程設計
組卷時,系統首先通過試卷模板得到題型和數量,然后通過隨機函數抽題,如果抽題成功,則將生成的試卷號`id`值添加到數據庫試卷表中,通常情況下,每個課程的考題數量要大于試卷模板要求的考題數量,譬如信息技術課程單選題有500多條(當然我們可以通過啟用和禁用字段進行選擇),而試卷模板單選題只考50條(每題1分,也可每題2分25條),因此隨機抽題時,抽題的范圍是500條,而抽到試題的數量由模板表下此題型的數量決定,假如500條單選題通過禁用,剩下30條,如果還是每條1分,顯然題數不夠,不能成功抽取,如果每題2分,那就在30條里面抽取25條,試題越多,分散度就越大,以單選題抽取為例,系統使用array_rand($radios,number)函數隨機從試題表中取得number數量個單選題鍵名(即ID值)組成的數組,通過for語句循環讀取獲取的鍵值,然后根據鍵值從試題表中獲取指定`id`的試題,并添加到試題數組中,最后通過$radio=implode('@',$radio_exam),對生成的試題數組進行由數組到字符串的轉換,以@為分隔符,形如9475@9493@9494@...@9689,最后將變量$radio通過SQL插入語句填寫到試卷表對應的`radio`字段中,字符串@的個數即為單選題的數量,系統獲得所有題型和數量之后,將試卷標題、考試時間一并添加進試卷表,組卷成功。
2.3 考試和評分過程設計
下面以正式考試情景介紹考試和評分過程的設計,考生在前臺頁面選擇正式考試單元,系統彈出登錄窗體,考生輸入準考證號、密碼,在下拉列表中選擇考試名稱,點擊登錄按鈕,開始進入考試,這里要說明的是考試名稱除了教師在后臺生成的名稱之外,考生還可以選擇隨機生成考卷,系統根據考生的準考證號,查詢用戶數據表,取得考生的課程類別,根據課程類別和該課程類別下一個固定的試卷模版,生成名為隨機考試的試卷,其抽題原理與后臺管理員組卷過程基本相同。考生登錄時的準考證號和密碼如果和用戶表中一致,系統便會讀取試卷表中的開考時間,如果登錄時間與開考時間相同,則開始考試,如果開考時間未到,系統會彈出考試時間未到并顯示等待時間窗口,如果考試時間已超過15分鐘,會彈出已超時窗口。考生登錄成功后,系統會將考生id、試卷id、準考證號、姓名、開考科目等信息存儲到服務器的Session變量中,然后系統根據Session變量中的試卷id值,去數據庫試卷表中查詢得到試卷標題、開考時間和結束時間,并將上述時間分別轉換為unix時間戳,存儲到服務器Session變量中,同時根據兩個unix時間戳的差值計算考試總時間,具備以上條件,則可生成考試頁面。
生成的考試頁面應包含考生姓名、準考證號、考核類型、試卷標題、題型、數量、分值、考試計時、剩余時間,以及每條具體試題內容,由于存儲在試卷表中的試題是按題型分類的試題題號,而不是試題內容本身,因此要根據試卷表中的每個題型的id值,去試題表中將具體試題內容查詢出來,下面以單選題(radio)為例,分析如何根據試題題號得到具體試題內容的過程:系統首先根據試卷的id值,通過$radio=explode('@',$kst['radio'])函數讀取試卷表中單選題(`radio`字段)中的數據,將形如9475@9493@9494@...樣式的字符串拆分成數組,然后通過for循環語句讀取數組中每條單選題的id,根據此id值向試題表查詢得到試題內容,譬如題號id為9475,則可在試題表中將id為9475的試題內容(`content`字段)讀取出來,用同樣的方法可取得所有題型的考試試題。考生進入考試后,系統運用Ajax技術,無刷新實現在考試頁面頭部顯示考試計時時間和剩余時間,考試剩余時間由SESSION變量中的考試結束時間值減去當前時間的unix時間戳得到,而計時開始時間值為當前unix時間戳減去SESSION變量中的開考時間,系統運用jQuery Ajax的post方法,利用回調函數來實現考試期間已答和未答試題的統計顯示,采用數組$sub_answer=array()存儲考生答案,采用變量$fraction存儲分數,當計時時間到或者考生提前交卷,系統獲取表單提交的數據,計算并保存考試結果,以題號9541單選題答題為例:系統首先判斷有無單選題題型存在,如果存在,則將考生提交答案與試題表中id為9541試題的正確答案進行比較,如果提交答案與正確答案相同,則按照試題表下每題分值(`fraction`字段)大小進行加分,如果答錯或者未答則給予0分,通過for循環語句遍歷所有單選題,將形如9541@radio@A@A@1的字符串結果存入$sub_answer[]數組中,同時計算單選題總分,當所有題型遍歷完后,計算試卷總分,并把考試結果數據填寫到考生表中,表中考生答案(`sub_answer`字段)用implode("*",$sub_answer)函數拼接成字符串,如果填寫成功,表示完成試卷信息的提交,系統彈出試卷提交成功信息,并同時顯示成績結果頁面。
考生也可以在考試結束后根據準考證號和試卷名稱查詢成績,顯示成績結果頁面。系統利用$ar=explode("*",$sub_answer)函數,拆分得到每條試題的考試結果,利用for循環讀取每條試題的數據,利用$dates=explode("@",$ar[$i])將每條試題的數據再拆分到數組中,利用$array_type[]=$dates[1]將題型存儲到數組中,利用$answers[]=$dates[2]將正確的答案存儲到數組中,利用$answer[]=$dates[3]將提交的答案存儲到數組中,利用$array_answer[]=$dates將每條試題的所有數據存儲到數組中。由于成績頁面中要顯示具體的試題內容、正確答案、提交答案,因此,系統根據試卷id值,將試卷的題型先放到變量$examtype中,通過foreach語句遍歷該題型下的所有試題id值,然后根據試題id值將試題內容從試題表中取出來,付給頁面模板。在頁面模板中,以單選題為例,系統利用雙重循環語句進行遍歷,遍歷的條件就是考生表中`sub_answer`字段包含的試題id、題型分別與試題表中的試題id、題型相等,遍歷結果中的試題內容取自試題表中的`content`字段、正確答案取自試題表中的`answer`字段、提交答案取自考生表中的`sub_answer`字段、問題解析取自試題表中的`resolve`字段。頁面中,考生還可以通過單擊查看答題情況按鈕查看所有答題情況,單擊正確或錯誤按鈕,頁面會跳轉到對應試題所在位置實現單條試題的結果查詢。
2.4 系統前后臺功能設計
客戶端程序在功能設計上共分為前臺和后臺兩大部分,前臺設計主要包括首頁設計,以及單項練習、模擬考試、正式考試、成績查詢、新聞公告五大模塊入口設計,如圖2所示。由于系統采用了Smarty模版引擎技術,它將應用程序分成視圖和邏輯控制兩部分[4],有效地實現了邏輯代碼與內容表現的分離,專注于內容表現,避免了標簽與程序的混合,使得邏輯內容的改變不會影響到前臺視圖[5],因此大大減輕了頁面設計的工作量,每個模板頁面通過對應PHP文件的$smarty->display方法指定,頁面的變量通過對應PHP文件的$smarty->assign方法指定。在單項練習模塊的頁面設計中,運用了Jquery的Ajax技術,對提交按鈕進行判斷,構建function checkInput(id,type)函數對單選題、判斷題、多選題進行題型檢查,構建function checkAnswer(id,type)函數對是否選擇了答案進行檢查,構建function createInputHidden(id)函數創建用戶已答試題的隱藏域,記錄用戶所答的問題。與模擬考試和正式考試不同的是,單項練習模塊的答案是提交到當前頁面,在隱藏域里利用setAttribute方法創建input元素的name值'hid',根據$_POST['hid']方法到數據庫試題表中查詢該id試題的正確答案,將提交的答案與之比較,正確則加分,然后將提交答案和正確答案輸出到當前頁中,用戶每答一題,就向單項練習表中添加一條記錄,保存用戶所做的數據。模擬考試模塊與正式考試模塊的功能設計基本相同,區別只在于模擬考試使用的是測試賬號,登錄時用戶只需選擇考題名稱而無須輸入準考證號和登錄密碼。
后臺頁面設計采用了框架布局的形式,管理員在后臺進行登錄時,系統首先運用JavaScript對登錄賬號、密碼、權限是否填寫進行檢查,然后去數據庫用戶表驗證所填寫的賬號、密碼是否正確,賬戶是否被凍結,驗證通過后進入后臺管理系統首頁,后臺首頁分為頭部、左部導航欄、右部功能展示區,頭部主要顯示登錄賬戶、用戶權限和上次登錄時間,導航欄包含所有功能菜單,它使用JavaScript實現子菜單的展開和折疊,所有功能如圖3所示,其中類別管理菜單既可以添加主課程類別,也可以添加該課程下的子課程類別,添加考生信息子菜單中的添加考生方法既可以使用富文本編輯器CKeditor手工逐條添加,也可以用Excel文件批量導入,新聞公告菜單主要實現考試信息及相關新聞的發布,試題管理菜單主要用于試題的增刪改查,試題除了可以手工逐條輸入之外,也可以進行批量導入,導入前需分別為四種題型建立對應的Excel文件,導入時在頁面先選擇課程類別、題型、題型分值,然后選擇要導入的文件,文件格式要求單選題和多選題應包含序號、試題內容、A—D選項內容,答案(大寫字母A—D)、解析等字段,判斷題和填空題應包含序號、試題內容、答案(判斷題用數字1表示正確、0表示錯誤)、解析等字段,除了導入功能,試題還可以導出為word文檔,方便打印紙質試卷。試卷管理菜單下的分數和分數線設定子菜單,可以設置總分和及格分數線,按照總分和分數線可以在模板定義子菜單中設定不同題型的試題數量,并保存為新模板。在模板管理子菜單中可以修改各個題型的數量占比,在管理題型子菜單中不但可以更改或刪除現有題型,而且還可以增加其他非客觀題型,進行人工閱卷。成績管理菜單可以用于正式考試成績的查詢和統計,在使用成績查詢子菜單進行查詢時,查詢的選項可以是考生姓名、考試名稱、課程類別和考試不及格者,可以將查詢的結果導出為Excel格式的文件。在成績統計子菜單,系統利用JpGraph圖表類庫實現某個考試名稱的成績統計與分析,利用直線圖表示所有考生的考試成績,利用3d餅圖表示考試通過率。權限管理菜單可以實現從用戶表中添加用戶為教師、管理員或超級管理員角色,也可以對已添加的角色進行權限更改,根據管理權限的不同,用戶以教師身份角色登錄后臺時導航欄沒有權限管理菜單,以教師和管理員角色登錄后臺時導航欄含有數據庫管理菜單,可用于對考試數據庫進行備份或還原,保證考試數據的安全。
3 系統測試和完善(System testing and improvement)
實現系統的穩定性是運行在線考試的關鍵[6],系統使用PHP技術使得考試數據得以及時更新,但頻繁的數據讀取卻給服務器帶來了巨大的壓力,特別是當并發訪問[7]量較大時,服務器頻繁工作于用戶請求與數據庫響應兩個操作之間,就會造成用戶請求多與數據庫響應慢兩者之間相互等待的局面,嚴重者則會導致系統崩潰。相對于其他模板引擎來說,采用Smarty模板編寫的應用程序可以獲得更大效能,在應用程序第一次運行時,Smarty會將程序編譯成一個非模板格式的PHP文件,并將最終輸出的內容緩存成一個靜態的HTML文件,若在源代碼未變動或緩存時間尚未過期的情況下,下次再訪問模板時,Smarty會將用戶請求直接定位到這個HTML文件上,而不再進行重編譯,既省去了業務邏輯[8]處理麻煩,又降低了訪問量較大引發的服務器工作負荷,有效提升了應用程序的性能和服務器的響應速度。系統在完成了整個考試系統的前后臺設計之后,必須對系統的穩定性和并發能力進行測試,測試的首要項目是服務器單機測試,系統在加載Apache服務和Mysql服務之后,檢查前臺登錄各個單元模塊是否流暢,是否存在服務器端口沖突,后臺試題導
入、考生數據表導入有無問題,前后臺頁面有無遲滯現象,單機測試合格后再進行內網測試,用一臺或者多臺服務器通過內網進行測試,選任意一臺考生用機進入指定一臺或多臺服務器,檢查系統運行是否正常、流暢,考試登錄、計時、交卷、評分、成績查詢各個環節有無錯誤,有無遲滯現象,內網測試合格后,進行60人同時在線考試,測試系統在多人上線時的穩定性和并發性,在服務器上檢查在線考生表的數量是否與參考人數相等,有無掉線現象,分析掉線產生的原因,測試一臺考試服務器最大考試客戶機連接數,在實際考試中,我們最好在每個機房安裝一臺服務器操作系統,并安裝PhpStudy集成軟件包和在線考試系統軟件,考試結束后,將每個機房的考試成績分別導出,再按考場和課程匯總,得到該門課程的全部考試成績[9]。
4 結論(Conclusion)
本系統基于PHP、Mysql和Smarty技術,采用B/S模式,能夠實現在線單項練習、模擬和正式考試及評分,系統經測試、使用,并發能力強,服務器運行穩定可靠,能夠顯著提高大學生計算機一級考試理論應試成績,該系統也可以用于其他課程的在線練習、考試。
參考文獻(References)
[1] 張福炎,孫志揮.大學計算機信息技術教程[M].南京大學出版社,2017,8.
[2] 劉洪江.在線考試系統的數據庫設計與實現[J].電腦知識與技術,2012,8 (3):508-511.
[3] 萬茹.基于HTML5的Web富客戶端網頁設計方法[J].電腦編程技巧與維護,2015(13):67-69.
[4] 馮興利,徐墨,鎖志海.基于模板引擎Smarty的信息管理系統設計[J].現代電子技術,2012,35(18):25-28.
[5] 劉耀欽,袁承芬.基于PHP的招聘報名系統設計與研究[J].計算機時代,2014(5):39-41.
[6] 李偉為.基于ASP.NET2.0的在線考試系統的設計與實現[J].計算機應用與軟件,2011,28(9):163-165.
[7] 王鑫.并發數據訪問代碼缺陷分析[J].航天控制,2011,29(2):81-92.
[8]孫小淋.會話外觀模式在業務邏輯集成中的應用[J].微處理機,2014(1):25-28.
[9] PHP項目開發實戰入門[M].明日科技.吉林:吉林大學出版社,2017,3.
作者簡介:
金 強(1970-),男,碩士,高級講師.研究領域:控制工程,軟件工程.
王 亮(1979-),男,碩士,講師.研究領域:計算機網絡,信息安全.
方春華(1973-),女,本科,講師.研究領域:數據挖掘,數據庫開發.