Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid duplicates #158

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/clj/byf/api.clj
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,16 @@
[{:keys [params]}]
(notifications/notify-slack "A new game was added!")
(let [validated (validate/conform-data :game params)
game-id (db/add-game! validated)]
last-game (-> (db/query db/last-game-sql)
first)]
(if (or
(:force validated)
(not (games/equal? validated last-game)))

(as-json
(resp/created "/api/games"
{:id game-id}))))
(as-json
(resp/created "/api/games"
{:id (db/add-game! (dissoc validated :force))}))
(resp/bad-request "Duplicate game"))))

(defn add-player!
"Adds a new user to the platform, authenticated with basic Auth"
Expand Down
7 changes: 7 additions & 0 deletions src/clj/byf/db.clj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@
(h/from :league)
(h/where [:= :id league-id])))

(defn last-game-sql
[]
(-> (h/select :*)
(h/from :game)
(h/order-by [:played_at :desc])
(h/limit 1)))

(defn query
[func & args]
(jdbc/query (db-spec)
Expand Down
20 changes: 20 additions & 0 deletions src/cljc/byf/games.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,23 @@
(if (>= next prev)
(recur rst (+ curr-increase (- next prev)) new-max)
(recur rst 0 new-max))))))

(defn invert-game
[game]
(-> game
(assoc :p1 (:p2 game))
(assoc :p2 (:p1 game))
(assoc :p1_points (:p2_points game))
(assoc :p2_points (:p1_points game))
(assoc :p1_using (:p2_using game))
(assoc :p2_using (:p1_using game))))

(defn equal?
[g1 g2]
(let [useful #(select-keys % [:p1 :p2 :p1_points :p2_points :p1_using :p2_using])
g1_ (useful g1)
g2_ (useful g2)
g2_inv (invert-game g2_)]

(or (= g1_ g2_)
(= g1_ g2_inv))))
25 changes: 13 additions & 12 deletions src/cljs/byf/common/handlers.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,19 @@
:on-failure [:failed]}}))

(defn writer
[page uri on-success transform-params-fn]
(fn [{:keys [db]} _]
{:db db
:http-xhrio {:method :post
:uri uri
:params (merge (transform-params-fn db)
{:league_id (get-league-id db)})

:format (ajax/json-request-format)
:response-format (ajax/json-response-format {:keywords? true})
:on-success [on-success]
:on-failure [:failed]}}))
([page uri on-success transform-params-fn]
(writer page uri on-success transform-params-fn :failed))
([page uri on-success transform-params-fn on-failure]
(fn [{:keys [db]} _]
{:http-xhrio {:method :post
:uri uri
:params (merge (transform-params-fn db)
{:league_id (get-league-id db)})

:format (ajax/json-request-format)
:response-format (ajax/json-response-format {:keywords? true})
:on-success [on-success]
:on-failure [on-failure]}})))

(defn failed
[page]
Expand Down
40 changes: 26 additions & 14 deletions src/cljs/byf/league_detail/handlers.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
:league_id nil
:show-all? false
:game-config shared/default-game-config
:show-notification false
:notification nil
:loading? false
:show-graph false})

Expand All @@ -63,14 +63,18 @@
[name-mapping vals]
(medley/map-keys #(get name-mapping %) vals))

(rf/reg-sub ::show-notification (getter [:show-notification]))
(rf/reg-event-db ::show-notification
(fn [db _]
(common/assoc-in* db page [:show-notification] true)))
(rf/reg-sub ::notification (getter [:notification]))
(rf/reg-event-db ::notification
(fn [db [_ type msg]]
(common/assoc-in* db
page
[:notification]
{:type type
:msg msg})))

(rf/reg-event-db ::clear-notification
(fn [db _]
(common/assoc-in* db page [:show-notification] false)))
(common/assoc-in* db page [:notification] false)))

(rf/reg-sub ::show-graph (getter [:show-graph]))
(rf/reg-sub ::loading? (getter [:loading?]))
Expand Down Expand Up @@ -258,14 +262,20 @@
(rf/reg-event-db ::played_at (setter [:game :played_at]))

(defn- reload-fn-gen
[extra-signal]
(fn [{:keys [db]} _]
{:db db
:dispatch-n (cons extra-signal [[::show-notification]
[::players-handlers/load-players]
[::load-games]])}))
[{:keys [db] :as full} other]
(js/console.log "Other = " other ", full = " full)
{:db db
:dispatch-n [[::notification :success "Game added successfully"]
[::reset-game]
[::players-handlers/load-players]
[::load-games]]})

