庖丁解牛-小程序版好友對戰答題項目實踐(一)

            

 

數據庫

 

        新的一年已經拉開了序幕,有的忙着離職、有的忙着請求加薪,有的忙着春運,有人忙着相親。。小程序

        對於絕大多數人來講,新的一年就是新的開始,新的開始也就是雄心壯志立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的開發與配置。

欲知後事如何,傾聽下回分解。

本文首發公衆號:微兔碼農說,歡迎關注,分享。

 

 

有的朋友要源碼。全部的源碼在整個系列發佈完成後,會打包,供你們下載。如需文章中提到的數據庫文件,請掃描下方二維碼,關注微信公衆號,回覆答題數據庫,便可獲取數據庫地址。

 

 

相關文章
相關標籤/搜索