score-the-pigs/src/com/biffweb/my_project/app.clj

210 lines
6.9 KiB
Clojure

(ns com.biffweb.my-project.app
(:require
[clojure.pprint :as pprint]
[clojure.pprint :as pp]
[clojure.string :as str]
[com.biffweb :as biff]
[com.biffweb.my-project.middleware :refer [wrap-session]]
[com.biffweb.my-project.settings :as settings]
[com.biffweb.my-project.ui :as ui]
[honey.sql :as sql]
[next.jdbc :as jdbc]
[org.sqids.clojure :as sqids]))
(defn reset [_]
{:status 200
:headers {"HX-Redirect" "/"}
:session {}})
;; thanks https://stackoverflow.com/a/58098360
(def sqids (sqids/sqids {:alphabet "cdefhjknprtvwxy2345689"}))
(defn game-code []
(apply str (take 6 (sqids/encode sqids [(rand-int Integer/MAX_VALUE)]))))
(defn error-style [s]
[:h4.pico-color-red-500 s])
(defn set-bar [{:keys [example/ds session params] :as _ctx}]
(let [players (map str/trim (-> params :players str/split-lines))]
(if (> 2 (count players))
(error-style "Need at least two players")
(let [id (-> session :id)
code (game-code)
random-order? (= "on" (-> params :random-player-order))
player-order (if random-order?
(shuffle (range 0 (count players)))
(range 0 (count players)))]
(println players)
(println player-order)
(println (interleave players player-order))
(jdbc/execute! ds (sql/format {:insert-into :game
:values [{:id id
:code code
:display_session id
:active false}]
:on-conflict :id
:do-update-set [:code :display_session :active]}))
(jdbc/execute! ds (sql/format {:insert-into :player
:values (for [[p o] (partition 2 (interleave players player-order))]
{:score 0
:name p
:play_order o
:game_code code})}))
{:status 200
:headers {"HX-redirect" "/game"}
:session {:id id}}))))
(defn game [{:keys [session params]
:example/keys [ds]
:as _ctx}]
(let [id (:id session)
_ (println id)
_ (println (str id))
game (jdbc/execute-one! ds (sql/format {:select :*
:from :game
:where [:= :id id]}))
players (sort-by :player/play_order
(jdbc/execute! ds (sql/format {:select :*
:from :player
:where [:= :game_code (:game/code game)]})))]
(println id)
(pprint/pprint game)
(ui/page
{}
[:div
[:nav
[:ul [:li [:strong "Score the pigs"]]]
[:ul [:li (biff/form {:id "reset"
:hx-get "/reset"}
[:button.secondary "Reset"])]]]
[:h4 id]
[:div
[:h4 "Game code is " (:game/code game)]
[:table
[:thead
[:tr
[:th {:scope "col"} "Player"]
[:th {:scope "col"} "Score"]]]
(into [:tbody]
(for [p players]
[:tr
[:th {:scope "row"} (:player/name p)]
[:td (:player/score p)]]))]]])))
(defn control-view [{:keys [session params path-params]
:example/keys [ds]
:as _ctx}]
(let [code (:code path-params)
players (sort-by :player/play_order (jdbc/execute! ds (sql/format {:select :* :from :player :where [:= :game_code code]})))]
(ui/page {}
[:div [:nav
[:ul [:li [:strong "Score the pigs"]]]
[:ul [:li (biff/form {:id "reset"
:hx-get "/reset"}
[:button.secondary "Reset"])]]]
[:h5 (str "Game " code)]
[:table
[:thead
[:tr
[:th {:scope "col"} "Player"]
[:th {:scope "col"} "Score"]]]
(into [:tbody]
(for [p players]
[:tr
[:th {:scope "row"} (:player/name p)]
[:td (:player/score p)]]))]])))
(defn connect
[{:keys [session params]
:example/keys [ds]
:as _ctx}]
(let [code (:game-code params)
game (delay (jdbc/execute-one! ds (sql/format {:select :* :from :game
:where [:= :code code]})))]
(println params)
(if (and code @game)
{:status 200
:session session
:headers {"HX-Redirect" (str "/game/" code)}}
(error-style "Code does not exist."))))
(defn app [{:keys [session params]
:example/keys [ds]
:as _ctx}]
(let [id (:id session)]
(ui/page
{}
[:div
[:nav
[:ul [:li [:strong "Score the pigs"]]]
[:ul [:li (biff/form {:id "reset"
:hx-get "/reset"}
[:button.secondary "Reset"])]]]
[:h4 id]
[:section
[:button {:_ "on click toggle the *display of #new-game-form"} "New game"]]
(biff/form
{:hx-post "/set-bar"
:style {:display :none}
:hx-swap "afterend"
:id ::new-game-form}
[:div
[:textarea#players {:type "textarea" :rows "8" :name "players"}]
[:fieldset
[:legend "Game options:"]
[:label
[:input {:type "checkbox", :name "random-player-order", :checked ""}]
"Random player order"]
;; [:label
;; [:input {:type "checkbox", :name "french", :checked ""}]
;; "French"]
]
[:button {:type "submit"} "Start"]])
(biff/form
{:hx-post "/connect"
:hx-swap "afterend"
:id ::connect-to-game}
[:fieldset
{:role "group"}
[:input
{:name "game-code",
:type "text",
:placeholder "Connect to an existing game"}]
[:input {:type "submit", :value "Connect"}]])])))
(def about-page
(ui/page
{:base/title (str "About " settings/app-name)}
[:p "This app was made with "
[:a {:href "https://biffweb.com"} "Biff"] "."]))
(defn echo [{:keys [params]}]
{:status 200
:headers {"content-type" "application/json"}
:body params})
(def module
{:static {"/about/" about-page}
:routes ["/" {:middleware [wrap-session]}
["" {:get app}]
["game/"
["" {:get game}]
[":code" {:get control-view}]]
["connect" {:post connect}]
["reset" {:get reset}]
["set-bar" {:post set-bar}]]
:api-routes [["/api/echo" {:post echo}]]})