Skip to content
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 5 commits into from
Oct 6, 2022

Conversation

spotxslagle
Copy link
Contributor

For any user facing change, submit a link to a PR on the docs repo at https://github.com/prebid/prebid.github.io/
-->

Type of change

  • [ x ] Feature

Description of change

Allow publishers to set their own rounding rules as desired

Other information

@robertrmartinez

@spotxslagle
Copy link
Contributor Author

I'll link doc changes when I have them

@robertrmartinez
Copy link
Collaborator

Looks fine to me, my only question is that if we should put some protection around the customFunction?

Maybe a try / catch to save pubs from themselves, and if caught use Math.floor ?

What do you think @dgirardi

@spotxslagle
Copy link
Contributor Author

Maybe a try / catch to save pubs from themselves, and if caught use Math.floor ?

That makes sense to me. I'm guessing a lot of pubs are going to end up calling their rounding function when they try to set it. I'll get that pushed up shortly

let expected = '{"low":"5.00","med":"6.50","high":"6.51","auto":"6.50","dense":"6.50","custom":"6.50"}';
let output = getPriceBucketString(cpm, customConfig);
config.getConfig = getConfig;
expect(JSON.stringify(output)).to.deep.equal(expected);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a test case that also handles if they DO pass a function but the function itself throws an error.

I think the case here actually is testing this part:

  let roundingFunction = Math.floor;
  let customRoundingFunction = config.getConfig('cpmRoundingFunction');
  if (typeof customRoundingFunction === 'function') {
    roundingFunction = customRoundingFunction;
  }

since config.getConfig = () => Math.ceil(5.3) will just return 6.0 not a function.

So typeof customRoundingFunction === 'function' will be false so it will keep default of Math.floor

So another test which does something like:

config.getConfig = () => () => {
   throw new Error('I am an error');
}

So it actually sets roundingFunction to the input customRoundingFunction and tries to execute it, but since it throws an error, it uses Math.floor

try {
cpmTarget = (roundingFunction(cpmToRound) * increment) + bucketMin;
} catch (err) {
cpmTarget = (Math.floor(cpmToRound) * increment) + bucketMin;
Copy link
Collaborator

Choose a reason for hiding this comment

The 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?

@@ -118,17 +119,35 @@ function getCpmTarget(cpm, bucket, granularityMultiplier) {
const precision = typeof bucket.precision !== 'undefined' ? bucket.precision : _defaultPrecision;
Copy link
Collaborator

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.

Copy link
Contributor Author

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.

Copy link
Collaborator

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.

@patmmccann
Copy link
Collaborator

patmmccann commented Sep 22, 2022

If you round up, what happens if someone bids 50000.00 usd for example. Please add a unit test to demonstrate this is handled and discuss in documentation bids over the top value.

@spotxslagle
Copy link
Contributor Author

I don't really understand what the requested unit test and docs changes have to do with this change. That behavior is entirely unaffected. As noted in the comment on line 85 (now 86), if the bid exceeds the cap, the cap will be returned. It will do so without ever touching this change. Even if it were related, the current unit tests cover this sufficiently, as the cap is returned for the low price config in the custom rounding function unit test.

@spotxslagle
Copy link
Contributor Author

@patmmccann What's your take? I haven't worked with the bucket manager before, so I wouldn't be shocked if I missed something. Do you think more unit tests/documentation is needed here?

@patmmccann patmmccann merged commit 63adafb into prebid:master Oct 6, 2022
JacobKlein26 pushed a commit to nextmillenniummedia/Prebid.js that referenced this pull request Feb 9, 2023
* Allow custom rounding functions

* Add custom rounding unit tests

* Default to Math.floor when passed an invalid rounding function

* Add error logging

* Fix import statement
jorgeluisrocha pushed a commit to jwplayer/Prebid.js that referenced this pull request May 23, 2023
* Allow custom rounding functions

* Add custom rounding unit tests

* Default to Math.floor when passed an invalid rounding function

* Add error logging

* Fix import statement
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants