Skip to content

Instantly share code, notes, and snippets.

@coderek
Created November 5, 2014 03:11
Show Gist options
  • Save coderek/fd9916165f05bd957e20 to your computer and use it in GitHub Desktop.
Save coderek/fd9916165f05bd957e20 to your computer and use it in GitHub Desktop.
var log = console.log.bind(console);
/**
* Given a ad
* calculate max bid rate
*/
function calculate_max_bid_rate(ad) {
var org_chain = get_org_chain(ad);
// this is the selling price to the campaign user
var max_cpm = ad.max_cpm;
var org_buying_price = 0;
var org_selling_price = max_cpm;
org_chain.forEach(function (org) {
// get pricing model from organization for this creative
// each organization has different pricing model for each creative
var pricing = org.get_pricing_model(ad.creative);
var pricing_type = pricing.type;
var margin_rate = pricing.margin_rate;
var margin_percentage = pricing.margin_percentage;
// new fields
var max_buying_rate = pricing.max_buying_rate;
switch (pricing_type) {
case 'fixed_margin_rate':
org_buying_price = org_selling_price - margin_rate;
// set selling price for next org
org_selling_price = org_buying_price;
break;
case 'flat_selling_rate':
org_buying_price = max_buying_rate;
// set selling price for next org
org_selling_price = org_buying_price;
break;
case 'fixed_margin_percentage':
org_buying_price = org_selling_price * ( 1 - margin_percentage);
// set selling price for next org
org_selling_price = org_buying_price;
break;
}
});
return org_buying_price;
}
function calculate_earnings_and_costs(bid_rate, ad) {
// reverse org_chain from top down
var org_chain = get_org_chain(ad).reverse();
var earnings = [];
var costs = [];
// this is the actual cost of parent org
var actual_buy = bid_rate;
var actual_sell = actual_buy;
// start from root org
org_chain.forEach(function (org, i) {
var pricing = org.get_pricing_model(ad);
// no matter what, cost is the actual sell price of parent org
costs[i] = actual_sell;
switch (pricing.type) {
case 'fixed_margin_rate':
earnings[i] = pricing.margin_rate;
actual_sell = costs[i] + pricing.margin_rate;
break;
case 'fixed_margin_percentage':
actual_sell = costs[i] / (1 - pricing.margin_percentage)
earnings[i] = actual_sell * pricing.margin_percentage;
break;
case 'flat_selling_rate':
earnings[i] = pricing.flat_selling_price - costs[i];
actual_sell = pricing.flat_selling_price;
break;
}
});
return earnings.map(function (e, i) {return {earning: e, cost: costs[i]}});
}
/**
* get a list of organzations
*
* bottom up
*
*/
function get_org_chain(ad) {
// some test cases, ignore ad
return [
new Organization({
type: 'fixed_margin_percentage',
margin_percentage: 0.1
}),
new Organization({
type: 'flat_selling_rate',
flat_selling_price: 20,
max_buying_rate: 12
}),
new Organization({
type: 'fixed_margin_rate',
margin_rate: 2.0
}),
new Organization({
type: 'fixed_margin_rate',
margin_rate: 1.0
})
];
}
/**
* [Organization description]
*/
function Organization(pricing) {
this.pricing = pricing;
}
Organization.prototype.get_pricing_model = function (creative) {
// for testing ignore creative
return this.pricing;
};
/**
* Pricing model for each creative
*
* @param {string} type the type of pricing model
* @param {float} margin_rate if the type is 'fixed_margin_rate', this value is used
* @param {float} margin_percentage if the type is 'fixed_margin_percentage', this value is used
* @param {float} max_buying_rate if the type is 'flat_selling_price', this value is used
* @param {float} selling_price if the type is 'flat_selling_price', this value is used
*/
function Pricing() {}
var ad = {
max_cpm: 10,
// for testing, this value can be null
creative: null
};
var bid = calculate_max_bid_rate(ad);
log(bid);
var bid_rate = bid / 2;
var ec = calculate_earnings_and_costs(bid_rate, ad);
log(JSON.stringify(ec));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment