class Split::Alternative

Attributes

experiment_name[RW]
name[RW]
recorded_info[RW]
weight[RW]

Public Class Methods

new(name, experiment_name) click to toggle source
# File lib/split/alternative.rb, line 9
def initialize(name, experiment_name)
  @experiment_name = experiment_name
  if Hash === name
    @name = name.keys.first
    @weight = name.values.first
  else
    @name = name
    @weight = 1
  end
  @p_winner = 0.0
end

Public Instance Methods

all_completed_count() click to toggle source
# File lib/split/alternative.rb, line 52
def all_completed_count
  if goals.empty?
    completed_count
  else
    goals.inject(completed_count) do |sum, g|
      sum + completed_count(g)
    end
  end
end
completed_count(goal = nil) click to toggle source
# File lib/split/alternative.rb, line 47
def completed_count(goal = nil)
  field = set_field(goal)
  Split.redis.hget(key, field).to_i
end
control?() click to toggle source
# File lib/split/alternative.rb, line 92
def control?
  experiment.control.name == self.name
end
conversion_rate(goal = nil) click to toggle source
# File lib/split/alternative.rb, line 96
def conversion_rate(goal = nil)
  return 0 if participant_count.zero?
  (completed_count(goal).to_f)/participant_count.to_f
end
delete() click to toggle source
# File lib/split/alternative.rb, line 177
def delete
  Split.redis.del(key)
end
experiment() click to toggle source
# File lib/split/alternative.rb, line 101
def experiment
  Split::ExperimentCatalog.find(experiment_name)
end
extra_info() click to toggle source
# File lib/split/alternative.rb, line 128
def extra_info
  data = Split.redis.hget(key, 'recorded_info')
  if data && data.length > 1
    begin
      JSON.parse(data)
    rescue
      {}
    end
  else
    {}
  end
end
goals() click to toggle source
# File lib/split/alternative.rb, line 25
def goals
  self.experiment.goals
end
increment_completion(goal = nil) click to toggle source
# File lib/split/alternative.rb, line 87
def increment_completion(goal = nil)
  field = set_field(goal)
  Split.redis.hincrby(key, field, 1)
end
increment_participation() click to toggle source
# File lib/split/alternative.rb, line 83
def increment_participation
  Split.redis.hincrby key, 'participant_count', 1
end
p_winner(goal = nil) click to toggle source
# File lib/split/alternative.rb, line 29
def p_winner(goal = nil)
  field = set_prob_field(goal)
  @p_winner = Split.redis.hget(key, field).to_f
end
participant_count() click to toggle source
# File lib/split/alternative.rb, line 39
def participant_count
  Split.redis.hget(key, 'participant_count').to_i
end
participant_count=(count) click to toggle source
# File lib/split/alternative.rb, line 43
def participant_count=(count)
  Split.redis.hset(key, 'participant_count', count.to_i)
end
record_extra_info(k, value = 1) click to toggle source
# File lib/split/alternative.rb, line 141
def record_extra_info(k, value = 1)
  @recorded_info = self.extra_info || {}

  if value.kind_of?(Numeric)
    @recorded_info[k] ||= 0
    @recorded_info[k] += value
  else
    @recorded_info[k] = value
  end

  Split.redis.hset key, 'recorded_info', (@recorded_info || {}).to_json
end
reset() click to toggle source
# File lib/split/alternative.rb, line 167
def reset
  Split.redis.hmset key, 'participant_count', 0, 'completed_count', 0, 'recorded_info', nil
  unless goals.empty?
    goals.each do |g|
      field = "completed_count:#{g}"
      Split.redis.hset key, field, 0
    end
  end
end
save() click to toggle source
# File lib/split/alternative.rb, line 154
def save
  Split.redis.hsetnx key, 'participant_count', 0
  Split.redis.hsetnx key, 'completed_count', 0
  Split.redis.hsetnx key, 'p_winner', p_winner
  Split.redis.hsetnx key, 'recorded_info', (@recorded_info || {}).to_json
end
set_completed_count(count, goal = nil) click to toggle source
# File lib/split/alternative.rb, line 78
def set_completed_count(count, goal = nil)
  field = set_field(goal)
  Split.redis.hset(key, field, count.to_i)
end
set_field(goal) click to toggle source
# File lib/split/alternative.rb, line 66
def set_field(goal)
  field = "completed_count"
  field += ":" + goal unless goal.nil?
  return field
end
set_p_winner(prob, goal = nil) click to toggle source
# File lib/split/alternative.rb, line 34
def set_p_winner(prob, goal = nil)
  field = set_prob_field(goal)
  Split.redis.hset(key, field, prob.to_f)
end
set_prob_field(goal) click to toggle source
# File lib/split/alternative.rb, line 72
def set_prob_field(goal)
  field = "p_winner"
  field += ":" + goal unless goal.nil?
  return field
end
to_s() click to toggle source
# File lib/split/alternative.rb, line 21
def to_s
  name
end
unfinished_count() click to toggle source
# File lib/split/alternative.rb, line 62
def unfinished_count
  participant_count - all_completed_count
end
validate!() click to toggle source
# File lib/split/alternative.rb, line 161
def validate!
  unless String === @name || hash_with_correct_values?(@name)
    raise ArgumentError, 'Alternative must be a string'
  end
end
z_score(goal = nil) click to toggle source
# File lib/split/alternative.rb, line 105
def z_score(goal = nil)
  # p_a = Pa = proportion of users who converted within the experiment split (conversion rate)
  # p_c = Pc = proportion of users who converted within the control split (conversion rate)
  # n_a = Na = the number of impressions within the experiment split
  # n_c = Nc = the number of impressions within the control split

  control = experiment.control
  alternative = self

  return 'N/A' if control.name == alternative.name

  p_a = alternative.conversion_rate(goal)
  p_c = control.conversion_rate(goal)

  n_a = alternative.participant_count
  n_c = control.participant_count

  # can't calculate zscore for P(x) > 1
  return 'N/A' if p_a > 1 || p_c > 1

  Split::Zscore.calculate(p_a, n_a, p_c, n_c)
end

Private Instance Methods

hash_with_correct_values?(name) click to toggle source
# File lib/split/alternative.rb, line 183
def hash_with_correct_values?(name)
  Hash === name && String === name.keys.first && Float(name.values.first) rescue false
end
key() click to toggle source
# File lib/split/alternative.rb, line 187
def key
  "#{experiment_name}:#{name}"
end