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

Update auction algorithm logic for long-form #3625

Merged
merged 1 commit into from
Mar 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions modules/adpod.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,18 @@ export function callPrebidCacheAfterAuction(bids, callback) {
}
})
}

/**
* Compare function to be used in sorting long-form bids. This will compare bids on price per second.
* @param {Object} bid
* @param {Object} bid
*/
export function sortByPricePerSecond(a, b) {
if (a.cpm / a.video.durationBucket < b.cpm / b.video.durationBucket) {
return 1;
}
if (a.cpm / a.video.durationBucket > b.cpm / b.video.durationBucket) {
return -1;
}
return 0;
}
18 changes: 3 additions & 15 deletions modules/freeWheelAdserverVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

import { registerVideoSupport } from '../src/adServerManager';
import { auctionManager } from '../src/auctionManager';
import { groupBy, deepAccess, logError } from '../src/utils';
import { groupBy, deepAccess, logError, compareOn } from '../src/utils';
import { config } from '../src/config';
import { ADPOD } from '../src/mediaTypes';
import { initAdpodHooks, TARGETING_KEY_PB_CAT_DUR, TARGETING_KEY_CACHE_ID, callPrebidCacheAfterAuction } from './adpod';
import { initAdpodHooks, TARGETING_KEY_PB_CAT_DUR, TARGETING_KEY_CACHE_ID, callPrebidCacheAfterAuction, sortByPricePerSecond } from './adpod';
import { getHook } from '../src/hook';

export function notifyTranslationModule(fn) {
Expand Down Expand Up @@ -37,7 +37,7 @@ export function getTargeting({codes, callback} = {}) {

let bids = getBidsForAdpod(bidsReceived, adPodAdUnits);
bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids;
bids.sort(compareOn('cpm'));
bids.sort(sortByPricePerSecond);

let targeting = {};
if (deferCachingEnabled === false) {
Expand Down Expand Up @@ -119,18 +119,6 @@ function getAdPodAdUnits(codes) {
.filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) != -1 : true);
}

function compareOn(property) {
return function compare(a, b) {
if (a[property] < b[property]) {
return 1;
}
if (a[property] > b[property]) {
return -1;
}
return 0;
}
}

/**
* This function removes bids of same freewheel category. It will be used when competitive exclusion is enabled.
* @param {Array[Object]} bidsReceived
Expand Down
17 changes: 17 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1276,3 +1276,20 @@ export function getMinValueFromArray(array) {
export function getMaxValueFromArray(array) {
return Math.max(...array);
}

/**
* This function will create compare function to sort on object property
* @param {string} property
* @returns {function} compare function to be used in sorting
*/
export function compareOn(property) {
return function compare(a, b) {
if (a[property] < b[property]) {
return 1;
}
if (a[property] > b[property]) {
return -1;
}
return 0;
}
}
61 changes: 60 additions & 1 deletion test/spec/modules/adpod_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as videoCache from 'src/videoCache';
import * as auction from 'src/auction';
import { ADPOD } from 'src/mediaTypes';

import { callPrebidCacheHook, checkAdUnitSetupHook, checkVideoBidSetupHook, adpodSetConfig } from 'modules/adpod';
import { callPrebidCacheHook, checkAdUnitSetupHook, checkVideoBidSetupHook, adpodSetConfig, sortByPricePerSecond } from 'modules/adpod';

let expect = require('chai').expect;

Expand Down Expand Up @@ -990,4 +990,63 @@ describe('adpod.js', function () {
expect(logWarnStub.called).to.equal(false);
})
});

