Skip to content

Commit

Permalink
Include position in ranking for each challenge in user page
Browse files Browse the repository at this point in the history
Additionally to showing the best player score and the best score for the
challenge, include the actual position of the best user score in the
ranking for that particular challenge.

Benchmarking: Created db:setup with challenges=300 users=10000, patched
db/seeds.db to have most challenges have a random number of entries in
the range 100..2,000, but 2% of them in the range 5,000..40,000, to
provide a more realist test scenario. (Creating all challenges with
20,000 entries just made all queries too expensive from the start.)

With that setup, I measured the effects of loading a user page, for a
user with entries in 36 challenges, which included all 6 challenges with
over 5,000 entries. More specifically, the 6 top challenges ranged from
17,829 to 37,251 entries.

I then loaded this page 10 times, with and without the changes in this PR.
I took the average and standard deviation of the 10 measurements for
each situation.

  - Without this PR:  0.25547s ± 0.00663s
  - With this PR:     2.23918s ± 0.05312s

This is a roughly 9x increase, which is perhaps quite expensive to make
it acceptable, even though the feature itself is very nice.
  • Loading branch information
filbranden committed Aug 11, 2020
1 parent dd31c71 commit 6cabc81
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
33 changes: 29 additions & 4 deletions app/repositories/repository_challenge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,14 @@ def self.player_best_scores(player_id)
}
},
{ "$unwind": "$entries" },
{ "$match": { "entries.user_id": player_id } },
{ "$sort": { "entries.score": 1 } },
{ "$sort": { "entries.score": 1, "entries.created_at": 1 } },
{
"$group": {
"_id": '$_id',
"_id": {
"challenge_id": '$_id',
"user_id": '$entries.user_id'
},
"user_id": { "$first": '$entries.user_id'},
"title": { "$first": '$title'},
"description": { "$first": '$description'},
"created_at": { "$first": '$created_at'},
Expand All @@ -362,7 +365,29 @@ def self.player_best_scores(player_id)
"attempts": { "$sum": 1 }
},
},
{ "$sort": { "created_at": -1 } },
{ "$sort": { "best_player_score": 1, "created_at": 1 } },
{
"$group": {
"_id": "$_id.challenge_id",
"items": { "$push": "$$ROOT" },
}
},
{ "$unwind": { "path": "$items", "includeArrayIndex": "items.position" }},
{ "$match": { "items.user_id": player_id }},
{ "$sort": { "items.created_at": -1 } },
{
"$project": {
"_id": 1,
"title": "$items.title",
"description": "$items.description",
"created_at": "$items.created_at",
"count_entries": "$items.count_entries",
"best_score": "$items.best_score",
"best_player_score": "$items.best_player_score",
"attempts": "$items.attempts",
"position": { "$add": ["$items.position", 1]}
}
},
)
end

Expand Down
1 change: 1 addition & 0 deletions app/views/users/show.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<ul>
<li>Best score: <b><%= player_challenge['best_score'] %></b></li>
<li>Best player score: <b><%= player_challenge['best_player_score'] %></b></li>
<li>Position: <b>#<%= player_challenge['position'] %></b></li>
<li>Number of attempts: <b><%= player_challenge['attempts'] %></b></li>
</ul>
</div>
Expand Down
3 changes: 3 additions & 0 deletions spec/repositories/repository_challenge_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@
expect(challenge['best_score']).to eq(10)
expect(challenge['best_player_score']).to eq(12)
expect(challenge['attempts']).to eq(2)
expect(challenge['position']).to eq(2)
end
end

Expand Down Expand Up @@ -459,6 +460,7 @@
expect(challenge['best_score']).to eq(14)
expect(challenge['best_player_score']).to eq(14)
expect(challenge['attempts']).to eq(1)
expect(challenge['position']).to eq(1)

# And challenge1 is next.
challenge = result[1]
Expand All @@ -469,6 +471,7 @@
expect(challenge['best_score']).to eq(10)
expect(challenge['best_player_score']).to eq(12)
expect(challenge['attempts']).to eq(2)
expect(challenge['position']).to eq(2)
end
end

Expand Down

0 comments on commit 6cabc81

Please sign in to comment.