<commit_before>package exchange

import (
	"context"
	"strconv"
	"strings"

	"github.com/golang/glog"
	"github.com/mxmCherry/openrtb"
	"github.com/prebid/prebid-server/openrtb_ext"
	"github.com/prebid/prebid-server/pbs/buckets"
	"github.com/prebid/prebid-server/prebid_cache_client"
)

const maxKeyLength = 20

// targetData tracks information about the winning Bid in each Imp.
//
// All functions on this struct are nil-safe. If the targetData struct is nil, then they behave
// like they would if no targeting information is needed.
//
// All functions on this struct are all nil-safe.
// If the value is nil, then no targeting data will be tracked.
type targetData struct {
	priceGranularity openrtb_ext.PriceGranularity
	includeCache     bool
}

// setTargeting writes all the targeting params into the bids.
// If any errors occur when setting the targeting params for a particular bid, then that bid will be ejected from the auction.
//
// The one exception is the `hb_cache_id` key. Since our APIs explicitly document cache keys to be on a "best effort" basis,
// it's ok if those stay in the auction. For now, this method implements a very naive cache strategy.
// In the future, we should implement a more clever retry & backoff strategy to balance the success rate & performance.
func (targData *targetData) setTargeting(ctx context.Context, cache prebid_cache_client.Client, numImps int, seatBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, ext map[openrtb_ext.BidderName]*seatResponseExtra) {
	if targData == nil {
		return
	}

	winningBids, _, winningBidsByBidder := findWinners(seatBids, numImps)
	roundedPrices := makeRoundedPrices(openrtb_ext.PriceGranularityLow /* TODO: Fix */, winningBids, winningBidsByBidder)
	var cacheIds map[*openrtb.Bid]string
	if targData.includeCache {
		cacheIds = doCache(ctx, cache, winningBids, winningBidsByBidder, roundedPrices)
	}

	setTargetingKeys(roundedPrices, cacheIds, winningBids, winningBidsByBidder)
}

func findWinners(seatBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, numImps int) (winningBids map[string]*pbsOrtbBid, winningBidders map[string]openrtb_ext.BidderName, winningBidsByBidder map[string]map[openrtb_ext.BidderName]*pbsOrtbBid) {
	// winningBids is a map from imp.id to the highest overall CPM bid in that imp.
	winningBids = make(map[string]*pbsOrtbBid, numImps)<commit_msg>Finished a missing TODO. (#389)<commit_after>package exchange

import (
	"context"
	"strconv"
	"strings"

	"github.com/golang/glog"
	"github.com/mxmCherry/openrtb"
	"github.com/prebid/prebid-server/openrtb_ext"
	"github.com/prebid/prebid-server/pbs/buckets"
	"github.com/prebid/prebid-server/prebid_cache_client"
)

const maxKeyLength = 20

// targetData tracks information about the winning Bid in each Imp.
//
// All functions on this struct are nil-safe. If the targetData struct is nil, then they behave
// like they would if no targeting information is needed.
//
// All functions on this struct are all nil-safe.
// If the value is nil, then no targeting data will be tracked.
type targetData struct {
	priceGranularity openrtb_ext.PriceGranularity
	includeCache     bool
}

// setTargeting writes all the targeting params into the bids.
// If any errors occur when setting the targeting params for a particular bid, then that bid will be ejected from the auction.
//
// The one exception is the `hb_cache_id` key. Since our APIs explicitly document cache keys to be on a "best effort" basis,
// it's ok if those stay in the auction. For now, this method implements a very naive cache strategy.
// In the future, we should implement a more clever retry & backoff strategy to balance the success rate & performance.
func (targData *targetData) setTargeting(ctx context.Context, cache prebid_cache_client.Client, numImps int, seatBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, ext map[openrtb_ext.BidderName]*seatResponseExtra) {
	if targData == nil {
		return
	}

	winningBids, _, winningBidsByBidder := findWinners(seatBids, numImps)
	roundedPrices := makeRoundedPrices(targData.priceGranularity, winningBids, winningBidsByBidder)
	var cacheIds map[*openrtb.Bid]string
	if targData.includeCache {
		cacheIds = doCache(ctx, cache, winningBids, winningBidsByBidder, roundedPrices)
	}

	setTargetingKeys(roundedPrices, cacheIds, winningBids, winningBidsByBidder)
}

func findWinners(seatBids map[openrtb_ext.BidderName]*pbsOrtbSeatBid, numImps int) (winningBids map[string]*pbsOrtbBid, winningBidders map[string]openrtb_ext.BidderName, winningBidsByBidder map[string]map[openrtb_ext.BidderName]*pbsOrtbBid) {
	// winningBids is a map from imp.id to the highest overall CPM bid in that imp.
	winningBids = make(map[string]*pbsOrtbBid, numImps)
{'fraction_non_alphanumeric': 0.08365261813537675, 'fraction_numerical': 0.001489995742869306, 'mean_word_length': 5.118489583333333, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2842820', 'n_tokens_mistral': 1599, 'n_tokens_neox': 1543, 'n_words': 471}