UNPKG

mk9-prebid

Version:

Header Bidding Management Library

137 lines (127 loc) 3.95 kB
import find from 'core-js-pure/features/array/find.js'; const utils = require('./utils.js'); const _defaultPrecision = 2; const _lgPriceConfig = { 'buckets': [{ 'max': 5, 'increment': 0.5 }] }; const _mgPriceConfig = { 'buckets': [{ 'max': 20, 'increment': 0.1 }] }; const _hgPriceConfig = { 'buckets': [{ 'max': 20, 'increment': 0.01 }] }; const _densePriceConfig = { 'buckets': [{ 'max': 3, 'increment': 0.01 }, { 'max': 8, 'increment': 0.05 }, { 'max': 20, 'increment': 0.5 }] }; const _autoPriceConfig = { 'buckets': [{ 'max': 5, 'increment': 0.05 }, { 'max': 10, 'increment': 0.1 }, { 'max': 20, 'increment': 0.5 }] }; function getPriceBucketString(cpm, customConfig, granularityMultiplier = 1) { let cpmFloat = parseFloat(cpm); if (isNaN(cpmFloat)) { cpmFloat = ''; } return { low: (cpmFloat === '') ? '' : getCpmStringValue(cpm, _lgPriceConfig, granularityMultiplier), med: (cpmFloat === '') ? '' : getCpmStringValue(cpm, _mgPriceConfig, granularityMultiplier), high: (cpmFloat === '') ? '' : getCpmStringValue(cpm, _hgPriceConfig, granularityMultiplier), auto: (cpmFloat === '') ? '' : getCpmStringValue(cpm, _autoPriceConfig, granularityMultiplier), dense: (cpmFloat === '') ? '' : getCpmStringValue(cpm, _densePriceConfig, granularityMultiplier), custom: (cpmFloat === '') ? '' : getCpmStringValue(cpm, customConfig, granularityMultiplier) }; } function getCpmStringValue(cpm, config, granularityMultiplier) { let cpmStr = ''; if (!isValidPriceConfig(config)) { return cpmStr; } const cap = config.buckets.reduce((prev, curr) => { if (prev.max > curr.max) { return prev; } return curr; }, { 'max': 0, }); let bucketFloor = 0; let bucket = find(config.buckets, bucket => { if (cpm > cap.max * granularityMultiplier) { // cpm exceeds cap, just return the cap. let precision = bucket.precision; if (typeof precision === 'undefined') { precision = _defaultPrecision; } cpmStr = (bucket.max * granularityMultiplier).toFixed(precision); } else if (cpm <= bucket.max * granularityMultiplier && cpm >= bucketFloor * granularityMultiplier) { bucket.min = bucketFloor; return bucket; } else { bucketFloor = bucket.max; } }); if (bucket) { cpmStr = getCpmTarget(cpm, bucket, granularityMultiplier); } return cpmStr; } function isValidPriceConfig(config) { if (utils.isEmpty(config) || !config.buckets || !Array.isArray(config.buckets)) { return false; } let isValid = true; config.buckets.forEach(bucket => { if (!bucket.max || !bucket.increment) { isValid = false; } }); return isValid; } function getCpmTarget(cpm, bucket, granularityMultiplier) { const precision = typeof bucket.precision !== 'undefined' ? bucket.precision : _defaultPrecision; const increment = bucket.increment * granularityMultiplier; const bucketMin = bucket.min * granularityMultiplier; // 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; // 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); } export { getPriceBucketString, isValidPriceConfig };