Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Show solutions from top users on problem solutions page #235

Merged
merged 2 commits into from

2 participants

@hans

I've introduced many people to Clojure by way of 4Clojure, and several have been confused on why they need to follow users to see other solutions. This patch adds code to display a few of the solutions from the top users for a given problem. (Somewhat related to #152.)

Screen Shot 2013-03-20 at 10 39 48 AM

Alternatively (/ additionally), we could show solutions from random users. Please let me know your thoughts!

Thanks,
Hans Engel

@amalloy
Owner

I love the general idea of this pull request, but I'm a little wary of some details. In particular, you're grabbing the top users, and then for each one going to the database and asking for their solution; it would be much better to use mongo's $in query to ask the question all in one go. There's also a limit argument you can pass to make sure you only get five results back, so that you won't need the take/filter approach.

The history of these commits is also quite messy; I'd appreciate if you could rebase all the nonsense commits like "typos" out and present a cleaner patch series. If you're not familiar enough with git to do that, it's fine and I can do it, but if possible I'd rather you do.

Anyway, thanks a lot for adding this feature: I think it will help the initial experience of new users quite a bit.

@hans

Thanks for the feedback! My apologies for these egregious errors—I'm only just getting started with Clojure web development and MongoDB.

In particular, you're grabbing the top users, and then for each one going to the database and asking for their solution; it would be much better to use mongo's $in query to ask the question all in one go. There's also a limit argument you can pass to make sure you only get five results back, so that you won't need the take/filter approach.

Done. The querying was a little trickier than I expected, since I wanted to avoid showing solutions with missing content in this new "top users" section. The new code fetches 15 top users and picks 5 of their solutions which have content. We might need to bump up the original fetch amount if it turns out that most of the top users finished the majority of the problems before solutions were stored.

The history of these commits is also quite messy.

I updated the request with a cleaner set of two squashed commits.

src/foreclojure/problems.clj
((73 lines not shown))
(defn show-solutions [id]
(let [problem-id (Integer. id)
user (session/get :user)]
(if-user [{:keys [solved]}]
- (if (some #{problem-id} solved)
- (show-solutions-page problem-id)
- (flash-error (str "/problem/" problem-id)
- "You must solve this problem before you can see others' solutions!"))
- (do
- (session/put! :login-to *url*)
- (flash-error "/login" "You must log in to see solutions!")))))
+ (if (some #{problem-id} solved)
+ (show-solutions-page problem-id)
+ (flash-error (str "/problem/" problem-id)
+ "You must solve this problem before you can see others' solutions!"))
+ (do
+ (session/put! :login-to *url*)
+ (flash-error "/login" "You must log in to see solutions!")))))
@amalloy Owner
amalloy added a note

I don't see a meaningful change here. Is this an accidental reindent, or am I missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@hans

Just removed the accidental indentation changes.

@amalloy amalloy merged commit df813ac into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 41 additions and 19 deletions.
  1. +41 −19 src/foreclojure/problems.clj
View
60 src/foreclojure/problems.clj
@@ -11,7 +11,7 @@
[foreclojure.template :only [def-page content-page]]
[foreclojure.social :only [tweet-link]]
[foreclojure.feeds :only [create-feed]]
- [foreclojure.users :only [golfer? get-user-id disable-codebox?]]
+ [foreclojure.users :only [golfer? get-user-id disable-codebox? get-ranked-users]]
[foreclojure.solutions :only [save-solution get-solution]]
[clojail.core :exclude [safe-read]]
[clojail.testers :only [secure-tester blacklist-symbols]]
@@ -338,35 +338,57 @@ Return a map, {:message, :error, :url, :num-tests-passed}."
" to view unapproved problems")))
(error "No such problem!"))))
+(defn solution-block [username code]
+ [:div.follower-solution
+ [:div.solution-username
+ (link-to (str "/user/" username) username)
+ "'s solution:"]
+ [:pre.solution-code
+ (escape-html code)]])
+
(def-page show-solutions-page [problem-id]
{:title "4Clojure - Problem Solutions"
:content
(list
[:div.message (session/flash-get :message)]
[:div#problems-error.error (session/flash-get :error)]
- [:h3 {:style "margin-top: -20px;"} "Solutions:"]
+ [:h3 {:style "margin-top: -20px;"} "Your solution"]
(with-user [{:keys [_id following]}]
(list
(let [user-code (get-solution :public _id problem-id)]
[:pre.solution-code.solution-user-code
(escape-html user-code)])
- (if (empty? following)
- [:p "You can only see solutions of users whom you follow. Click on any name from the " (link-to "/users" "users") " listing page to see their profile, and click follow from there."]
- (if (some (complement nil?) (map #(get-solution :public % problem-id) following))
- (interpose [:hr.solution]
- (for [f-user-id following
- :let [f-user (:user (from-mongo
- (fetch-one :users
- :where {:_id f-user-id}
- :only [:user])))
- f-code (get-solution :public
- f-user-id problem-id)]
- :when f-code]
- [:div.follower-solution
- [:div.solution-username (str f-user "'s solution:")]
- [:pre.solution-code
- (escape-html f-code)]]))
- [:p "None of the users you follow have solved this problem yet!"])))))})
+
+ [:h3 "Your followers' solutions"]
+ (if (some (complement nil?) (map #(get-solution :public % problem-id) following))
+ (interpose
+ [:hr.solution]
+ (for [f-user-id following
+ :let [f-user (:user (from-mongo
+ (fetch-one :users
+ :where {:_id f-user-id}
+ :only [:user])))
+ f-code (get-solution :public
+ f-user-id problem-id)]
+ :when f-code]
+ (solution-block f-user f-code)))
+ [:p "None of the users you follow have solved this problem yet!"])
+
+ [:h3 "Top users' solutions"]
+ [:p "These solutions were written by some of the top users of 4Clojure."]
+ (interpose
+ [:hr.solution]
+ (let [top-users (take 15 (get-ranked-users))
+ top-users-m (zipmap (map :_id top-users) top-users)
+
+ solns (fetch :solutions
+ :where {:user {:$in (map :_id top-users)}
+ :code {:$ne nil}}
+ :limit 5)]
+ (for [soln solns
+ :let [username (:user (top-users-m (:user soln)))
+ code (:code soln)]]
+ (solution-block username code)))))))})
(defn show-solutions [id]
(let [problem-id (Integer. id)
Something went wrong with that request. Please try again.