Skip to content

Commit

Permalink
Can stop, start, restart experiments. Display experiment results on the
Browse files Browse the repository at this point in the history
revision info page.
  • Loading branch information
Doug Youch committed Sep 8, 2010
1 parent 32d4558 commit 37ca27b
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 14 deletions.
41 changes: 37 additions & 4 deletions app/controllers/structure_controller.rb
Expand Up @@ -448,15 +448,26 @@ def edit_page_revision
end

def experiment
view_language

@container = SiteNode.find params[:path][0]
@language = params[:path][1] || 'en'

@experiment = @container.experiment || Experiment.new(:experiment_container => @container)
@experiment.language = @language
@new = params[:new]
if @new
@experiment = Experiment.new(:experiment_container => @container)
else
@experiment = @container.experiment || Experiment.new(:experiment_container => @container)
end

@experiment.language = @view_language
@min_revisions = @experiment.started? ? @experiment.versions.size : 2
@experiment.num_versions = @experiment.id ? @experiment.versions.size : @min_revisions
@experiment.num_versions = @min_revisions if @experiment.num_versions < @min_revisions

@revisions = @container.page_revisions.find(:all, :conditions => {:revision_type => 'real', :language => @view_language}, :select => 'revision, version_name, active', :order => :revision).collect { |r| ["#{r.active ? '*' : ''} #{r.revision} #{r.version_name}".strip, r.revision] }

@revisions = @container.page_revisions.find(:all, :conditions => {:revision_type => 'real', :language => @language}, :select => 'revision, version_name, active', :order => :revision).collect { |r| ["#{r.active ? '*' : ''} #{r.revision} #{r.version_name}".strip, r.revision] }
@max_revisions = @revisions.size
@max_revisions = @min_revisions if @max_revisions < @min_revisions

if request.post? && params[:experiment]
@experiment.num_versions = (params[:num_versions] || @min_revisions).to_i
Expand All @@ -475,6 +486,28 @@ def experiment
render :partial => 'experiment'
end

def update_experiment
view_language

@experiment = Experiment.find params[:path][0]
@experiment.language = @view_language

if params[:start]
@experiment.start! params[:start_time]
elsif params[:restart]
@experiment.restart! params[:end_time], :start_time => params[:start_time], :reset => params[:reset]
elsif params[:stop]
@experiment.end_experiment! params[:end_time]
else params[:select] && params[:version_id]
version_id = params[:version_id].to_i
@experiment.end_experiment! unless @experiment.finished?
@version = @experiment.versions.find { |v| v.id == version_id }
PageRevision.activate_page_revision(@experiment.experiment_container, @version.page_revision.id) if @version && @version.page_revision
end

p_element_info @experiment.experiment_container
end

protected

def view_language
Expand Down
27 changes: 26 additions & 1 deletion app/models/experiment_version.rb
Expand Up @@ -2,11 +2,36 @@
class ExperimentVersion < DomainModel
belongs_to :experiment
has_many :experiment_users, :dependent => :destroy
has_many :successful_users, :conditions => 'success=1'
has_many :successful_users, :conditions => 'success=1', :class_name => 'ExperimentUser'

validates_presence_of :language
validates_presence_of :revision
validates_presence_of :weight
validates_presence_of :experiment_id

def title
return @title if @title
return @title = self.revision.to_s unless self.page_revision
@title = "#{self.page_revision.active? ? '*' : ''} #{self.revision} #{self.page_revision.version_name}"
end

def num_visits
self.experiment_users.count
end

def num_conversions
self.successful_users.count
end

def success_percent
return 0 unless self.num_visits > 0
(self.num_conversions.to_f / self.num_visits.to_f * 100.0).to_i
end

def page_revision
return @page_revision if @page_revision
return nil unless self.experiment && self.experiment.experiment_container
@page_revision = self.experiment.experiment_container.page_revisions.first :conditions => {:revision => self.revision, :language => self.language, :revision_type => 'real'}
end
end

