package modules import ( "fmt" "sync" "time" "github.com/bwmarrin/discordgo" "TerraOceanBot/db" "TerraOceanBot/discord/backend" "TerraOceanBot/discord/config" "TerraOceanBot/discord/message" ) type confirmedResult struct { VoteID int IsPositive bool } const invalidVote = -1 var voteMutex sync.Mutex var toAnnounceResultList []confirmedResult func ListenToVoteFinishes(s *discordgo.Session) { for { voteMutex.Lock() for _, v := range toAnnounceResultList { if v.VoteID == invalidVote { continue } message.AuditInfo(s, fmt.Sprintf("Announcing the result of vote %d.", v.VoteID)) if err := db.FinishVote(v.VoteID); err != nil { message.AuditError(s, "", err) continue } voteType, _ := db.GetVoteType(v.VoteID) voteName, _ := db.GetVoteName(v.VoteID) messageID, _ := db.GetMessageIDFromVote(v.VoteID) voteTypes[voteType].EmbedBuilder(v.VoteID, voteName).UpdateVoteStatus(v.IsPositive).Edit(s, config.VoteChannel, messageID) 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 := db.GetAllVoteChoices(id) if err != nil { message.AuditError(s, "", err) return } var currentScore, totalTrust float64 var absoluteRejectionVote bool for _, vote := range votes { if vote.Value == db.ForceRejectionVote { absoluteRejectionVote = true } trust, err := backend.GetTrust(s, vote.UserID) if err != nil { message.AuditError(s, "", err) return } currentScore += float64(vote.Value) * trust totalTrust += float64(trust) } totalGlobalTrust, err := backend.GetTotalTrust(s) if err != nil { message.AuditError(s, "", err) return } remainingTrust := totalGlobalTrust - totalTrust lowestPossible := (currentScore + remainingTrust) / totalGlobalTrust highestPossible := (currentScore + remainingTrust*5) / totalGlobalTrust voteMutex.Lock() defer voteMutex.Unlock() if highestPossible <= 3.5 || absoluteRejectionVote { //Rejection confirmed. for _, v := range toAnnounceResultList { if v.VoteID == id { //It's already queued to be announced in the next announcement cycle. return } } message.AuditInfo(s, fmt.Sprintf("Rejection of vote ID %d has been confirmed.", id)) toAnnounceResultList = append(toAnnounceResultList, confirmedResult{ VoteID: id, IsPositive: false, }) } else if lowestPossible >= 3.5 { //Acceptance confirmed. for _, v := range toAnnounceResultList { if v.VoteID == id { //It's already queued to be announced in the next announcement cycle. return } } message.AuditInfo(s, fmt.Sprintf("Acceptance of vote ID %d has been confirmed.", id)) toAnnounceResultList = append(toAnnounceResultList, confirmedResult{ VoteID: id, IsPositive: true, }) } else { //Nothing happened. Make sure it's not in the queue. for k, v := range toAnnounceResultList { if v.VoteID == id { //It's already queued to be announced in the next announcement cycle. toAnnounceResultList[k] = confirmedResult{ VoteID: invalidVote, IsPositive: false, } return } } } }