Skip to content

Instantly share code, notes, and snippets.

@mjamesruggiero
Created July 11, 2012 05:49
Show Gist options
  • Save mjamesruggiero/3088223 to your computer and use it in GitHub Desktop.
Save mjamesruggiero/3088223 to your computer and use it in GitHub Desktop.
tiered CPM calcs
#!/usr/bin/env ruby
# mjamesuggiero
# Tue Jul 10 22:14:59 PDT 2012
# so embarrassed about this!
require 'test/unit'
class Cpm
def initialize(rate_in_cents, discounted_rate_in_cents, threshold)
@rate = rate_in_cents
@discounted_rate = discounted_rate_in_cents
@threshold = threshold
@debug = false
end
def calculate_earnings(impressions)
threshold_already_met = false
earnings = 0
cpm = @rate / 1000.00
discount_cpm = @discounted_rate / 1000.00
total_impressions = impressions[:previous] + impressions[:now]
if total_impressions < @threshold
earnings = cpm * impressions[:now]
end
if impressions[:previous] >= @threshold
threshold_already_met = true
earnings = discount_cpm * impressions[:now]
end
if not threshold_already_met
if total_impressions == @threshold #you just hit threshold
earnings = cpm * impressions[:now]
elsif total_impressions > @threshold
non_discount_impressions = (impressions[:now] - (total_impressions - @threshold))
discount_impressions = impressions[:now] - non_discount_impressions
earnings = (cpm * non_discount_impressions) + (discount_cpm * discount_impressions)
if @debug
puts "impressions now #{impressions[:now]}"
puts "impressions previous #{impressions[:previous]}"
puts "threshold #{@threshold}"
puts "total impressions #{total_impressions}"
puts "discount_impressions #{discount_impressions}"
puts "non_discount_impressions #{non_discount_impressions}"
end
end
end
#convert to dollars
earnings * 0.01
end
end
class TestCpm < Test::Unit::TestCase
def test_no_impressions_today
cpm = Cpm.new(1000, 500, 2000)
impressions = {previous: 1000, now: 0}
assert_equal(0, cpm.calculate_earnings(impressions))
end
def test_vanilla_impressions
cpm = Cpm.new(1000, 500, 2000)
impressions = {previous: 1000, now: 500}
assert_equal(5, cpm.calculate_earnings(impressions))
end
def test_case_where_threshold_already_crossed
cpm = Cpm.new(1000, 500, 1000)
impressions = {previous: 1000, now: 1000}
assert_equal(5, cpm.calculate_earnings(impressions))
end
def test_case_where_new_events_crossed_threshold
cpm = Cpm.new(1000, 500, 5000)
impressions = {previous: 2000, now: 5000}
assert_equal(40, cpm.calculate_earnings(impressions))
end
def test_case_where_new_events_just_crosses_threshold
cpm = Cpm.new(1000, 500, 5000)
impressions = {previous: 2000, now: 3000}
assert_equal(30, cpm.calculate_earnings(impressions))
end
def test_case_where_new_events_is_small
cpm = Cpm.new(1000, 500, 5000)
impressions = {previous: 4500, now: 600}
assert_equal(5.5, cpm.calculate_earnings(impressions))
end
end
@rweald
Copy link

rweald commented Jul 11, 2012

Also don't be embarassed it was my fault as well for making the old implementation to much about the math and making you guys think you needed to implement it using the piecewise function that I put up on the whiteboard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment