lib/vanity/experiment/ab_test.rb in vanity-2.2.4 vs lib/vanity/experiment/ab_test.rb in vanity-2.2.6

- old
+ new

@@ -458,11 +458,11 @@ # # a is expensive, only choose a if it performs 2x better than b # a.measure > b.measure * 2 ? a : b # end def outcome_is(&block) raise ArgumentError, "Missing block" unless block - raise "outcome_is already called on this experiment" if @outcome_is + raise "outcome_is already called on this experiment" if defined?(@outcome_is) @outcome_is = block end # Alternative chosen when this experiment completed. def outcome @@ -476,11 +476,11 @@ return unless @playground.collecting? && active? self.enabled = false super unless outcome - if @outcome_is + if defined?(@outcome_is) begin result = @outcome_is.call outcome = result.id if Alternative === result && result.experiment == self rescue => e Vanity.logger.warn("Error in AbTest#complete!: #{e}") @@ -509,30 +509,22 @@ connection.set_experiment_created_at(@id, Time.now) @outcome = @completed_at = nil self end - # clears all collected data for the experiment - def reset - connection.destroy_experiment(@id) - connection.set_experiment_created_at(@id, Time.now) - @outcome = @completed_at = nil - self - end - # Set up tracking for metrics and ensure that the attributes of the ab_test # are valid (e.g. has alternatives, has a default, has metrics). # If collecting, this method will also store this experiment into the db. # In most cases, you call this method right after the experiment's been instantiated # and declared. def save - if @saved + if defined?(@saved) Vanity.logger.warn("Experiment #{name} has already been saved") return end @saved = true - true_false unless @alternatives + true_false unless defined?(@alternatives) fail "Experiment #{name} needs at least two alternatives" unless @alternatives.size >= 2 if !@is_default_set default(@alternatives.first) Vanity.logger.warn("No default alternative specified; choosing #{@default} as default.") elsif alternative(@default).nil? @@ -540,14 +532,14 @@ Vanity.logger.warn("Attempted to set unknown alternative #{@default} as default! Using #{@alternatives.first} instead.") # Set the instance variable directly since default(value) is no longer defined @default = @alternatives.first end super - if @metrics.nil? || @metrics.empty? + if !defined?(@metrics) || @metrics.nil? || @metrics.empty? Vanity.logger.warn("Please use metrics method to explicitly state which metric you are measuring against.") - metric = @playground.metrics[id] ||= Vanity::Metric.new(@playground, name) - @metrics = [metric] + default_metric = @playground.metrics[id] ||= Vanity::Metric.new(@playground, name) + @metrics = [default_metric] end @metrics.each do |metric| metric.hook(&method(:track!)) end end @@ -634,36 +626,36 @@ check_completion! end def filter_visitor?(request, identity) @playground.request_filter.call(request) || - (@request_filter_block && @request_filter_block.call(request, identity)) + (defined?(@request_filter_block) && @request_filter_block && @request_filter_block.call(request, identity)) end def call_on_assignment_if_available(identity, index) # if we have an on_assignment block, call it on new assignments - if @on_assignment_block + if defined?(@on_assignment_block) && @on_assignment_block assignment = alternatives[index] if !connection.ab_seen @id, identity, assignment @on_assignment_block.call(Vanity.context, identity, assignment, self) end end end def rebalance_if_necessary! # if we are rebalancing probabilities, keep track of how long it has been since we last rebalanced - if @rebalance_frequency + if defined?(@rebalance_frequency) && @rebalance_frequency @assignments_since_rebalancing += 1 if @assignments_since_rebalancing >= @rebalance_frequency @assignments_since_rebalancing = 0 rebalance! end end end def has_alternative_weights?(args) - @alternatives.nil? && args.size == 1 && args[0].is_a?(Hash) + (!defined?(@alternatives) || @alternatives.nil?) && args.size == 1 && args[0].is_a?(Hash) end def build_alternatives_with_weights(args) @alternatives = args[0] sum_of_probability = @alternatives.values.reduce(0) { |a,b| a+b } @@ -686,13 +678,13 @@ Alternative.new(self, i, value) end end begin - a = 50.0 + avg = 50.0 # Returns array of [z-score, percentage] norm_dist = [] - (0.0..3.1).step(0.01) { |x| norm_dist << [x, a += 1 / Math.sqrt(2 * Math::PI) * Math::E ** (-x ** 2 / 2)] } + (0.0..3.1).step(0.01) { |x| norm_dist << [x, avg += 1 / Math.sqrt(2 * Math::PI) * Math::E ** (-x ** 2 / 2)] } # We're really only interested in 90%, 95%, 99% and 99.9%. Z_TO_PROBABILITY = [90, 95, 99, 99.9].map { |pct| [norm_dist.find { |x,a| a >= pct }.first, pct] }.reverse end end