端到端的實現
我們大多數人都喜歡知識競賽,對吧? 有許多應用程序可以通過讓我們回答來自不同職業的問題來解渴。
在這篇文章中,我将解釋我是如何使用 Golang 實現一個實時競賽應用程序的。
申請流程
需要遵循一些業務規則。
我的架構決策
在本節中,我将嘗試解釋為什麼我做出了一些決定,并在開始之前嘗試對我們的項目提出一些觀點。這部分就像電影劇透一樣。
比賽流程
我曾經使用 RunCompetition() 方法管理比賽流程,如下所示。
我通過創建一個 goroutine 在應用程序的主要流程中調用了這個函數。
func RunCompetition() {
CompetitionState = CompetitionNotStartedState
for {
if CompetitionState == CompetitionNotStartedState {
time.Sleep(CompetitionStateDuration)
numberOfClients := CountClient()
msg := DetermineCompetitionState(numberOfClients)
BroadcastMessage([]byte(msg))
if numberOfClients == 2 {
time.Sleep(CompetitionStartDuration)
CompetitionState = CompetitionStartedState
}
} else if CompetitionState == CompetitionStartedState {
PrepaRequestions()
StartSendingQuestions()
CompetitionState = CompetitionFinish
} else if CompetitionState == CompetitionFinish {
leaderBoard := CreateLeaderBoard()
jsonBytes, _ := json.Marshal(leaderBoard)
BroadcastMessage(jsonBytes)
BroadcastMessage([]byte(CompetitionFinishedStateMessage))
break
}
}
}
RunCompetition() 方法中有三個 CompetitionState。
func StartSendingQuestions() {
for i := range Questions {
Questions[i].IsTimeout = false
questionDTO := Questions[i].ToDTO()
questionDTOBytes, _ := json.Marshal(questionDTO)
BroadcastMessage(questionDTOBytes)
time.Sleep(QuestionResponseIntervalDuration)
Questions[i].IsTimeout = true
}
}
發送問題時,我們将 Question 結構體轉換為 questionDTO 以向連接的用戶隐藏正确答案以防止作弊。
10 秒後,我們将 IsTimeout 更改為 true,因為給問題的時間到了。
處理客戶端應答流
我們需要從用戶那裡得到答案來檢查和計算他們的分數。
func HandleClientAnswer(sessionID string, message []byte) {
var ClientMsg ClientMessage
json.Unmarshal(message, &ClientMsg)
for _, question := range Questions {
if question.ID == ClientMsg.QuestionId {
if question.IsTimeout == true {
fmt.Println("Response Time is out")
} else {
load, _ := Clients.Load(sessionID)
client := load.(Client)
if ClientMsg.Answer == question.CorrectAnswer {
client.totalScore = ScoreForCorrectAnswer
Clients.Store(sessionID, client)
fmt.Printf("Right Answer!!! SessionId: %s, TotalScore: %d\n", sessionID, client.totalScore)
} else {
fmt.Printf("Wrong Answer!! Your Answer is : %s, Right Answer is : %s, SessionId: %s, TotalScore: %d\n", ClientMsg.Answer, question.CorrectAnswer, sessionID, client.totalScore)
}
}
}
}
}
用戶在指定的時間間隔内正确回答問題可以獲得分數( 10)。
這裡有一些重要的點:
滿足這些條件後,用戶的分數通過 sessionID 存儲在地圖上。 我們在 ws() 方法中調用這個函數。
func ws(c echo.Context) error {
numberOfClients := CountClient()
if numberOfClients >= 2 {
return c.string(http.StatusBadRequest, "")
}
wsConn, err := Upgrader.Upgrade(c.Response(), c.Request(), nil)
if err != nil {
return err
}
defer wsConn.Close()
sessionID := IDGenerator()
Clients.Store(sessionID, Client{
wsConn: wsConn,
totalScore: 0,
})
for {
_, message, err := wsConn.ReadMessage()
if err != nil {
Clients.Delete(sessionID)
c.Logger().Errorf("Client disconnect msg=%s err=%s", string(message), err.Error())
return nil
}
HandleClientAnswer(sessionID, message)
}
}
為了讓我們的應用程序簡單,比賽将從兩個用戶開始。 如果用戶的數量大于 2,我們的應用會發送 http.StatusBadRequest 給用戶。
關注七爪網,獲取更多APP/小程序/網站源碼資源!
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!