(rf/reg-event-fx ::add-game-success reload-fn-gen)

(rf/reg-event-fx ::add-game-success (reload-fn-gen [::reset-game]))
(rf/reg-event-fx ::add-game-failed
(fn [{:keys [db]}]
(js/console.log "inside game failed")
{:dispatch [::notification :failure "Duplicate game"]}))

(rf/reg-event-db ::failed (common/failed page))

Expand All @@ -289,7 +299,9 @@

(rf/reg-event-fx ::add-game
(common/writer page "/api/add-game"
::add-game-success game-transform))
::add-game-success
game-transform
::add-game-failed))

(rf/reg-sub ::hidden? (sets/in? page :hidden-players))

Expand Down
13 changes: 9 additions & 4 deletions src/cljs/byf/league_detail/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -428,13 +428,18 @@

(defn notifications
[]
(let [show-notification (rf/subscribe [::handlers/show-notification])]
(let [notification (rf/subscribe [::handlers/notification])]
(fn []
(when @show-notification
[:div.notification.is-success
(when @notification
[:div.notification
{:class (case (:type @notification)
:success "is-success"
:failure "is-failure")}


[:button.delete
{:on-click #(rf/dispatch [::handlers/clear-notification])}]
"Thank you, your game has been recorded"]))))
(:msg @notification)]))))

(defn root
[]
Expand Down
67 changes: 44 additions & 23 deletions test/clj/byf/api_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[clojure.test :refer [deftest is testing use-fixtures join-fixtures]]
[byf.api :as sut]
[byf.db :as db]
[byf.games :refer [invert-game]]
[environ.core :refer [env]]
[ring.mock.request :as mock])
(:import (java.util UUID)))
Expand Down Expand Up @@ -58,7 +59,7 @@
authenticated-req
sut/app)]

(assert (contains? #{201 401} status), "Invalid status code")
(assert (contains? #{201 401 400} status), "Invalid status code")
response))

(defn- store-users!
Expand All @@ -70,6 +71,28 @@

[p1-id p2-id]))

(deftest store-results-invariants-test
(testing "Can't add two equal games"
(let [[p1-id p2-id] (store-users!)
game1 {:p1 (:player-id p1-id)
:p2 (:player-id p2-id)
:league_id sample-league-id
:p1_using "RM"
:p2_using "Juv"
:p1_points 3
:p2_points 0
:played_at "2018-08-29+01:0021:50:32"}
game2 (invert-game game1)
game3 (assoc game2 :force true)]

(let [first-call (write-api-call "/add-game" game1)
second-call (write-api-call "/add-game" game2)
third-call (write-api-call "/add-game" game3)]

(is (= 201 (:status first-call)))
(is (= 400 (:status second-call)))
(is (= 201 (:status third-call)))))))

(deftest store-results-test
(testing "Should be able to store results"
(let [[p1-id p2-id] (store-users!)
Expand All @@ -80,28 +103,26 @@
:p2_using "Juv"
:p1_points 3
:p2_points 0
:played_at "2018-08-29+01:0021:50:32"}

_ (write-api-call "/add-game" sample)
games (read-api-call "/api/games" {:league_id sample-league-id})

desired {"p1" (str (:player-id p1-id))
"p1_points" 3,
"p1_using" "RM",
"p2" (str (:player-id p2-id)),
"p2_points" 0,
"p2_using" "Juv"
"played_at" "2018-08-29T20:50:00Z"}]

(is (= 200 (:status games)))

(is (= desired
(select-keys
(first (json/read-str (:body games)))
["p1_points" "p2_points"
"p1" "p2"
"p1_using" "p2_using"
"played_at"]))))))
:played_at "2018-08-29+01:0021:50:32"}]
(write-api-call "/add-game" sample)
(let [games (read-api-call "/api/games" {:league_id sample-league-id})
desired {"p1" (str (:player-id p1-id))
"p1_points" 3,
"p1_using" "RM",
"p2" (str (:player-id p2-id)),
"p2_points" 0,
"p2_using" "Juv"
"played_at" "2018-08-29T20:50:00Z"}]

(is (= 200 (:status games)))

(is (= desired
(select-keys
(first (json/read-str (:body games)))
["p1_points" "p2_points"
"p1" "p2"
"p1_using" "p2_using"
"played_at"])))))))

(deftest get-players-test
(testing "Fetching all the existing players"
Expand Down