-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prebid Core: Allow Cpm Custom Rounding #9018
Merged
Merged
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
1c0c289
Allow custom rounding functions
spotxslagle 0f2290a
Add custom rounding unit tests
spotxslagle 46738bd
Default to Math.floor when passed an invalid rounding function
spotxslagle a5a8586
Add error logging
spotxslagle f3ead29
Fix import statement
spotxslagle File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import {find} from './polyfill.js'; | ||
import { isEmpty } from './utils.js'; | ||
import { config } from './config.js'; | ||
|
||
const _defaultPrecision = 2; | ||
const _lgPriceConfig = { | ||
|
@@ -118,17 +119,30 @@ function getCpmTarget(cpm, bucket, granularityMultiplier) { | |
const precision = typeof bucket.precision !== 'undefined' ? bucket.precision : _defaultPrecision; | ||
const increment = bucket.increment * granularityMultiplier; | ||
const bucketMin = bucket.min * granularityMultiplier; | ||
let roundingFunction = Math.floor; | ||
let customRoundingFunction = config.getConfig('cpmRoundingFunction'); | ||
if (typeof customRoundingFunction === 'function') { | ||
roundingFunction = customRoundingFunction; | ||
} | ||
|
||
// start increments at the bucket min and then add bucket min back to arrive at the correct rounding | ||
// note - we're padding the values to avoid using decimals in the math prior to flooring | ||
// this is done as JS can return values slightly below the expected mark which would skew the price bucket target | ||
// (eg 4.01 / 0.01 = 400.99999999999994) | ||
// min precison should be 2 to move decimal place over. | ||
let pow = Math.pow(10, precision + 2); | ||
let cpmToFloor = ((cpm * pow) - (bucketMin * pow)) / (increment * pow); | ||
let cpmTarget = ((Math.floor(cpmToFloor)) * increment) + bucketMin; | ||
let cpmToRound = ((cpm * pow) - (bucketMin * pow)) / (increment * pow); | ||
let cpmTarget; | ||
// It is likely that we will be passed {cpmRoundingFunction: roundingFunction()} | ||
// rather than the expected {cpmRoundingFunction: roundingFunction}. Default back to floor in that case | ||
try { | ||
cpmTarget = (roundingFunction(cpmToRound) * increment) + bucketMin; | ||
} catch (err) { | ||
cpmTarget = (Math.floor(cpmToRound) * increment) + bucketMin; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we log a warning here so easier to debug when this exception occurs? |
||
} | ||
// force to 10 decimal places to deal with imprecise decimal/binary conversions | ||
// (for example 0.1 * 3 = 0.30000000000000004) | ||
|
||
cpmTarget = Number(cpmTarget.toFixed(10)); | ||
return cpmTarget.toFixed(precision); | ||
} | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change LGTM, but isn't the use case for this already covered by this configurable
precision
(as explained here)? This is probably more about documentation, it's not clear to me why I'd want to use one over the other.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Precision states where the rounding will occur, but the rounding is always down. This change allows for other rounding methods.
e.g.
Current
cpm = 2.1456, increment = .05, precision = 3
precise cpm = 2.145, rounded down to nearest increment = 2.10
Final result = 2.100
With alternate rounding
cpm = 2.1456, increment = 0.5 precision = 4
precise cpm = 2.1456, rounded with Math.round to nearest increment = 2.15
Final result = 2.1500
At least, that's how I understand it. As far as I can tell, the precision determines what is being rounded down, but it is always rounded down, and always to the nearest increment, which in effect just tacks extra zeroes to the end of the result.
Then again, I'm mostly basing that off the unit tests, which aren't super comprehensive for precision, and the documentation, which only shows the default of 2. If precision is supposed to affect rounding in any way, I don't get it. As long as the precision is greater than or equal to the number of decimal places in the increment, rounding will be unaffected by precision, which makes this change useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, I thought you could get the equivalent of
Math.round
by increasing the precision by 1, but that's not exactly what happens.