docbrown/app/views/field_test/experiments/_experiments.html.erb
Jeremy Friesen 3fb085b3d9
Adding more context to /admin/abtests (#17821)
* Adding more context to `/admin/abtests`

Prior to this commit, the `/admin/abtests` was fully rendered by the
field_test gem (see
https://github.com/ankane/field_test/blob/master/app/views/field_test/experiments/index.html.erb
and
https://github.com/ankane/field_test/blob/master/app/views/field_test/experiments/show.html.erb).

With this commit, we're pre-pending our own
partial (e.g. `app/views/field_test/experiments/_experiments.html.erb`)
in the view paths; which means instead of rendering
https://github.com/ankane/field_test/blob/master/app/views/field_test/experiments/_experiments.html.erb
we render our newly created
`app/views/field_test/experiments/_experiments.html.erb`)

Why the ugly antics in the view?  As I'm not fully certain if this will
"meet" the full needs of those monitoring the experiments.  I'm also
constructing this to most closely match the spreadsheet that has been
assembled for tracking this information.

Why introduce another caching layer for the variant assembly?  The
original caching
layer (e.g. `Articles::Feeds::VariantAssembler.pre_assembled_variants`)
is in place to provide the quickest access to the assembled variants.
But due to the nature of the implemented view, we are needing a
programmatic representation of all variants.  And the added Rails cache
is there to minimize disk reads.

Closes forem/forem#17820

* Update app/models/articles/feeds/variant_assembler.rb

Co-authored-by: Ridhwana <Ridhwana.Khan16@gmail.com>

* Update app/models/articles/feeds/variant_assembler.rb

Co-authored-by: Ridhwana <Ridhwana.Khan16@gmail.com>

Co-authored-by: Ridhwana <Ridhwana.Khan16@gmail.com>
2022-06-03 11:27:09 -04:00

118 lines
4.4 KiB
Text

<style>
details details { padding: 1em 0 0 1.5em; }
</style>
<% experiments.reverse_each do |experiment| %>
<h2><%= experiment.name %><% unless experiment.active? %> <small class="closed">Completed</small><% end %></h2>
<details<%= " open" if experiment.active? %>>
<summary>Experiment Details</summary>
<% if experiment.description %>
<p class="description"><%= experiment.description %></p>
<% end %>
<details<%= " open" if experiment.active? %>>
<summary>Goals for <%= experiment.name %></summary>
<% experiment.goals.each do |goal| %>
<% results = experiment.results(goal: goal) %>
<% if experiment.multiple_goals? %>
<h3><%= goal.titleize %></h3>
<% end %>
<table>
<thead>
<tr>
<th>Variant</th>
<th style="width: 20%;">Participants</th>
<th style="width: 20%;">Conversions</th>
<th style="width: 20%;">Conversion Rate</th>
<th style="width: 20%;">Prob Winning</th>
</tr>
</thead>
<tbody>
<% results.each do |variant, result| %>
<tr>
<td>
<%= variant %>
<% if variant == experiment.winner %>
<span class="check">✓</span>
<% end %>
</td>
<td><%= result[:participated] %></td>
<td><%= result[:converted] %></td>
<td>
<% if result[:conversion_rate] %>
<%= (100.0 * result[:conversion_rate]).round(FieldTest.precision) %>%
<% else %>
-
<% end %>
</td>
<td>
<% if result[:prob_winning] %>
<% if result[:prob_winning] < 0.01 %>
&lt; 1%
<% else %>
<%= (100.0 * result[:prob_winning]).round(FieldTest.precision) %>%
<% end %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
</details>
<% if experiment.id.start_with?("feed_strategy") %>
<% experiment.variants.each do |variant| %>
<details>
<summary>Config for <%= variant %> <% if variant == experiment.winner %><span class="check">✓</span><% end %></summary>
<% config = Articles::Feeds::VariantAssembler.user_config_hash_for(variant: variant) %>
<dl>
<dt>Description</dt>
<dd><%= config["description"] || "n/a" %></dd>
<dt>Weight</dt>
<dd><%= experiment.weights[experiment.variants.index(variant)] %></dd>
<dt>Order Lever</dt>
<dd><%= config["order_by"] %></dd>
<% config["levers"].each do |lever_key, lever| %>
<% next unless lever.key?("query_parameters") %>
<dt>Parameters for <strong><%= lever_key %></strong> relevancy lever</dt>
<% lever["query_parameters"].each do |key, value| %>
<dd><strong><%= key %>:</strong> <%= value %></dd>
<% end %>
<% end %>
</dl>
<table>
<% lever_range = config["levers"].map { |_, lever| lever["cases"].map(&:first) }.flatten.uniq.sort %>
<caption>Relevency Lever(s): Fallback and Range Factors</caption>
<thead>
<tr>
<th>Lever</th>
<th>Fallback</th>
<% lever_range.each do |i| %>
<th><%= i %></th>
<% end %>
</tr>
</thead>
<tbody>
<% config["levers"].each do |lever_key, lever| %>
<% cases = lever["cases"].each_with_object({}) { |(key, value), mem| mem[key] = value } %>
<tr>
<th><%= lever_key %></th>
<td><%= lever["fallback"] %></th>
<% lever_range.each do |i| %>
<td><%= cases.fetch(i, "&nbsp;".html_safe) %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</details>
<% end %>
<% end %>
<p><%= link_to "Data Details", experiment_path(experiment.id) %> <small>(individual user conversions)</small></p>
</details>
<% end %>