端到端的实现

go ai编程(七爪源码用Go)(1)

我们大多数人都喜欢知识竞赛,对吧? 有许多应用程序可以通过让我们回答来自不同职业的问题来解渴。

在这篇文章中,我将解释我是如何使用 Golang 实现一个实时竞赛应用程序的。

申请流程

go ai编程(七爪源码用Go)(2)

需要遵循一些业务规则。

我的架构决策

在本节中,我将尝试解释为什么我做出了一些决定,并在开始之前尝试对我们的项目提出一些观点。这部分就像电影剧透一样。

go ai编程(七爪源码用Go)(3)

go ai编程(七爪源码用Go)(4)

go ai编程(七爪源码用Go)(5)

比赛流程

我曾经使用 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/小程序/网站源码资源!

,