package main import ( "fmt" "sync" "time" "github.com/bwmarrin/discordgo" ) type voteChoice struct { UserID string Value int } type confirmedResult struct { VoteID int IsPositive bool } var voteMutex sync.Mutex var toAnnounceResultList []confirmedResult func listenToVoteFinishes(s *discordgo.Session) { for { voteMutex.Lock() for _, v := range toAnnounceResultList { auditLog(s, fmt.Sprintf("Announcing the result of vote %d.", v.VoteID)) if err := finishVote(v.VoteID); err != nil { auditLog(s, fmt.Sprintf("Error while finishing vote %d.", v.VoteID)) } voteType, _ := getVoteType(v.VoteID) voteName, _ := getVoteName(v.VoteID) messageID, _ := getMessageIDFromVote(v.VoteID) s.ChannelMessageEditEmbed(voteChannel, messageID, showVoteStatus(voteTypes[voteType].EmbedBuilder(v.VoteID, voteName), v.IsPositive)) voteTypes[voteType].ResultHandler(s, v.VoteID, voteName, v.IsPositive) } toAnnounceResultList = toAnnounceResultList[:0] voteMutex.Unlock() time.Sleep(60 * time.Second) } } func checkForVoteResult(s *discordgo.Session, id int) { votes, err := getAllVoteChoices(id) if err != nil { auditLog(s, fmt.Sprintf("Error while calculating vote result for ID %d: %s", id, err.Error())) return } var currentScore, totalTrust float64 var absoluteRejectionVote bool for _, vote := range votes { if vote.Value == forceRejectionVote { absoluteRejectionVote = true } trust, err := getTrust(vote.UserID) if err != nil { auditLog(s, fmt.Sprintf("Error while getting vote trust for user ID %d: %s", vote.UserID, err.Error())) return } currentScore += float64(vote.Value) * trust totalTrust += float64(trust) } totalGlobalTrust, err := getTotalTrust(s) if err != nil { auditLog(s, fmt.Sprintf("Error while getting total vote trust: %s", err.Error())) return } remainingTrust := totalGlobalTrust - totalTrust lowestPossible := (currentScore + remainingTrust) / totalGlobalTrust highestPossible := (currentScore + remainingTrust*5) / totalGlobalTrust if highestPossible <= 3.5 || absoluteRejectionVote { //Rejection confirmed. voteMutex.Lock() for _, v := range toAnnounceResultList { if v.VoteID == id { //It's already queued to be announced in the next announcement cycle. voteMutex.Unlock() return } } auditLog(s, fmt.Sprintf("Rejection of vote ID %d has been confirmed.", id)) toAnnounceResultList = append(toAnnounceResultList, confirmedResult{ VoteID: id, IsPositive: false, }) voteMutex.Unlock() } if lowestPossible >= 3.5 { //Acceptance confirmed. voteMutex.Lock() for _, v := range toAnnounceResultList { if v.VoteID == id { //It's already queued to be announced in the next announcement cycle. voteMutex.Unlock() return } } auditLog(s, fmt.Sprintf("Acceptance of vote ID %d has been confirmed.", id)) toAnnounceResultList = append(toAnnounceResultList, confirmedResult{ VoteID: id, IsPositive: true, }) voteMutex.Unlock() } } func showVoteStatus(embed *discordgo.MessageEmbed, isPositive bool) *discordgo.MessageEmbed { if isPositive { embed.Color = 0x00F000 embed.Title = "投票通过 Vote Passed" } else { embed.Color = 0xF00000 embed.Title = "投票不通过 Vote Rejected" } return embed }