Ejemplo n.º 1
0
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),
	}
}