Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
194 lines (169 sloc) 6.44 KB
(ns foreclojure.users
(:require [ring.util.response :as response]
[sandbar.stateful-session :as session])
(:use [foreclojure.utils :only [from-mongo def-page row-class get-user with-user]]
[foreclojure.config :only [config repo-url]]
[somnium.congomongo :only [fetch-one fetch update!]]
[compojure.core :only [defroutes GET POST]]
[hiccup.form-helpers :only [form-to hidden-field]]
[ :only [link-to]]))
(def golfer-tags (into [:contributor]
(when (:golfing-active config)
(defn get-user-id [name]
(fetch-one :users
:where {:user name}
:only [:_id])))
(def sort-by-solved-and-date (juxt (comp count :solved) :last-login))
(defn users-sort [users]
(reverse (sort-by sort-by-solved-and-date users)))
(defn get-users []
(let [users (from-mongo
(fetch :users
:only [:user :solved :contributor]))
sortfn (comp - count :solved)]
(sort-by sortfn users)))
(defn get-user-with-ranking [username, users]
(when username
(let [total (count users)
users-with-rankings (map-indexed
(fn [idx itm]
(assoc itm :rank
(str (inc idx) " out of " total)))
(filter #(= username (% :user)) users-with-rankings)))))
(defn get-top-100-and-current-user [username]
(let [users (get-users)
user-ranking (get-user-with-ranking username users)]
{:user-ranking user-ranking
:top-100 (take 100 users)}))
(defn golfer? [user]
(some user golfer-tags))
(defn disable-codebox? [user]
(true? (:disable-code-box user)))
(defn hide-solutions? [user]
(true? (:hide-solutions user)))
(defn email-address [username]
(:email (fetch-one :users :where {:user username})))
(defn mailto [username]
(link-to (str "mailto:" (email-address username))
(defn format-user-ranking [{:keys [rank user contributor solved]}]
(when user
[:h2 "Your Ranking"]
[:div.ranking (str "Username: ")
(when contributor [:span.contributor "* "])
[:a.user-profile-link {:href (str "/user/" user)} user]]
[:div.ranking (str "Rank: " rank)]
[:div.ranking (str "Problems Solved: " (count solved))]
(def-page users-page []
(let [username (session/session-get :user)
{:keys [user-ranking top-100]} (get-top-100-and-current-user username)]
{:title "Top 100 Users"
[:h1 "Top 100 Users"]
(format-user-ranking user-ranking)
[:span.contributor "*"] " "
(link-to repo-url "4clojure contributor")]
[:th {:style "width: 40px;"} "Rank"]
[:th "Username"]
[:th "Problems Solved"]]]
(map-indexed (fn [rownum {:keys [user contributor solved]}]
[:tr (row-class rownum)
[:td (inc rownum)]
(when contributor [:span.contributor "* "])
[:a.user-profile-link {:href (str "/user/" user)} user]]
[:td.centered (count solved)]])
;; TODO: this is snagged from problems.clj but can't be imported due to cyclic dependency, must refactor this out.
(defn get-problems
(fetch :problems
:only [:_id :difficulty]
:where {:approved true}
:sort {:_id 1})))
(get (group-by :difficulty (get-problems)) difficulty [{}])))
(defn get-solved
(:solved (get-user username)))
([username difficulty]
(let [ids (->> (from-mongo
(fetch :problems
:only [:_id]
:where {:approved true, :difficulty difficulty}))
(map :_id)
(filter ids (get-solved username)))))
(def-page user-profile [username]
(let [page-title (str "User: " username)
user-id (:_id (get-user username))]
{:title page-title
[:div.user-profile-name page-title]
(if (session/session-get :user)
(with-user [{:keys [_id following]}]
(if (not= _id user-id)
(let [[url label] (if (some #{user-id} following)
["unfollow" "Unfollow"]
["follow" "Follow"])]
(form-to [:post (str "/user/" url "/" username)]
[:button.user-follow-button {:type "submit"} label]))
[:div {:style "clear: right; margin-bottom: 10px;"} " "]))
[:div {:style "clear: right; margin-bottom: 10px;"} " "])
(for [difficulty ["Elementary" "Easy" "Medium" "Hard"]]
(let [solved (count (get-solved username difficulty))
total (count (get-problems difficulty))]
[:td.count-label difficulty]
{:style (str "width: "
(int (* 100 (/ solved total)))
[:td.count-total "TOTAL:" ]
(count (get-solved username)) "/"
(count (get-problems))]]])}))
(defn follow-user [username operation]
(with-user [{:keys [_id]}]
(let [follow-id (:_id (get-user username))]
(update! :users
{:_id _id}
{operation {:following follow-id}})))
(response/redirect (str "/user/" username)))
(defn set-disable-codebox [disable-flag]
(with-user [{:keys [_id]}]
(update! :users
{:_id _id}
{:$set {:disable-code-box (boolean disable-flag)}})
(response/redirect "/problems")))
(defn set-hide-solutions [hide-flag]
(with-user [{:keys [_id]}]
(update! :users
{:_id _id}
{:$set {:hide-solutions (boolean hide-flag)}})
(response/redirect "/problems")))
(defroutes users-routes
(GET "/users" [] (users-page))
(GET "/user/:username" [username] (user-profile username))
(POST "/user/follow/:username" [username] (follow-user username :$addToSet))
(POST "/user/unfollow/:username" [username] (follow-user username :$pull)))
Jump to Line
Something went wrong with that request. Please try again.