序數據庫
新的一年已經拉開了序幕,有的忙着離職、有的忙着請求加薪,有的忙着春運,有人忙着相親。。小程序
對於絕大多數人來講,新的一年就是新的開始,新的開始也就是雄心壯志立flag的之時,只求不恍惚間到年尾,而後再把去年的flag,copy一次。緩存
千里之行,始於足下。因此,個人雄心壯志,也從這簡簡單單的知識分享開始。微信
說到知識分享,就不能不提去年年末大火的直播答題app,不過,隨着時間的推移,貌似熱度已漸減。做爲一個不算資深的程序猿,當別人爲了衝關成功而欣喜,爲了失敗而失落時,我以爲程序猿們應該有透過現象看本質的想法與能力,正如,不以物喜,不以己悲。app
廢話很少少,好文剛出鍋,你們趁熱食用。函數
01測試
本次我分享的是小程序版好友對戰答題的實現思路與具體方法,因爲篇幅問題,我將分紅多個小段進行分享。首先咱們先來分析下需求流程。spa
首先,用戶進入小程序。有兩個選擇,一,發起挑戰;二.圍觀對戰,選擇圍觀對戰則隨機進入一個正在對戰的房間,成爲圍觀觀衆。選擇發起挑戰,則服務端生成一個房間號,而後觸發分享操做,攜帶生成的房間號,由用戶選擇分享給好友或者微信羣。code
微信用戶經過分享的卡片進入小程序後,可選擇參戰或者圍觀,若是已經選擇參戰了,則其餘用戶自動成爲圍觀用戶。此時,發起方的頁面狀態由等待好友響應變爲等待開始。在發起方單擊開始以前,參戰的用戶可選擇退出參戰,此時,任意一個圍觀用戶則能夠選擇參戰。blog
答題正式開始時,每道題有10s的時間回答。答錯,或者超時,均認爲答題錯誤,則不加分。答對,則根據答題用時,(11-所用秒數)*10的公式進行加分,每題滿分100(留了1s時間,用戶客戶端和服務端之間的通信耗時,以及客戶端渲染題目所須要的時間),最後一題雙倍分數。
02
下面說下程序的實現邏輯:
程序分爲兩部分,小程序端和服務端。爲了知足答題的及時性以及用戶體驗,小程序與服務端間的通信使用WebSocket。小程序端負責用戶交互,展現返回的數據。
服務端負責處理用戶建立房間、進入房間、圍觀、發彈幕的操做。
服務端的邏輯功能包括:處理圍觀用戶的請求,圍觀用戶的請求分爲兩種,隨機圍觀和指定房間號圍觀,服務端根據用戶請求數據中是否包含房間號進行判斷,若是不含,則隨機進入正在進行中的對戰房間進行圍觀。
處理圍觀用戶發彈幕請求。用戶在答題過程當中,圍觀用戶可進行交流評論,而後以彈幕的形式實時顯示在界面中。
處理用戶發起挑戰的請求。用戶發起挑戰,則生成一個房間號,存儲在數據庫,並返回給請求用戶。
處理應戰用戶請求。用戶點擊應戰按鈕後,設置當前房間狀態爲配對成功,其餘用戶則不能再發起此房間的挑戰。
處理放棄挑戰請求。與應戰操做邏輯相反。
處理房主點擊開始請求。房主點擊開始後,服務端隨機從數據庫中抽取有效的題目。並每隔11s(考慮到客戶端與服務端之間的通信耗時和客戶端頁面渲染耗時),推送新的題目,直到答題完畢。
處理用戶提交答案請求。用戶提交答案時,從數據庫(或緩存)中匹配答案,正確時,則根據耗時,計算本輪分數,另外,須要將答題結果推送給圍觀用戶。錯誤時,則將正確答案推送給答題者。
處理用戶超時未答。當服務端在11秒內未收到提交的答題請求,則自動判斷答題超時,將正確答案推送給超時用戶。
03
數據庫中,跟題目相關的表有兩個,一個是題庫表,一個是每一個對戰房間的題目表。表結構以下:
題庫表:
列名 |
類型 |
說明 |
Id |
int |
主鍵,惟一標識 |
CreateTime |
DateTime |
題目的建立時間 |
Title |
Nvarchar |
標題 |
Options |
Nvarchar |
答案選項 |
Status |
int |
是否可用,默認1,可用。0爲不可用 |
Level |
int |
難易程度,值越大越難 |
試卷表:
列名 |
類型 |
說明 |
Id |
int |
主鍵,惟一標識 |
Title |
Nvarchar |
標題 |
Options |
Nvarchar |
答案選項 |
Answer |
int |
答案的序號。從1開始。 |
Level |
int |
難易程度,值越大越難 |
HomeId |
int |
房間號 |
SubjectId |
int |
題庫編號 |
從上面的表中能夠看出,題目的答案選項我是用nvarchar存儲的,這樣方便管理人員進行編輯。默認第一個爲正確答案。因此,在從題庫中抽取題目時,須要將答案順序打亂,並記錄正確答案的序號。
具體實現思路是,首先隨機從題庫中抽取有效的題目存入臨時表,而後遍歷每條記錄,把選項打亂順序,並存入新表。最後刪除臨時表,將已選的題目的狀態更新爲不可用。代碼以下:
CREATE PROC [dbo].[proc_getsubject](@count INT,@homeId INT) AS BEGIN IF OBJECT_ID('tempdb..#Subject_TEMP','U') IS NOT NULL DROP TABLE #Subject_TEMP --隨機從表中獲取指定條數的有效題目,並存入臨時表 SELECT TOP (@count) Title,Options,Id,Level INTO #Subject_TEMP FROM dbo.Subject WHERE Status=1 ORDER BY NEWID() --刪除試卷中,當前房間號已存在的題目 DELETE [dbo].[ActivityItems] WHERE [HomeId]=@homeId --遍歷每一個題目 WHILE @count>0 BEGIN DECLARE @title NVARCHAR(500),@options NVARCHAR(2000), @level INT,--難易程度 @newoptions NVARCHAR(2000),@id INT,@optionCount INT ,--當前答案的數量 @answer INT--答案的索引,從1開始。 SET @newoptions='' --初始化 --從臨時表中,取出一條數據 SELECT TOP 1 @title=Title,@options=Options,@id=Id,@level=Level FROM #Subject_TEMP IF OBJECT_ID('tempdb..#Options_TEMP','U') IS NOT NULL DROP TABLE #Options_TEMP --使用表值函數,分割答案選項,並打亂順序。 SELECT * INTO #Options_TEMP FROM dbo.F_SplitSTR(@options,',') --獲取選項的數量 SELECT @optionCount=COUNT(1) FROM #Options_TEMP DECLARE @temp_i INT--循環裏的索引 SET @temp_i =1 --循環分割後的答案,拼接成新的答案選項字符串 WHILE @optionCount>0 BEGIN DECLARE @item NVARCHAR(200),@sort INT --隨機從答案選項中選擇 SELECT TOP 1 @item=col,@sort=sort FROM #Options_TEMP ORDER BY NEWID() SET @newoptions+=@item+',' IF @sort=1 SET @answer=@temp_i SET @optionCount-=1 SET @temp_i+=1 DELETE #Options_TEMP WHERE sort=@sort END SET @count-=1 --從臨時表中刪除剛剛處理過的題目 DELETE #Subject_TEMP WHERE Id=@id --將處理後的題目信息存入試卷表 PRINT(@newoptions) INSERT [dbo].[ActivityItems] VALUES(@title,@newoptions,@answer,@level,@HomeId,@id) END /*更新已選題庫爲無效狀態,保證每道題只出現1次,測試時,可不執行此代碼。這樣題目是能夠重複利用的*/ --UPDATE dbo.Subject SET Status=0 WHERE Id IN (SELECT SubjectId FROM [ActivityItems] WHERE HomeId=@homeId) SELECT * FROM ActivityItems WHERE HomeId=@homeId ORDER BY [Level] END
其中,用於分割選項的方法代碼以下:
CREATE FUNCTION [dbo].[f_splitSTR]( @s VARCHAR(8000), --待分拆的字符串 @split VARCHAR(10) --數據分隔符 )RETURNS @re TABLE(col VARCHAR(100),sort INT) AS BEGIN DECLARE @splitlen INT,@sort INT SET @sort=0 SET @splitlen=LEN(@split+'a')-2 WHILE CHARINDEX(@split,@s)>0 BEGIN SET @sort+=1 INSERT @re VALUES(LEFT(@s,CHARINDEX(@split,@s)-1),@sort) SET @s=STUFF(@s,1,CHARINDEX(@split,@s)+@splitlen,'') END INSERT @re VALUES(@s,@sort+1) RETURN END
未完待續
是否是有種戛然而止的感受,沒錯,後面的正在整理中,整個系列將完整實現一個對戰答題的小程序,包含服務端和小程序端的代碼實現,以及服務端wss的開發與配置。
欲知後事如何,傾聽下回分解。
本文首發公衆號:微兔碼農說,歡迎關注,分享。
有的朋友要源碼。全部的源碼在整個系列發佈完成後,會打包,供你們下載。如需文章中提到的數據庫文件,請掃描下方二維碼,關注微信公衆號,回覆答題數據庫,便可獲取數據庫地址。