describe('adpod utils', function() {
it('should sort bids array', function() {
let bids = [{
cpm: 10.12345,
video: {
durationBucket: 15
}
}, {
cpm: 15,
video: {
durationBucket: 15
}
}, {
cpm: 15.00,
video: {
durationBucket: 30
}
}, {
cpm: 5.45,
video: {
durationBucket: 5
}
}, {
cpm: 20.1234567,
video: {
durationBucket: 60
}
}]
bids.sort(sortByPricePerSecond);
let sortedBids = [{
cpm: 5.45,
video: {
durationBucket: 5
}
}, {
cpm: 15,
video: {
durationBucket: 15
}
}, {
cpm: 10.12345,
video: {
durationBucket: 15
}
}, {
cpm: 15.00,
video: {
durationBucket: 30
}
}, {
cpm: 20.1234567,
video: {
durationBucket: 60
}
}]
expect(bids).to.include.deep.ordered.members(sortedBids);
});
})
});
32 changes: 16 additions & 16 deletions test/spec/modules/freeWheelAdserverVideo_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ describe('freeWheel adserver module', function() {
});

expect(targeting['preroll_1'].length).to.equal(3);
expect(targeting['midroll_1'].length).to.equal(2);
expect(targeting['midroll_1'].length).to.equal(3);
});

it('should return targeting for passed adunit code', function() {
Expand Down Expand Up @@ -128,7 +128,7 @@ describe('freeWheel adserver module', function() {
});

expect(targeting['preroll_1'].length).to.equal(3);
expect(targeting['midroll_1'].length).to.equal(2);
expect(targeting['midroll_1'].length).to.equal(3);
});

