This change introduces several things things:
1. Fixes the performance of the `/admin/abtests` page; instead of
rendering all of the experiment results, just render the overview.
2. Adjust the show page for an experiment to show the summary of
results.
3. Favor the existing "started_at" and "ended_at" attributes of
FieldTest (see https://github.com/ankane/field_test#config)
4. Update the field test experiments to include the `started_at` and
`ended_at` attributes.
5. Skip processing all non-active experiments in our conversion handler.
Why are there no tests? This is a page that is Admin only and is only
visible for reporting purposes. So, it's not quite worth writing tests
as you'd need lots of data. So we'll assume the logic from the upstream
[field_test gem][1] is adequate.
Closesforem/forem#17869
[1]:https://github.com/ankane/field_test
In the general sense we have an existing `order by` that follows the
following format: `order(x) = f(x) * rand() ^ ( 1 / g(x))`
For the present [20220603-variant-b][1], `g(x)` is the article’s score.
And `f(x)` is 1.
This pull request introduces a few named variations for the above
`order(x)` formula.
The three named formats each use a different `g(x)` function; namely
`greatest(0.1, ln(1 + greatest(0, public_reactions_count)))`. The more
public_reactions the article has the closer to zero the resulting
positive number will be. And raising a random number, with range
`(0..1)`, to the inverse of that number will tend to mean that artciles
with many reactions will tend to group towards the higher end of the
random range, whereas articles with few reactions will have a more even
distribution across the range.
Further the `ln` function helps dampen the weight we give to reactions.
The variation within these three order levers is on the `f(x)` portion:
1. Using `published_at`
2. Using `last_commented_at`
3. Using a mix of `published_at` and `last_commented_at`
In all cases, those dates are converted to an integer. A date 2 weeks
ago will result in a number less than a date 1 week ago which will be
less than a today.
The idea for the mix of `published_at` and `last_commented_at` is to see
a mix of things where some “older” articles (from the underlying result
set) will get a chance to show up earlier in the feed.
My rational for this order structure is because the `RANDOM() ^ (1 /
score)` is showing possible success in a current experiment. And in
past trials long past, it rose to the top as a likely and viable
contender.
These new `order_by` lever patterns introduce three things:
1. A variable based on a date in time
2. A dampening of what can be a large number; (we have scores in the
publication range that are between -200 and 750 so I think it is
important to apply a dampening. For example `(0.1 ^ (1/100)) =
0.977` and `(0.01 ^ (1/100)) = 0.955`; in other words these large
scores aggressively pushed their corresponding posts to the top of
the relevance; even as we weren't explicitly querying for those
scores.
3. With the score being quasi-magical, it doesn’t make sense to sort on
that value but to instead sort on a property that represents what
we’re setting as our experiment goals (e.g. publishing something or
commenting on something and/or reacting to something)
Note: it would be feasible to extract these into a singular order lever
that we would configure. But that's a future concern.
Also note, none of these are yet part of any experiment, but are instead
being "queued up" to add to our available corpus.
Closesforem/forem#17834
Related to:
- forem/forem#17827
- forem/forem#17826
- forem/forem#17833
- forem/forem#16128 :: for past order queries to seek as inspiration
[1]:https://github.com/forem/forem/blob/main/config/feed-variants/20220603-variant-b.json
* Adds the Assign Role modal to the Member Index View
* Adds e2e tests for the Assign role modal
* WIP: Conditionally redirects to the correct view upon assigning a role
* Conditionally renders the redirect in the correct method :|
* Adjusts the conditional redirect to account for ID
* Adds an even more explicit check for the correct refferer
This is uncalled code. We instead use
`Spam::Handler.handle_article!` (see
[Article#create_conditional_autovomits][1]) for usage.
```shell
❯ rg ArticleHandler; echo $?
1
```
The above command shows for the "after this commit" state that there are
no mentions of the `ArticleHandler`. The `1` is the exit status of the
`rg` (e.g. `ripgrep`). A 1 exit status means no matches found.
[1]:bea711310e/app/models/article.rb (L915-L917)
Relates to forem/forem#15412
* Add utils for preset date ranges
* show the preset options in the calendar
* allow ranges to be selected in storybook
* add some more docs
* add missing prop type
* add tests
* move story out of beta
* fix last time periods
* small refactors
Prior to this commit, we were always using a new random number for a
query. With this commit we cache the randomized seed; which allows us
to have "a repeatable random" experience within a windo of time.
Closesforem/forem#17826
* refactor(listings-dashboard): migrates comp to pure comp
* refactor(listing-dashboard): organizes data setup for tests
* refactor(listing-dashboard): uses func to setup tests and starts using screen
* test(listing-dashboard): refactors tests using role query and expects
* test(listing-dashboard): separate first listing tests into another description block
* test(listing-dashboard): separate second listing tests into another description block
* test(listing-dashboard): separate third listing tests into another description block
* feat: create a crayons component called MultiInput that appears under App Components/MultiInput
* feat: add the doc describing the components to storybook
* feat: create the component ina different file and reference its usage from the stories
* feat: add a random class to hook up a stylesheet to the component
* lets just copy soem HTML
* chore: remove arias that will not be used for the multiinput
* feat: update the classnames and remove unneeded html
* feat: multi input css updates
* feat: add the ability to set the list of emails using state
* feat: add the ability to clear the input selection
* feat: remove item
* feat: handle key events like space, comma and enter in the input
* refactor: clean up code a bit
* refactor: rename email to item
* fix: remove space keydown as its causing weird behaviour
* refactor: remove unused css now that we using pills
* feat: ensure that we do not add blank pills
* feat: add the component to BETA
* feat: rename addToList to addItemToList to be more verbose
* feat: add the first component prop i.e. placeholder
* feat: add a more descriptive text
* feat: add a padding to the field
* remove unused arial labels, and erword soem descriptions
* feat: add imports to scss
* Update app/javascript/crayons/MultiInput/MultiInput.jsx
Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
* Update app/javascript/crayons/MultiInput/MultiInput.jsx
Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
* Update app/javascript/crayons/MultiInput/__stories__/MultiInput.mdx
Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>
Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
Co-authored-by: Julianna Tetreault <32834804+juliannatetreault@users.noreply.github.com>
The commit includes three changes that work to allow us to "seed" the
randomization. When using the same seed, and randomizer should/must
return the same sequence of numbers.
First, I added the "seed" parameter to the variant query. If you want
the same sequence of random numbers from query to query, pass the same
seed. Otherwise, we'll use a Ruby generated random seed.
Second, I added a virtual column to the virtual `article_relevancies`
table. If you provide a seed, and call the query twice, the first row
in each of `article_relevancies` will have the same `randomized_value`,
likewise the second row, etc.
Third, I amended the existing `order_by_lever` that had a `RANDOM()`
postgresql function call. I replaced that with the `randomized_value`
which is computed based on the provided seed.
Fundamentally the idea is to allow for randomness but introduce possible
repeatability; a hard thing considering that some of the inner selection
criteria is not fixed (e.g. number of reactions can change from moment
to moment).
I wrote a [complimentary blog post][1] to further explain what's
happening.
Related to forem/forem#17826
[1]:https://takeonrules.com/2022/06/03/adding-reproducible-randomization-to-sql-queries/
This commit contains two separate but related changes:
1. A check-list for creating a new experiment.
2. A new experiment along with declaring a winner for the previous experiment.
Below are the diffs of the two new variants versus the incumbent for the
experiment:
```
❯ diff config/feed-variants/20220603-variant-b.json config/feed-variants/20220518-variant.json
3,4c3
< "description": "As 202205518-variant but with modificiation to `order_by` lever.",
< "order_by": "final_order_by_random_weighted_to_score",
---
> "order_by": "relevancy_score_and_publication_date",
```
```
❯ diff config/feed-variants/20220603-variant-a.json config/feed-variants/20220518-variant.json
3d2
< "description": "As 202205518-variant but with modificiation to `matching_positive_tags_intersection_count`.",
69c68
< [0, 0.5],
---
> [0, 0.7],
```
Closesforem/forem#17822