func vote(client types.RepPoolClient, instance instance.Instance, representatives []string) (string, float64, error) { results := client.Vote(representatives, instance) winningScore := 1e9 winners := []string{} for _, result := range results { if result.Error != "" { continue } if result.Score < winningScore { winningScore = result.Score winners = []string{result.Rep} } else if result.Score == winningScore { // can be less strict here winners = append(winners, result.Rep) } } if len(winners) == 0 { return "", 0, AllBiddersFull } winner := winners[util.R.Intn(len(winners))] return winner, winningScore, nil }
func Auction(client types.RepPoolClient, auctionRequest types.AuctionRequest) types.AuctionResult { var auctionWinner string var representatives []string if !auctionRequest.Rules.RepickEveryRound { representatives = randomSubset(auctionRequest.RepGuids, auctionRequest.Rules.MaxBiddingPool) } numRounds, numVotes := 0, 0 t := time.Now() for round := 1; round <= auctionRequest.Rules.MaxRounds; round++ { if auctionRequest.Rules.RepickEveryRound { representatives = randomSubset(auctionRequest.RepGuids, auctionRequest.Rules.MaxBiddingPool) } numRounds++ winner, _, err := vote(client, auctionRequest.Instance, representatives) numVotes += len(representatives) if err != nil { continue } c := make(chan types.VoteResult) go func() { winnerScore, err := client.ReserveAndRecastVote(winner, auctionRequest.Instance) result := types.VoteResult{ Rep: winner, } if err != nil { result.Error = err.Error() c <- result return } result.Score = winnerScore c <- result }() secondRoundVoters := []string{} for _, rep := range representatives { if rep != winner { secondRoundVoters = append(secondRoundVoters, rep) } } _, secondPlaceScore, err := vote(client, auctionRequest.Instance, secondRoundVoters) winnerRecast := <-c numVotes += len(representatives) if winnerRecast.Error != "" { //winner ran out of space on the recast, retry continue } if err == nil && secondPlaceScore < winnerRecast.Score && round < auctionRequest.Rules.MaxRounds { client.Release(winner, auctionRequest.Instance) continue } client.Claim(winner, auctionRequest.Instance) auctionWinner = winner break } return types.AuctionResult{ Winner: auctionWinner, Instance: auctionRequest.Instance, NumRounds: numRounds, NumVotes: numVotes, Duration: time.Since(t), } }