9 changes: 7 additions & 2 deletions app/views/structure/_experiment.html.erb
Expand Up @@ -4,6 +4,7 @@
<script type="text/javascript">
submitExperimentForm = function(frm, update) {
var params = Form.serialize(frm);
params += '&language=<%= @view_language %><%= @new ? "&new=1" : "" %>';
if(update) { params += '&update=1'; }
SCMS.updateOverlay("<%= url_for %>", params);
}
Expand All @@ -12,13 +13,17 @@ submitExperimentForm = function(frm, update) {
<% admin_form_for :experiment, @experiment, :html => { :onsubmit => "submitExperimentForm(this, 1); return false;" } do |f| -%>
<%= f.custom_field '', :value => f.output_error_message('', :base) if @experiment.errors.on(:base) %>
<%= f.text_field :name %>
<%= f.custom_field :num_versions, :value => select_tag(:num_versions, options_for_select((2..@revisions.size).to_a, @experiment.num_versions), :onchange => 'submitExperimentForm(this.form);') %>
<%= f.custom_field :num_versions, :value => select_tag(:num_versions, options_for_select((@min_revisions..@max_revisions).to_a, @experiment.num_versions), :onchange => 'submitExperimentForm(this.form);') %>
<%= f.header 'Select Revisions'.t, :description => 'Leave blank to distribute evenly'.t %>
<% (1..@experiment.num_versions).each do |i| -%>
<% version = @experiment.versions[i-1] || ExperimentVersion.new
-%>
<% cms_unstyled_fields_for "experiment[versions][#{i}]", version do |sf| -%>
<%= f.custom_field i.to_s, :value => "#{version.id ? sf.hidden_field(:id) : ''}#{sf.select(:revision, @revisions)} #{sf.text_field(:weight, :size => 4)}%" %>
<% if @experiment.is_running? && version.id -%>
<%= f.custom_field i.to_s, :value => "#{version.id ? sf.hidden_field(:id) : ''}#{sf.text_field(:revision, :readonly => true, :size => 4)} #{sf.text_field(:weight, :size => 4)}%" %>
<% else -%>
<%= f.custom_field i.to_s, :value => "#{version.id ? sf.hidden_field(:id) : ''}#{sf.select(:revision, @revisions)} #{sf.text_field(:weight, :size => 4)}%" %>
<% end -%>
<% end -%>
<% end -%>
<%= f.spacer %>
Expand Down
44 changes: 44 additions & 0 deletions app/views/structure/_experiment_info.html.erb
@@ -0,0 +1,44 @@
<ul class='description_list'>
<li><h2><%= 'Running an Experiment'.t %></h2></li>

<li>
<strong><%= "Name:".t %></strong> <%= h experiment.name %>
<a href='javascript:void(0);' onclick="SCMS.remoteOverlay('<%= url_for :action => 'experiment', :path => @node.id, :language => @view_language %>');">edit</a>
</li>

<% if ! experiment.started? && ! experiment.finished? -%>
<li>Experiment has not started. <a href="javascript:void(0);" onclick="StructureEditor.updateExperiment(<%= experiment.id %>, '<%= jh experiment.language %>', 'start')">Start it now.</a></li>
<% elsif experiment.is_running? -%>
<li><strong><%= "Started on:".t %></strong> <%= experiment.started_at.to_s(:full) %></li>
<li>
<strong><%= "Ends on:".t %></strong> <%= experiment.ended_at ? experiment.ended_at.to_s(:full) : '(not set)'.t %>
<a href="javascript:void(0);" onclick="StructureEditor.updateExperiment(<%= experiment.id %>, '<%= jh experiment.language %>', 'stop')">stop</a>
</li>
<% elsif experiment.finished? -%>
<li><strong><%= "Started on:".t %></strong> <%= experiment.started_at.to_s(:full) %></li>
<li>
<strong><%= "Ended on:".t %></strong> <%= experiment.ended_at.to_s(:full) %>
<a href="javascript:void(0);" onclick="StructureEditor.updateExperiment(<%= experiment.id %>, '<%= jh experiment.language %>', 'restart')">restart</a>
</li>
<% end -%>

<li>
<table class="mini_table">
<% experiment.experiment_versions.each do |version| -%>
<tr>
<td><%= version.title %> (<%= version.weight %>%)</td>
<td>&nbsp;| <%= '%d Visits' / version.num_visits %></td>
<td>&nbsp;| <%= '%d Conversions' / version.num_conversions %></td>
<td>&nbsp;| <%= version.success_percent %>%</td>
<td>
&nbsp;
<a href="<%= url_for :controller => 'edit', :action => 'page', :path => ['page', experiment.experiment_container.id, version.page_revision.id] %>">Edit</a>
<% if experiment.started? -%>
<a href="javascript:void(0);" onclick="StructureEditor.updateExperiment(<%= experiment.id %>, '<%= jh experiment.language %>', 'select', 'version_id=<%= version.id %>')">Select</a>
<% end -%>
</td>
</tr>
<% end -%>
</table>
</li>
</ul>
21 changes: 16 additions & 5 deletions app/views/structure/_revision_info.rhtml
Expand Up @@ -25,6 +25,11 @@ latest = @active_revision_info[2] -%>
<% end -%>
</ul>

<% if @node.experiment -%>
<% @node.experiment.language = @view_language -%>
<%= render(:partial => 'experiment_info', :locals => {:experiment => @node.experiment}) if @node.experiment.versions.size > 0 %>
<% end -%>
<% if permit?('editor_editor') %>
<h2><%= "Edit Page" %></h2>
<% if latest && latest != revision -%>
Expand All @@ -43,10 +48,16 @@ latest = @active_revision_info[2] -%>
<%= revision_saved_details(revision) %>
</div>
<% end -%>
<div class='third'>
<br/>
<a class='large' href='javascript:void(0);' onclick="SCMS.remoteOverlay('<%= url_for :action => 'experiment', :path => @node.id %>');">Run an Experiment</a>
</div>

<% if @node.experiment.nil? || @node.experiment.versions.size == 0 -%>
<div class='third'>
<br/>
<a class='large' href='javascript:void(0);' onclick="SCMS.remoteOverlay('<%= url_for :action => 'experiment', :path => @node.id, :language => @view_language %>');">Run an Experiment</a>
</div>
<% elsif @node.experiment && @node.experiment.finished? -%>
<div class='third'>
<br/>
<a class='large' href='javascript:void(0);' onclick="SCMS.remoteOverlay('<%= url_for :action => 'experiment', :path => @node.id, :language => @view_language, :new => 1 %>');">Run another Experiment</a>
</div>
<% end -%>
<% end -%>
</div>
9 changes: 7 additions & 2 deletions app/views/structure/_structure_editor.rhtml
Expand Up @@ -1059,9 +1059,14 @@ var StructureEditor = {
return false;
}

}

},

updateExperiment: function(experiment_id, language, action, params) {
var updateUrl = "<%= url_for :action => 'update_experiment' %>/" + experiment_id;
var parameters = "language=" + language + "&" + action + "=1";
if(params) { parameters += '&' + params; }
new Ajax.Updater('element_info', updateUrl, {parameters: parameters, evalScripts: true});
}
}

</script>

0 comments on commit 37ca27b

Please sign in to comment.