210 lines
6.9 KiB
Clojure
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}]]})
|