it('should return unique category bids when competitive exclusion is enabled', function() {
Expand All @@ -139,10 +139,10 @@ describe('freeWheel adserver module', function() {
}
});
amStub.returns([
createBid(10, 'preroll_1', 30, '10.00_airline_30s', '123', 'airline'),
createBid(15, 'preroll_1', 30, '15.00_airline_30s', '123', 'airline'),
createBid(15, 'midroll_1', 60, '15.00_travel_60s', '123', 'travel'),
createBid(10, 'preroll_1', 30, '10.00_airline_30s', '123', 'airline')
createBid(10, 'preroll_1', 30, '10.00_395_30s', '123', '395'),
createBid(15, 'preroll_1', 30, '15.00_395_30s', '123', '395'),
createBid(15, 'midroll_1', 60, '15.00_406_60s', '123', '406'),
createBid(10, 'preroll_1', 30, '10.00_395_30s', '123', '395')
]);
let targeting;
getTargeting({
Expand All @@ -157,9 +157,9 @@ describe('freeWheel adserver module', function() {

it('should only select bids less than adpod duration', function() {
amStub.returns([
createBid(10, 'preroll_1', 90, '10.00_airline_90s', '123', 'airline'),
createBid(15, 'preroll_1', 90, '15.00_airline_90s', '123', 'airline'),
createBid(15, 'midroll_1', 90, '15.00_travel_90s', '123', 'travel')
createBid(10, 'preroll_1', 90, '10.00_395_90s', '123', '395'),
createBid(15, 'preroll_1', 90, '15.00_395_90s', '123', '395'),
createBid(15, 'midroll_1', 90, '15.00_406_90s', '123', '406')
]);
let targeting;
getTargeting({
Expand Down Expand Up @@ -194,11 +194,11 @@ describe('freeWheel adserver module', function() {

function getBidsReceived() {
return [
createBid(10, 'preroll_1', 15, '10.00_airline_15s', '123', 'airline'),
createBid(15, 'preroll_1', 15, '15.00_airline_15s', '123', 'airline'),
createBid(15, 'midroll_1', 30, '15.00_travel_30s', '123', 'travel'),
createBid(5, 'midroll_1', 5, '5.00_travel_5s', '123', 'travel'),
createBid(20, 'midroll_1', 60, '20.00_travel_60s', '123', 'travel'),
createBid(10, 'preroll_1', 15, '10.00_395_15s', '123', '395'),
createBid(15, 'preroll_1', 15, '15.00_395_15s', '123', '395'),
createBid(15, 'midroll_1', 30, '15.00_406_30s', '123', '406'),
createBid(5, 'midroll_1', 5, '5.00_406_5s', '123', '406'),
createBid(20, 'midroll_1', 60, '20.00_406_60s', '123', '406'),
]
}

Expand All @@ -225,8 +225,8 @@ function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid,
'appnexus': {
'buyerMemberId': 9325
},
'vastUrl': 'http://nym1-ib.adnxs.com/ab?ro=1&referrer=http%3A%2F%2Fprebid.org%2Fexamples%2Fvideo%2FjwPlayerPrebid.html&e=wqT_3QKQCKAQBAAAAwDWAAUBCOC2reIFENXVz86_iKrdKRiyjp7_7P7s0GQqNgkAAAECCBRAEQEHNAAAFEAZAAAA4HoUFEAhERIAKREJADERG6gw6dGnBjjtSEDtSEgCUMuBwC5YnPFbYABozbp1eIHdBIABAYoBA1VTRJIBAQbwUJgBAaABAagBAbABALgBA8ABBMgBAtABANgBAOABAPABAIoCO3VmKCdhJywgMjUyOTg4NSwgMTU0ODQ0MjQ2NCk7dWYoJ3InLCA5NzUxNzc3MTYeAPQAAZIC8QEhOXpPdkVBaTItTHdLRU11QndDNFlBQ0NjOFZzd0FEZ0FRQVJJN1VoUTZkR25CbGdBWUVwb0FIQ0FBWGdBZ0FHMEFvZ0JBSkFCQVpnQkFhQUJBYWdCQTdBQkFMa0I4NjFxcEFBQUZFREJBZk90YXFRQUFCUkF5UUhWSVlsRnN5SDRQOWtCQUFBQUFBQUE4RF9nQVFEMUFRQUFBQUNZQWdDZ0FnQzFBZ0FBQUFDOUFnQUFBQURBQWdESUFnRGdBZ0RvQWdENEFnQ0FBd0dRQXdDWUF3R29BN2I0dkFxNkF3bE9XVTB5T2pRd016SGdBODBGmgJhIU53M1VaUWkyLvQAKG5QRmJJQVFvQURFCY1cQUFVUURvSlRsbE5Nam8wTURNeFFNMEZTBZwYQUFBUEFfVREMDEFBQVcdDPBMwgI_aHR0cDovL3ByZWJpZC5vcmcvZGV2LWRvY3Mvc2hvdy12aWRlby13aXRoLWEtZGZwLXZpZGVvLXRhZy5odG1s2AIA4AKtmEjqAjRGSgAgZXhhbXBsZXMvBUUkL2p3UGxheWVyUAlseGh0bWzyAhMKD0NVU1RPTV9NT0RFTF9JRBIA8gIaChYyFgAgTEVBRl9OQU1FAR0IHgoaNh0ACEFTVAE-4ElGSUVEEgCAAwCIAwGQAwCYAxegAwGqAwDAA-CoAcgDANgDAOADAOgDAPgDAYAEAJIEDS91dC92Mw3-8E6YBACiBAsxMC4xLjEyLjE4MKgEjq4IsgQSCAEQAhiABSDoAigBKAIwADgDuAQAwAQAyAQA0gQOOTMyNSNOWU0yOjQwMzHaBAIIAeAEAPAEYTYgiAUBmAUAoAX_EQEUAcAFAMkFaXAU8D_SBQkJCQx4AADYBQHgBQHwBcOVC_oFBAgAEACQBgGYBgC4BgDBBgklJPA_yAYA2gYWChAJEDQAAAAAAAAAAAAAEAAYAA..&s=539bcaeb9ce05a13a8c4a6cab3c000194a8e8f53',
'vastImpUrl': 'http://nym1-ib.adnxs.com/vast_track/v2?info=ZQAAAAMArgAFAQlgW0tcAAAAABHV6tP5Q6i6KRlgW0tcAAAAACDLgcAuKAAw7Ug47UhA0-hISLuv1AFQ6dGnBljDlQtiAkZSaAFwAXgAgAEBiAEBkAGABZgB6AKgAQCoAcuBwC4.&s=61db1767c8c362ef1a58d2c5587dd6a9b1015aeb&event_type=1',
'vastUrl': 'http://some-vast-url.com',
'vastImpUrl': 'http://some-vast-imp-url.com',
'auctionId': 'ec266b31-d652-49c5-8295-e83fafe5532b',
'responseTimestamp': 1548442460888,
'requestTimestamp': 1548442460827,
Expand Down