This source file includes following definitions.
- GetCurrentTrialState
- SimulateGroupAssignment
- FindExperiment
- VariationParamsAreEqual
- ComputeDifferences
- PermanentStudyGroupChanged
- SessionStudyGroupChanged
#include "components/variations/variations_seed_simulator.h"
#include <map>
#include "base/metrics/field_trial.h"
#include "components/variations/processed_study.h"
#include "components/variations/proto/study.pb.h"
#include "components/variations/variations_associated_data.h"
namespace chrome_variations {
namespace {
void GetCurrentTrialState(std::map<std::string, std::string>* current_state) {
base::FieldTrial::ActiveGroups trial_groups;
base::FieldTrialList::GetActiveFieldTrialGroups(&trial_groups);
for (size_t i = 0; i < trial_groups.size(); ++i)
(*current_state)[trial_groups[i].trial_name] = trial_groups[i].group_name;
}
std::string SimulateGroupAssignment(
const base::FieldTrial::EntropyProvider& entropy_provider,
const ProcessedStudy& processed_study) {
const Study& study = *processed_study.study();
DCHECK_EQ(Study_Consistency_PERMANENT, study.consistency());
const double entropy_value =
entropy_provider.GetEntropyForTrial(study.name(),
study.randomization_seed());
scoped_refptr<base::FieldTrial> trial(
base::FieldTrial::CreateSimulatedFieldTrial(
study.name(), processed_study.total_probability(),
study.default_experiment_name(), entropy_value));
for (int i = 0; i < study.experiment_size(); ++i) {
const Study_Experiment& experiment = study.experiment(i);
if (!experiment.has_forcing_flag() &&
experiment.name() != study.default_experiment_name()) {
trial->AppendGroup(experiment.name(), experiment.probability_weight());
}
}
if (processed_study.is_expired())
trial->Disable();
return trial->group_name();
}
const Study_Experiment* FindExperiment(const Study& study,
const std::string& experiment_name) {
for (int i = 0; i < study.experiment_size(); ++i) {
if (study.experiment(i).name() == experiment_name)
return &study.experiment(i);
}
return NULL;
}
bool VariationParamsAreEqual(const Study& study,
const Study_Experiment& experiment) {
std::map<std::string, std::string> params;
GetVariationParams(study.name(), ¶ms);
if (static_cast<int>(params.size()) != experiment.param_size())
return false;
for (int i = 0; i < experiment.param_size(); ++i) {
std::map<std::string, std::string>::const_iterator it =
params.find(experiment.param(i).name());
if (it == params.end() || it->second != experiment.param(i).value())
return false;
}
return true;
}
}
VariationsSeedSimulator::VariationsSeedSimulator(
const base::FieldTrial::EntropyProvider& entropy_provider)
: entropy_provider_(entropy_provider) {
}
VariationsSeedSimulator::~VariationsSeedSimulator() {
}
int VariationsSeedSimulator::ComputeDifferences(
const std::vector<ProcessedStudy>& processed_studies) {
std::map<std::string, std::string> current_state;
GetCurrentTrialState(¤t_state);
int group_change_count = 0;
for (size_t i = 0; i < processed_studies.size(); ++i) {
const Study& study = *processed_studies[i].study();
std::map<std::string, std::string>::const_iterator it =
current_state.find(study.name());
if (it == current_state.end())
continue;
const std::string& selected_group = it->second;
if (study.consistency() == Study_Consistency_PERMANENT) {
if (PermanentStudyGroupChanged(processed_studies[i], selected_group))
++group_change_count;
} else if (study.consistency() == Study_Consistency_SESSION) {
if (SessionStudyGroupChanged(processed_studies[i], selected_group))
++group_change_count;
}
}
return group_change_count;
}
bool VariationsSeedSimulator::PermanentStudyGroupChanged(
const ProcessedStudy& processed_study,
const std::string& selected_group) {
const Study& study = *processed_study.study();
DCHECK_EQ(Study_Consistency_PERMANENT, study.consistency());
const std::string simulated_group = SimulateGroupAssignment(entropy_provider_,
processed_study);
if (simulated_group != selected_group)
return true;
const Study_Experiment* experiment = FindExperiment(study, selected_group);
DCHECK(experiment);
return !VariationParamsAreEqual(study, *experiment);
}
bool VariationsSeedSimulator::SessionStudyGroupChanged(
const ProcessedStudy& processed_study,
const std::string& selected_group) {
const Study& study = *processed_study.study();
DCHECK_EQ(Study_Consistency_SESSION, study.consistency());
if (processed_study.is_expired() &&
selected_group != study.default_experiment_name()) {
return true;
}
const Study_Experiment* experiment = FindExperiment(study, selected_group);
if (!experiment)
return true;
if (experiment->probability_weight() == 0 &&
!experiment->has_forcing_flag()) {
return true;
}
return !VariationParamsAreEqual(study, *experiment);
}
}