diff --git a/contracts/room_contract.go b/contracts/room_contract.go index 6ac09e7..fc52d53 100644 --- a/contracts/room_contract.go +++ b/contracts/room_contract.go @@ -22,6 +22,8 @@ func RuntimeNotify(args []any) { runtime.Notify(notificationName, args) } +// CONSTANTS + const ( RoomStatusWaiting = "waiting" // Waiting for the game to start, players are joining RoomStatusGaming = "gaming" // In this phase, players are ready, but the question hasn't been asked yet @@ -30,6 +32,8 @@ const ( RoomStatusFinished = "finished" // Game is finished, and results have been determined ) +// STRUCTS + type Room struct { Id string Host interop.Hash160 @@ -58,6 +62,8 @@ type Player struct { // todo: Сделать реализацию подсчета выигранных раундов } +// GLOBAL PRIVATE METHODS FOR ROOM + func getSender() interop.Hash160 { return runtime.GetScriptContainer().Sender } @@ -79,52 +85,13 @@ func getRoom(ctx storage.Context, roomId string) Room { return room } -func roomContainsPlayer(players []Player, wallet interop.Hash160) bool { - for _, player := range players { - if player.Wallet.Equals(wallet) { - return true - } - } - return false -} - -func chooseWinner(round Round, countWinners int) []Answer { - var winners []Answer - var answers = round.answers - sort.Slice(answers, func(a, b int) bool { - return len(answers[a].votes) > len(answers[b].votes) - }) - - if countWinners > len(round.answers) { - return round.answers - } - - if countWinners == 1 { - return []Answer{answers[0]} - } - - // Choose winners from sorted answers. If the current answer has the same number of votes as the previous one, - // we add it to the winners list. We increase the number of winners if there are multiple answers with the same - // number of votes, as in cases where there are 5 answers with equal votes and countWinners is 3, all should be included. - var lastVote = len(answers[0].votes) - winners = append(winners, answers[0]) - for i := 1; i < len(answers) && len(winners) < countWinners; i++ { - var currentVote = len(answers[i].votes) - if lastVote == currentVote { - countWinners++ // todo: Могут возникнуть проблемы, надо протестировать - } - lastVote = currentVote - winners = append(winners, answers[i]) - } - - return winners -} - // Function for send message to player, now it is default func sendMessageToPlayer(message string, player Player) { // todo: Сделать основную логику } +// MAIN METHODS FOR PLAY IN GAME + func CreateRoom(host interop.Hash160, countWinners int) string { var ctx = storage.GetContext() var id = uuid.NewString() @@ -231,12 +198,21 @@ func AskQuestion(roomId string, question string) bool { return true } +func roomContainsPlayer(players []Player, wallet interop.Hash160) bool { + for _, player := range players { + if player.Wallet.Equals(wallet) { + return true + } + } + return false +} + func SendAnswer(roomId string, text string) bool { var ctx = storage.GetContext() var room = getRoom(ctx, roomId) var wallet = getSender() - if !roomContainsPlayer(room.Players, getSender()) || room.Status != RoomStatusAnswering { + if !roomContainsPlayer(room.Players, wallet) || room.Status != RoomStatusAnswering { return false // Only player can send content, room status must be round is started } @@ -257,7 +233,6 @@ func SendAnswer(roomId string, text string) bool { } round.answers = append(round.answers, answer) - room.Rounds[len(room.Rounds)-1] = round setRoom(ctx, &room) return true @@ -306,12 +281,44 @@ func VoteAnswer(roomId string, answerIdx int) bool { return false // Player cannot vote twice for one answer } } - round.answers[answerIdx].votes = append(round.answers[answerIdx].votes, wallet) + round.answers[answerIdx].votes = append(round.answers[answerIdx].votes, wallet) setRoom(ctx, &room) return true } +func chooseWinner(round Round, countWinners int) []Answer { + var winners []Answer + var answers = round.answers + sort.Slice(answers, func(a, b int) bool { + return len(answers[a].votes) > len(answers[b].votes) + }) + + if countWinners > len(round.answers) { + return round.answers + } + + if countWinners == 1 { + return []Answer{answers[0]} + } + + // Choose winners from sorted answers. If the current answer has the same number of votes as the previous one, + // we add it to the winners list. We increase the number of winners if there are multiple answers with the same + // number of votes, as in cases where there are 5 answers with equal votes and countWinners is 3, all should be included. + var lastVote = len(answers[0].votes) + winners = append(winners, answers[0]) + for i := 1; i < len(answers) && len(winners) < countWinners; i++ { + var currentVote = len(answers[i].votes) + if lastVote == currentVote { + countWinners++ // todo: Могут возникнуть проблемы, надо протестировать + } + lastVote = currentVote + winners = append(winners, answers[i]) + } + + return winners +} + // GetWinner todo: Нам сказали, что ссылку на другой контракт нельзя чисто, используем nns func GetWinner(roomId string) bool { var ctx = storage.GetContext() @@ -343,6 +350,14 @@ func GetWinner(roomId string) bool { return true } +func automaticFinishGame(ctx storage.Context, room *Room, voted int) bool { + if voted != len(room.Players) { + return false // All players must voted for finish the game + } + + return finishGame(ctx, room) +} + func VoteToFinishGame(roomId string) bool { var ctx = storage.GetContext() var room = getRoom(ctx, roomId) @@ -377,14 +392,6 @@ func VoteToFinishGame(roomId string) bool { return automaticFinishGame(ctx, &room, voted) } -func automaticFinishGame(ctx storage.Context, room *Room, voted int) bool { - if voted != len(room.Players) { - return false // All players must voted for finish the game - } - - return finishGame(ctx, room) -} - func ManuallyFinishGame(roomId string) bool { var ctx = storage.GetContext() var room = getRoom(ctx, roomId) @@ -406,4 +413,6 @@ func finishGame(ctx storage.Context, room *Room) bool { return true } -// todo логика выкидывания игрока из игры, если пропускает несколько вопросов подряд - делаем булевый флаг по которому определяем, активен игрок или нет +/* todo: Логика выкидывания игрока из игры, если пропускает несколько вопросов подряд - + * делаем булевый флаг по которому определяем, активен игрок или нет. + */