Exemple #1
0
        public static void Register(string name, string description, Func<string> identify = null, Func<Experiment, bool> conclude = null, Func<Experiment, IOrderedEnumerable<KeyValuePair<int, double>>> score = null, Func<string, int, int> splitOn = null, object[] alternatives = null, params string[] metrics)
        {
            var experiment = new Experiment(name, description, identify, conclude, score, splitOn, alternatives, metrics);
            ExperimentRepository.Save(experiment);

            foreach (var metric in experiment.Metrics.Select(GetOrRegisterMetric))
            {
                metric.Hook += (sender, args) => Track(experiment, args);
            }
        }
Exemple #2
0
        public virtual Score Score(Experiment experiment, double probability = 90.0)
        {
            var score = new Score();

            // sort by conversion rate
            var sorted = experiment.Score(experiment);
            var @base = sorted.Skip(1).Take(1).First(); // sorted[-2]

            // calculate z-score
            var cohort = experiment.ParticipantsByAlternative();
            var pc = @base.Value;
            var nc = cohort[@base.Key];
            foreach (var alt in sorted)
            {
                var p = alt.Value;
                var index = alt.Key;
                var n = cohort[index];
                var zscore = (p - pc)/((p * (1 - p) / n) + (pc * (1 - pc) / nc)).Abs().Pow(0.5);
                zscore = double.IsNaN(zscore) ? 0 : zscore;
                score.Alternatives.Add(new Alternative
                {
                    Index = index,
                    Name = experiment.Alternatives[index - 1].ToString(),
                    Label = "Option " + (char)(index + 64),
                    Value = alt.Value,
                    ZScore = zscore,
                    Probability = ProbabilityOfScore(zscore)
                });
            }
            score.Base = score.Alternatives[@base.Key - 1];

            // difference is measured from least performant
            KeyValuePair<int, double> least;
            if ((least = sorted.FirstOrDefault(kv => kv.Value > 0)).Value > 0)
            {
                foreach (var alt in sorted.Where(alt => alt.Value > least.Value))
                {
                    score.Alternatives[alt.Key].Difference = (alt.Value - least.Value) / least.Value * 100;
                }
                score.Least = score.Alternatives[least.Key - 1];
            }

            // best alternative is one with highest conversion rate (best shot).
            if (sorted.Last().Value > 0.0)
            {
                score.Best = score.Alternatives[sorted.Last().Key - 1];
            }

            // choice alternative can only pick best if we have high probability (>90%)
            score.Choice = experiment.Outcome.HasValue
                               ? score.Alternatives[experiment.Outcome.Value - 1]
                               : (score.Best != null && score.Best.Probability >= probability ? score.Best : null);

            return score;
        }
 public void Save(Experiment experiment)
 {
     var exists = GetByName(experiment.Name);
     var db = _connector();
     if(exists == null)
     {
         db.Insert(experiment);
     }
     else
     {
         db.Update(experiment);
     }
 }
Exemple #4
0
 public static IEnumerable<AlternativeViewModel> ProjectAlternatives(Experiment experiment, Score score)
 {
     var index = 1;
     foreach (var alternative in experiment.Alternatives)
     {
         var value = alternative.ToString();
         var vm = new AlternativeViewModel
         {
             Name = "Option " + (char)(index + 64),
             Participants = experiment.ParticipantsByAlternative()[index],
             Converted = experiment.ConvertedByAlternative()[index],
             ConversionRate = experiment.ConversionRateByAlternative()[index],
             Showing = experiment.AlternativeValue.ToString() == value,
             Choice = score.Choice != null && score.Choice.Index == index,
             Value = value
         };
         index++;
         yield return vm;
     }
 }
Exemple #5
0
 private static void Track(Experiment experiment, MetricEventArgs args)
 {
     if (!experiment.IsActive)
     {
         return;
     }
     args = args;
     experiment.CurrentParticipant.Conversions++;
     experiment.CurrentParticipant.Seen++;
     var index = experiment.AlternativeIndex;
     //def track!(metric_id, timestamp, count, *args)
     //   return unless active?
     //   identity = identity() rescue nil
     //   if identity
     //     return if connection.ab_showing(@id, identity)
     //     index = alternative_for(identity)
     //     connection.ab_add_conversion @id, index, identity, count
     //     check_completion!
     //   end
     // end
 }
 public void Save(Experiment experiment)
 {
     var key = experiment.Name;
     Inner.AddOrUpdate(key, experiment, (n, m) => m);
 }
        public void Save(Experiment experiment)
        {
            var key = experiment.Name;

            Inner.AddOrUpdate(key, experiment, (n, m) => m);
        }