func (election *Election) PrefillNeighborVotes(neighborIDs []interface{}, vote interface{}) error {
	if election.IsStopped() {
		return errors.New("Election has already stopped")
	}
	for _, neighborID := range neighborIDs {
		election.neighborVotes.LoadOrStore(neighborID, vote)
	}
	select {
	case election.voteReceived <- struct{}{}:
	default:
	}
	return nil
}
PrefillNeighborVotes prefills vote for neighborIDs that don't have a vote yet
package election
import (
	"errors"
	"fmt"
	"sync"
	"time"
)
type electionState uint8
const (
	initialized electionState = 0
	started     electionState = 1
	stopped     electionState = 2
)
type Config struct {
	Duration                    time.Duration
	MinVotingInterval           time.Duration
	MaxVotingInterval           time.Duration
	ChangeVoteMinRelativeWeight float32
	ChangeVoteMinAbsoluteWeight uint32
	ConsensusMinRelativeWeight  float32
	ConsensusMinAbsoluteWeight  uint32
	GetWeight                   func(interface{}) uint32
}
type Election struct {
	*Config
	startOnce     sync.Once
	neighborVotes sync.Map
	voteReceived  chan struct{}
	txVoteChan    chan interface{}
	sync.RWMutex
	selfVote interface{}
	state    electionState
}
func NewElection(config *Config) (*Election, error) {
	if config.Duration == 0 {
		return nil, errors.New("Election duration cannot be empty")
	}
	if config.MinVotingInterval > config.MaxVotingInterval {
		return nil, fmt.Errorf("Min voting interval %v is greater than max voting interval %v", config.MinVotingInterval, config.MaxVotingInterval)
	}
	if config.GetWeight == nil {
		config.GetWeight = func(interface{}) uint32 { return 1 }
	}
	election := &Election{
		Config:       config,
		state:        initialized,
		voteReceived: make(chan struct{}, 1),
		txVoteChan:   make(chan interface{}),
	}
	return election, nil
}
func (election *Election) SetInitialVote(vote interface{}) error {
	if election.HasStarted() {
		return errors.New("Cannot set initial vote, election has started")
	}
	election.Lock()
	election.selfVote = vote
	election.Unlock()
	return nil
}
func (election *Election) Start() bool {
	success := false
	election.startOnce.Do(func() {
		election.Lock()
		election.state = started
		election.Unlock()
		go election.updateVote()
		time.AfterFunc(election.Duration, func() {
			election.Stop()
		})
		success = true
	})
	return success
}
func (election *Election) Stop() {
	election.Lock()
	election.state = stopped
	election.Unlock()
	select {
	case election.voteReceived <- struct{}{}:
	default:
	}
}
func (election *Election) HasStarted() bool {
	election.RLock()
	defer election.RUnlock()
	return election.state != initialized
}
func (election *Election) IsStopped() bool {
	election.RLock()
	defer election.RUnlock()
	return election.state == stopped
}
func (election *Election) ReceiveVote(neighborID, vote interface{}) error {
	if election.IsStopped() {
		return errors.New("Election has already stopped")
	}
	election.neighborVotes.Store(neighborID, vote)
	select {
	case election.voteReceived <- struct{}{}:
	default:
	}
	return nil
}
func (election *Election) GetTxVoteChan() <-chan interface{} {
	return election.txVoteChan
}
func (election *Election) GetResult() (interface{}, uint32, float32, error) {
	if !election.IsStopped() {
		return nil, 0, 0, errors.New("election has not stopped yet")
	}
	result, absWeight, relWeight := election.getLeadingVote()
	if absWeight < election.ConsensusMinAbsoluteWeight {
		return nil, 0, 0, fmt.Errorf("leading vote %v only got %d weight, which is less than threshold %d", result, absWeight, election.ConsensusMinAbsoluteWeight)
	}
	if relWeight < election.ConsensusMinRelativeWeight {
		return nil, 0, 0, fmt.Errorf("leading vote %v only got %f%% weight, which is less than threshold %f%%", result, relWeight*100, election.ConsensusMinRelativeWeight*100)
	}
	if result == nil {
		return nil, 0, 0, errors.New("election result is nil")
	}
	return result, absWeight, relWeight, nil
}
func (election *Election) GetNeighborIDsByVote(vote interface{}) []interface{} {
	var neighborIDs []interface{}
	election.neighborVotes.Range(func(key, value interface{}) bool {
		if value == vote {
			neighborIDs = append(neighborIDs, key)
		}
		return true
	})
	return neighborIDs
}
func (election *Election) NeighborVoteCount() uint32 {
	count := uint32(0)
	election.neighborVotes.Range(func(key, value interface{}) bool {
		count++
		return true
	})
	return count
}