diff --git a/app/Queries/Feeds/TrendingQuestionsFeed.php b/app/Queries/Feeds/TrendingQuestionsFeed.php index a81d57d4c..945459ed9 100644 --- a/app/Queries/Feeds/TrendingQuestionsFeed.php +++ b/app/Queries/Feeds/TrendingQuestionsFeed.php @@ -16,9 +16,12 @@ */ public function builder(): Builder { + // (likes * 0.5 + views * 0.2) / (minutes since answered + 1) = trending score + // the +1 is to prevent division by zero + return Question::query() ->withCount('likes') - ->orderBy('likes_count', 'desc') + ->orderByRaw('((`likes_count` * 0.5) + (`views` * 0.2)) / ((strftime("%s", "now") - strftime("%s", `answer_created_at`)) / 60 + 1) desc') ->where('is_reported', false) ->where('is_ignored', false) ->where('answer_created_at', '>=', now()->subDays(7)) diff --git a/tests/Unit/Livewire/Home/TrendingTest.php b/tests/Unit/Livewire/Home/TrendingTest.php index b2aa0639f..01b04da31 100644 --- a/tests/Unit/Livewire/Home/TrendingTest.php +++ b/tests/Unit/Livewire/Home/TrendingTest.php @@ -51,3 +51,65 @@ ->assertSee('There is no trending questions right now') ->assertDontSee($questionContent); }); + +test('renders trending questions orderby trending score', function () { + // (likes * 0.5 + views * 0.2) / (minutes since answered + 1) = trending score + + Question::factory() + ->hasLikes(5) + ->create([ + 'content' => 'trending question 1', + 'answer_created_at' => now()->subMinutes(10), + 'views' => 20, + ]); // score = (5 * 0.5 + 20 * 0.2) / (10 + 1) = 0.59 + + Question::factory() + ->hasLikes(5) + ->create([ + 'content' => 'trending question 2', + 'answer_created_at' => now()->subMinutes(20), + 'views' => 20, + ]); // score = (5 * 0.5 + 20 * 0.2) / (20 + 1) = 0.30 + + Question::factory() + ->hasLikes(15) + ->create([ + 'content' => 'trending question 3', + 'answer_created_at' => now()->subMinutes(20), + 'views' => 100, + ]); // score = (15 * 0.5 + 100 * 0.2) / (20 + 1) = 1.30 + + Question::factory() + ->hasLikes(20) + ->create([ + 'content' => 'trending question 4', + 'answer_created_at' => now()->subMinutes(20), + 'views' => 100, + ]); // score = (20 * 0.5 + 100 * 0.2) / (20 + 1) = 1.42 + + Question::factory() + ->hasLikes(50) + ->create([ + 'content' => 'trending question 5', + 'answer_created_at' => now()->subMinutes(30), + 'views' => 500, + ]); // score = (50 * 0.5 + 500 * 0.2) / (30 + 1) = 4.03 + + Question::factory() + ->hasLikes(50) + ->create([ + 'content' => 'trending question 6', + 'answer_created_at' => now()->subMinutes(30), + 'views' => 700, + ]); // score = (50 * 0.5 + 700 * 0.2) / (30 + 1) = 5.32 + + $component = Livewire::test(TrendingQuestions::class); + $component->assertSeeInOrder([ + 'trending question 6', + 'trending question 5', + 'trending question 4', + 'trending question 3', + 'trending question 1', + 'trending question 2', + ]); +});