client/server updates to use the newly added lists

just bare-bones changes for now, no list management, and some hardcoding
of list id 0 in places where code is showing something based on the
owned list of cards
This commit is contained in:
Gered 2016-07-24 15:09:30 -04:00
parent 4b2bc86866
commit 20ab3c0693
14 changed files with 588 additions and 325 deletions

View file

@ -6,6 +6,7 @@
[webtools.reagent.bootstrap :as bs] [webtools.reagent.bootstrap :as bs]
[webtools.reagent.components :refer [raw-html]] [webtools.reagent.components :refer [raw-html]]
[mtgcoll.common :refer [max-search-results]] [mtgcoll.common :refer [max-search-results]]
[mtgcoll.client.auth :as auth]
[mtgcoll.client.components.utils :refer [set-short-label symboled-markup th-sortable]] [mtgcoll.client.components.utils :refer [set-short-label symboled-markup th-sortable]]
[mtgcoll.client.components.inventory :refer [inventory]] [mtgcoll.client.components.inventory :refer [inventory]]
[mtgcoll.client.utils :refer [format-currency]])) [mtgcoll.client.utils :refer [format-currency]]))
@ -49,13 +50,13 @@
(> num-results max-search-results)) (> num-results max-search-results))
(defvc card-list-table (defvc card-list-table
[filters pager & [{:keys [no-owned-highlight?] :as options}]] [list-id filters pager & [{:keys [no-owned-highlight?] :as options}]]
(let [sort-settings (r/atom (let [sort-settings (r/atom
{:sort-by :name {:sort-by :name
:ascending? true})] :ascending? true})]
(fn [filters pager] (fn [list-id filters pager]
(let [cards (view-cursor :cards filters (:sort-by @sort-settings) (:ascending? @sort-settings) (:page @pager) (:page-size @pager)) (let [cards (view-cursor :cards list-id (auth/get-username) filters (:sort-by @sort-settings) (:ascending? @sort-settings) (:page @pager) (:page-size @pager))
card-count (view-cursor :count-of-cards filters) card-count (view-cursor :count-of-cards list-id (auth/get-username) filters)
num-pages (min (js/Math.ceil (/ @card-count (:page-size @pager))) num-pages (min (js/Math.ceil (/ @card-count (:page-size @pager)))
(max-pages @pager))] (max-pages @pager))]
(if (vc/loading? cards) (if (vc/loading? cards)
@ -76,8 +77,9 @@
[th-sortable sort-settings :inventory "Inventory"]]] [th-sortable sort-settings :inventory "Inventory"]]]
[:tbody [:tbody
(map (map
(fn [{:keys [id name set_code set_name mana_cost type power toughness rarity paper_price online_price owned_count] :as card}] (fn [{:keys [id name set_code set_name mana_cost type power toughness rarity paper_price online_price quantity] :as card}]
(let [owned? (> owned_count 0)] (let [quantity (or quantity 0)
owned? (> quantity 0)]
^{:key id} ^{:key id}
[:tr {:class (if (and (not no-owned-highlight?) owned?) "warning")} [:tr {:class (if (and (not no-owned-highlight?) owned?) "warning")}
[:td [card-link id name :block-element? true]] [:td [card-link id name :block-element? true]]
@ -89,8 +91,8 @@
[:td rarity] [:td rarity]
[:td (format-currency paper_price true)] [:td (format-currency paper_price true)]
[:td (format-currency online_price true)] [:td (format-currency online_price true)]
[:td [inventory id [:td [inventory id list-id
{:num-owned owned_count {:num-owned quantity
:button-size "xsmall" :button-size "xsmall"
:button-style (if owned? "primary")}]]])) :button-style (if owned? "primary")}]]]))
@cards)]] @cards)]]

View file

@ -13,15 +13,15 @@
["online" "near mint" "lightly played" "moderately played" "heavily played" "damaged"]) ["online" "near mint" "lightly played" "moderately played" "heavily played" "damaged"])
(defn on-add-card (defn on-add-card
[card-id quality foil?] [card-id quality foil? list-id]
(ajax/POST (->url "/collection/add") (ajax/POST (->url "/collection/add")
:params {:card-id card-id :quality quality :foil foil?} :params {:card-id card-id :quality quality :foil foil? :list-id list-id}
:on-error #(set-error! "Server error while adding card to inventory."))) :on-error #(set-error! "Server error while adding card to inventory.")))
(defn on-remove-card (defn on-remove-card
[card-id quality foil?] [card-id quality foil? list-id]
(ajax/POST (->url "/collection/remove") (ajax/POST (->url "/collection/remove")
:params {:card-id card-id :quality quality :foil foil?} :params {:card-id card-id :quality quality :foil foil? :list-id list-id}
:on-error #(set-error! "Server error while adding card to inventory."))) :on-error #(set-error! "Server error while adding card to inventory.")))
(defn can-modify-inventory? (defn can-modify-inventory?
@ -30,7 +30,7 @@
(auth/authenticated?))) (auth/authenticated?)))
(defvc inventory-management (defvc inventory-management
[card-id] [card-id list-id]
(let [inventory (view-cursor :owned-card card-id) (let [inventory (view-cursor :owned-card card-id)
inventory (group-by :quality @inventory) inventory (group-by :quality @inventory)
colspan (if (can-modify-inventory?) 2 1) colspan (if (can-modify-inventory?) 2 1)
@ -72,10 +72,10 @@
[:td.col-sm-3 [:td.col-sm-3
[bs/ButtonGroup {:justified true} [bs/ButtonGroup {:justified true}
[bs/ButtonGroup [bs/ButtonGroup
[bs/Button {:bsStyle "success" :on-click #(on-add-card card-id quality false)} [bs/Button {:bsStyle "success" :on-click #(on-add-card card-id quality false list-id)}
[bs/Glyphicon {:glyph "plus"}]]] [bs/Glyphicon {:glyph "plus"}]]]
[bs/ButtonGroup [bs/ButtonGroup
[bs/Button {:bsStyle "danger" :disabled (= 0 non-foil-quantity) :on-click #(on-remove-card card-id quality false)} [bs/Button {:bsStyle "danger" :disabled (= 0 non-foil-quantity) :on-click #(on-remove-card card-id quality false list-id)}
[bs/Glyphicon {:glyph "minus"}]]]]]) [bs/Glyphicon {:glyph "minus"}]]]]])
;; foil ;; foil
[:td {:class quantity-class} [:td {:class quantity-class}
@ -87,21 +87,21 @@
[:td.col-sm-3 [:td.col-sm-3
[bs/ButtonGroup {:justified true} [bs/ButtonGroup {:justified true}
[bs/ButtonGroup [bs/ButtonGroup
[bs/Button {:bsStyle "success" :on-click #(on-add-card card-id quality true)} [bs/Button {:bsStyle "success" :on-click #(on-add-card card-id quality true list-id)}
[bs/Glyphicon {:glyph "plus"}]]] [bs/Glyphicon {:glyph "plus"}]]]
[bs/ButtonGroup [bs/ButtonGroup
[bs/Button {:bsStyle "danger" :disabled (= 0 foil-quantity) :on-click #(on-remove-card card-id quality true)} [bs/Button {:bsStyle "danger" :disabled (= 0 foil-quantity) :on-click #(on-remove-card card-id quality true list-id)}
[bs/Glyphicon {:glyph "minus"}]]]]])])) [bs/Glyphicon {:glyph "minus"}]]]]])]))
qualities))]]])) qualities))]]]))
(defn inventory (defn inventory
[card-id & [{:keys [num-owned owned? button-size button-style] :as opts}]] [card-id list-id & [{:keys [num-owned owned? button-size button-style] :as opts}]]
[bs/OverlayTrigger {:placement "bottom" [bs/OverlayTrigger {:placement "bottom"
:trigger "click" :trigger "click"
:root-close true :root-close true
:overlay (r/as-component :overlay (r/as-component
[bs/Popover {:class "inventory" :title "Card Inventory"} [bs/Popover {:class "inventory" :title "Card Inventory"}
[inventory-management card-id]])} [inventory-management card-id list-id]])}
[bs/Button [bs/Button
(merge (merge
{:block true} {:block true}

View file

@ -16,7 +16,7 @@
(defroute "/all" [] (page/page [collection/all-cards-list])) (defroute "/all" [] (page/page [collection/all-cards-list]))
(defroute "/sets" [] (page/page [sets/sets-list])) (defroute "/sets" [] (page/page [sets/sets-list]))
(defroute "/set/:code" [code] (page/page [sets/set-details code])) (defroute "/set/:code" [code] (page/page [sets/set-details code]))
(defroute "/card/:id" [id] (page/page [cards/card-details id])) (defroute "/card/:id" [id] (page/page [cards/card-details id 0]))
(defroute "/stats" [] (page/page [stats/stats-page])) (defroute "/stats" [] (page/page [stats/stats-page]))
(defroute "*" [] (page/barebones-page [:div "not found"])) (defroute "*" [] (page/barebones-page [:div "not found"]))

View file

@ -6,6 +6,7 @@
[webtools.cljs.utils :refer [->url pprint-json]] [webtools.cljs.utils :refer [->url pprint-json]]
[webtools.reagent.bootstrap :as bs] [webtools.reagent.bootstrap :as bs]
[webtools.reagent.components :refer [->keyed-comps raw-html]] [webtools.reagent.components :refer [->keyed-comps raw-html]]
[mtgcoll.client.auth :as auth]
[mtgcoll.client.components.cards :refer [card-image card-link]] [mtgcoll.client.components.cards :refer [card-image card-link]]
[mtgcoll.client.components.utils :refer [symbol-image set-heading set-label symboled-markup]] [mtgcoll.client.components.utils :refer [symbol-image set-heading set-label symboled-markup]]
[mtgcoll.client.components.inventory :refer [inventory]] [mtgcoll.client.components.inventory :refer [inventory]]
@ -27,8 +28,8 @@
(->keyed-comps components)]) (->keyed-comps components)])
(defvc card-details (defvc card-details
[id] [id list-id]
(let [card (view-cursor :full-card-info id) (let [card (view-cursor :full-card-info id list-id (auth/get-username))
variations (view-cursor :card-variations id) variations (view-cursor :card-variations id)
pricing (view-cursor :card-pricing id) pricing (view-cursor :card-pricing id)
printings (view-cursor :card-printings (:card_name @card))] printings (view-cursor :card-printings (:card_name @card))]
@ -48,10 +49,11 @@
[:a {:href (->url "#/set/" (:set_code @card))} [:a {:href (->url "#/set/" (:set_code @card))}
[:small [set-heading (:set_code @card) (:set_name @card)]]] [:small [set-heading (:set_code @card) (:set_name @card)]]]
[:div.pull-right [:div.pull-right
[inventory id (let [quantity (or (:quantity @card) 0)]
{:num-owned (:owned_count @card) [inventory id list-id
{:num-owned quantity
:button-size "large" :button-size "large"
:button-style (if (> (:owned_count @card) 0) "primary")}]]] :button-style (if (> quantity 0) "primary")}])]]
[bs/Grid [bs/Grid
{:class "card" :fluid true} {:class "card" :fluid true}
[bs/Col {:sm 6 :class "card-image"} [bs/Col {:sm 6 :class "card-image"}

View file

@ -16,13 +16,14 @@
(defn all-cards-list (defn all-cards-list
[] []
(let [active-search-filters (r/cursor all-cards-search-filters [:active-filters]) (let [active-search-filters (r/cursor all-cards-search-filters [:active-filters])
pager (r/cursor all-cards-search-filters [:pager])] pager (r/cursor all-cards-search-filters [:pager])
list-id 0]
(fn [] (fn []
(set-active-breadcrumb! :all) (set-active-breadcrumb! :all)
[:div [:div
[bs/PageHeader "All Cards"] [bs/PageHeader "All Cards"]
[s/search-filter-selector all-cards-search-filters] [s/search-filter-selector all-cards-search-filters]
[card-list-table @active-search-filters pager]]))) [card-list-table list-id @active-search-filters pager]])))
;;; ;;;
@ -33,11 +34,12 @@
[] []
(let [fixed-filters [{:field :owned? :value true :comparison :=}] (let [fixed-filters [{:field :owned? :value true :comparison :=}]
active-search-filters (r/cursor owned-cards-search-filters [:active-filters]) active-search-filters (r/cursor owned-cards-search-filters [:active-filters])
pager (r/cursor owned-cards-search-filters [:pager])] pager (r/cursor owned-cards-search-filters [:pager])
list-id 0]
(s/apply-search-filters! owned-cards-search-filters fixed-filters) (s/apply-search-filters! owned-cards-search-filters fixed-filters)
(fn [] (fn []
(set-active-breadcrumb! :owned) (set-active-breadcrumb! :owned)
[:div [:div
[bs/PageHeader "Owned Cards"] [bs/PageHeader "Owned Cards"]
[s/search-filter-selector owned-cards-search-filters {:fixed-active-filters fixed-filters}] [s/search-filter-selector owned-cards-search-filters {:fixed-active-filters fixed-filters}]
[card-list-table @active-search-filters pager {:no-owned-highlight? true}]]))) [card-list-table list-id @active-search-filters pager {:no-owned-highlight? true}]])))

View file

@ -61,12 +61,13 @@
[set-code] [set-code]
(let [fixed-filters [{:field :set-code :value set-code :comparison :=}] (let [fixed-filters [{:field :set-code :value set-code :comparison :=}]
active-search-filters (r/cursor set-cards-search-filters [:active-filters]) active-search-filters (r/cursor set-cards-search-filters [:active-filters])
pager (r/cursor set-cards-search-filters [:pager])] pager (r/cursor set-cards-search-filters [:pager])
list-id 0]
(s/apply-search-filters! set-cards-search-filters fixed-filters) (s/apply-search-filters! set-cards-search-filters fixed-filters)
(fn [] (fn []
[:div.set-cards-list [:div.set-cards-list
[s/search-filter-selector set-cards-search-filters {:fixed-active-filters fixed-filters}] [s/search-filter-selector set-cards-search-filters {:fixed-active-filters fixed-filters}]
[card-list-table @active-search-filters pager]]))) [card-list-table list-id @active-search-filters pager]])))
(defvc set-details (defvc set-details
[set-code] [set-code]

View file

@ -6,6 +6,7 @@
[webtools.reagent.bootstrap :as bs] [webtools.reagent.bootstrap :as bs]
[webtools.reagent.components :refer [->keyed-comps]] [webtools.reagent.components :refer [->keyed-comps]]
[webtools.cljs.utils :refer [->url]] [webtools.cljs.utils :refer [->url]]
[mtgcoll.client.auth :as auth]
[mtgcoll.client.page :refer [set-active-breadcrumb!]] [mtgcoll.client.page :refer [set-active-breadcrumb!]]
[mtgcoll.client.utils :refer [format-number format-currency get-field-value]] [mtgcoll.client.utils :refer [format-number format-currency get-field-value]]
[mtgcoll.client.components.utils :refer [set-short-label]] [mtgcoll.client.components.utils :refer [set-short-label]]
@ -84,8 +85,8 @@
:backgroundColor (vec bg-colors)}]}) :backgroundColor (vec bg-colors)}]})
(defvc widget-color-totals (defvc widget-color-totals
[online? & [{:keys [width] :as options}]] [online? list-id & [{:keys [width] :as options}]]
(let [color-totals (view-cursor :stats/color-totals online?)] (let [color-totals (view-cursor :stats/color-totals online? list-id (auth/get-username))]
(if-not (vc/loading? color-totals) (if-not (vc/loading? color-totals)
[bs/Col {:sm (or width 12) :class "widget"} [bs/Col {:sm (or width 12) :class "widget"}
[:div.title "Card Colors"] [:div.title "Card Colors"]
@ -97,8 +98,8 @@
{:vertical-legend? true}]]))) {:vertical-legend? true}]])))
(defvc widget-basic-type-totals (defvc widget-basic-type-totals
[online? & [{:keys [width] :as options}]] [online? list-id & [{:keys [width] :as options}]]
(let [basic-type-totals (view-cursor :stats/basic-type-totals online?)] (let [basic-type-totals (view-cursor :stats/basic-type-totals online? list-id (auth/get-username))]
(if-not (vc/loading? basic-type-totals) (if-not (vc/loading? basic-type-totals)
[bs/Col {:sm (or width 12) :class "widget"} [bs/Col {:sm (or width 12) :class "widget"}
[:div.title "Basic Card Types"] [:div.title "Basic Card Types"]
@ -133,8 +134,8 @@
data)]]])) data)]]]))
(defvc widget-most-owned-sets (defvc widget-most-owned-sets
[online? & [options]] [online? list-id & [options]]
(let [data (view-cursor :stats/most-owned-sets online?)] (let [data (view-cursor :stats/most-owned-sets online? list-id (auth/get-username))]
(if-not (vc/loading? data) (if-not (vc/loading? data)
[table-statistics [table-statistics
"Cards Owned By Set" "Cards Owned By Set"
@ -145,8 +146,8 @@
options]))) options])))
(defvc widget-most-copies-of-card (defvc widget-most-copies-of-card
[online? & [options]] [online? list-id & [options]]
(let [data (view-cursor :stats/most-copies-of-card online?)] (let [data (view-cursor :stats/most-copies-of-card online? list-id (auth/get-username))]
(if-not (vc/loading? data) (if-not (vc/loading? data)
[table-statistics [table-statistics
"Most Copies Owned" "Most Copies Owned"
@ -158,8 +159,8 @@
options]))) options])))
(defvc widget-most-nonland-copies-of-card (defvc widget-most-nonland-copies-of-card
[online? & [options]] [online? list-id & [options]]
(let [data (view-cursor :stats/most-nonland-copies-of-card online?)] (let [data (view-cursor :stats/most-nonland-copies-of-card online? list-id (auth/get-username))]
(if-not (vc/loading? data) (if-not (vc/loading? data)
[table-statistics [table-statistics
"Most Non-land Copies Owned" "Most Non-land Copies Owned"
@ -171,8 +172,8 @@
options]))) options])))
(defvc widget-most-valuable-cards (defvc widget-most-valuable-cards
[online? pricing-source & [options]] [online? list-id pricing-source & [options]]
(let [data (view-cursor :stats/most-valuable-cards online? pricing-source)] (let [data (view-cursor :stats/most-valuable-cards online? pricing-source list-id (auth/get-username))]
(if-not (vc/loading? data) (if-not (vc/loading? data)
[table-statistics [table-statistics
"Most Valuable Cards" "Most Valuable Cards"
@ -184,8 +185,8 @@
options]))) options])))
(defvc widget-rarity-totals (defvc widget-rarity-totals
[online? & [options]] [online? list-id & [options]]
(let [data (view-cursor :stats/card-rarity-totals online?)] (let [data (view-cursor :stats/card-rarity-totals online? list-id (auth/get-username))]
(if-not (vc/loading? data) (if-not (vc/loading? data)
[table-statistics [table-statistics
"Cards Owned By Rarity" "Cards Owned By Rarity"
@ -195,8 +196,8 @@
options]))) options])))
(defvc widget-agg-price-stats (defvc widget-agg-price-stats
[online? pricing-source & [{:keys [width] :as options}]] [online? list-id pricing-source & [{:keys [width] :as options}]]
(let [agg-price-stats (view-cursor :stats/agg-price-stats online? pricing-source) (let [agg-price-stats (view-cursor :stats/agg-price-stats online? pricing-source list-id (auth/get-username))
min-price (:min_price @agg-price-stats) min-price (:min_price @agg-price-stats)
max-price (:max_price @agg-price-stats) max-price (:max_price @agg-price-stats)
avg-price (:avg_price @agg-price-stats) avg-price (:avg_price @agg-price-stats)
@ -209,15 +210,16 @@
[big-currency-statistic "Median Card Value" median-price]]))) [big-currency-statistic "Median Card Value" median-price]])))
(defvc widget-summary-stats (defvc widget-summary-stats
[online? pricing-source & [{:keys [width] :as options}]] [online? list-id pricing-source & [{:keys [width] :as options}]]
(let [agg-price-stats (view-cursor :stats/agg-price-stats online? pricing-source) (let [username (auth/get-username)
owned-total (view-cursor :stats/owned-total online?) agg-price-stats (view-cursor :stats/agg-price-stats online? pricing-source list-id username)
owned-foil-total (view-cursor :stats/owned-foil-total online?) owned-total (view-cursor :stats/owned-total online? list-id username)
distinct-owned-total (view-cursor :stats/distinct-owned-total online?) owned-foil-total (view-cursor :stats/owned-foil-total online? list-id username)
total-sets-owned-from (view-cursor :stats/total-sets-owned-from online?) distinct-owned-total (view-cursor :stats/distinct-owned-total online? list-id username)
total-sets-owned-all-from (view-cursor :stats/total-sets-owned-all-from online?) total-sets-owned-from (view-cursor :stats/total-sets-owned-from online? list-id username)
total-price (view-cursor :stats/total-price online? pricing-source) total-sets-owned-all-from (view-cursor :stats/total-sets-owned-all-from online? list-id username)
num-worth-over-1-dollar (view-cursor :stats/num-cards-worth-over-1-dollar online? pricing-source)] total-price (view-cursor :stats/total-price online? pricing-source list-id username)
num-worth-over-1-dollar (view-cursor :stats/num-cards-worth-over-1-dollar online? pricing-source list-id username)]
[bs/Col {:sm (or width 12) :class "widget"} [bs/Col {:sm (or width 12) :class "widget"}
[widget-row [big-number-statistic "Owned" @owned-total]] [widget-row [big-number-statistic "Owned" @owned-total]]
[widget-row [big-number-statistic "Unique" @distinct-owned-total]] [widget-row [big-number-statistic "Unique" @distinct-owned-total]]
@ -239,7 +241,8 @@
[] []
(let [pricing-sources (view-cursor :pricing-sources) (let [pricing-sources (view-cursor :pricing-sources)
online? (:online? @settings) online? (:online? @settings)
pricing-source (:pricing-source @settings)] pricing-source (:pricing-source @settings)
list-id 0]
(set-active-breadcrumb! :stats) (set-active-breadcrumb! :stats)
(if (and (not (vc/loading? pricing-sources)) (if (and (not (vc/loading? pricing-sources))
(nil? (:pricing-source @settings))) (nil? (:pricing-source @settings)))
@ -268,12 +271,12 @@
[bs/Grid {:fluid true :class "statistics"} [bs/Grid {:fluid true :class "statistics"}
[widget-row [widget-row
[bs/Col {:sm 4} [bs/Col {:sm 4}
[widget-row [widget-summary-stats online? pricing-source]] [widget-row [widget-summary-stats online? list-id pricing-source]]
[widget-row [widget-rarity-totals online?]] [widget-row [widget-rarity-totals online? list-id]]
[widget-row [widget-most-owned-sets online?]]] [widget-row [widget-most-owned-sets online? list-id]]]
[bs/Col {:sm 8} [bs/Col {:sm 8}
[widget-row [widget-color-totals online?]] [widget-row [widget-color-totals online? list-id]]
[widget-row [widget-basic-type-totals online?]] [widget-row [widget-basic-type-totals online? list-id]]
[widget-row [widget-most-valuable-cards online? pricing-source {:width 10}]] [widget-row [widget-most-valuable-cards online? list-id pricing-source {:width 10}]]
[widget-row [widget-most-copies-of-card online? {:width 10}]] [widget-row [widget-most-copies-of-card online? list-id {:width 10}]]
[widget-row [widget-most-nonland-copies-of-card online? {:width 10}]]]]]])) [widget-row [widget-most-nonland-copies-of-card online? list-id {:width 10}]]]]]]))

View file

@ -1,37 +1,43 @@
(ns mtgcoll.models.collection (ns mtgcoll.models.collection
(:require (:require
[clojure.java.jdbc :as jdbc]
[views.sql.core :refer [vexec! with-view-transaction]] [views.sql.core :refer [vexec! with-view-transaction]]
[mtgcoll.db :refer [db]] [mtgcoll.db :refer [db]]
[mtgcoll.views.core :refer [view-system]])) [mtgcoll.views.core :refer [view-system]]))
(defn update-collection! (defn update-collection!
[card-id quality foil? quantity-change] [card-id quality foil? list-id user-id quantity-change]
;; written assuming postgresql server is _not_ 9.5+ (so, without access to UPSERT functionality) ;; written assuming postgresql server is _not_ 9.5+ (so, without access to UPSERT functionality)
(let [list-id (int list-id)
public-only? (nil? user-id)]
(with-view-transaction (with-view-transaction
view-system view-system
[dt @db] [dt @db]
(if-not (first (jdbc/query dt ["select count(*) from lists where id = ? and is_public in (true, ?)" list-id public-only?]))
(throw (new Exception (str "Not authorized to update list:" list-id)))
(let [num-updates (first (let [num-updates (first
(vexec! view-system dt (vexec! view-system dt
["update collection ["update collection
set quantity = quantity + ? set quantity = quantity + ?
where card_id = ? and where card_id = ? and
quality = ? and quality = ? and
foil = ?" foil = ? and
quantity-change card-id quality foil?]))] list_id = ?"
quantity-change card-id quality foil? list-id]))]
(if (= 0 num-updates) (if (= 0 num-updates)
(first (first
(vexec! view-system dt (vexec! view-system dt
["insert into collection ["insert into collection
(card_id, quality, quantity, foil) (card_id, quality, quantity, foil, list_id)
values values
(?, ?, ?, ?)" (?, ?, ?, ?, ?)"
card-id quality quantity-change foil?])) card-id quality quantity-change foil? list-id]))
num-updates)))) num-updates))))))
(defn add-to-collection! (defn add-to-collection!
[card-id quality foil?] [card-id quality foil? list-id user-id]
(update-collection! card-id quality foil? 1)) (update-collection! card-id quality foil? list-id user-id 1))
(defn remove-from-collection! (defn remove-from-collection!
[card-id quality foil?] [card-id quality foil? list-id user-id]
(update-collection! card-id quality foil? -1)) (update-collection! card-id quality foil? list-id user-id -1))

View file

@ -9,11 +9,13 @@
(def collection-routes (def collection-routes
(wrap-middleware (wrap-middleware
(routes (routes
(POST "/collection/add" [card-id quality foil :as request] (POST "/collection/add" [card-id quality foil list-id :as request]
(collection/add-to-collection! card-id quality foil) (let [username (get-in request [:session :user :username])
(response/json {:status "ok"})) result (collection/add-to-collection! card-id quality foil list-id username)]
(POST "/collection/remove" [card-id quality foil :as request]
(collection/remove-from-collection! card-id quality foil)
(response/json {:status "ok"}))) (response/json {:status "ok"})))
(POST "/collection/remove" [card-id quality foil list-id :as request]
(let [username (get-in request [:session :user :username])
result (collection/remove-from-collection! card-id quality foil list-id username)]
(response/json {:status "ok"}))))
(wrap-authenticated))) (wrap-authenticated)))

View file

@ -1,10 +1,12 @@
(ns mtgcoll.views.core (ns mtgcoll.views.core
(:require (:require
[clojure.tools.logging :as log]
[views.reagent.sente.server :as vr] [views.reagent.sente.server :as vr]
[views.core :as views] [views.core :as views]
[views.sql.view :refer [view]] [views.sql.view :refer [view]]
[honeysql.format :as fmt] [honeysql.format :as fmt]
[mtgcoll.db :refer [db]] [mtgcoll.db :refer [db]]
[mtgcoll.auth :as auth]
[mtgcoll.views.sente :refer [sente-socket]] [mtgcoll.views.sente :refer [sente-socket]]
[mtgcoll.views.functions.cards :as cards] [mtgcoll.views.functions.cards :as cards]
[mtgcoll.views.functions.sets :as sets] [mtgcoll.views.functions.sets :as sets]
@ -56,11 +58,42 @@
#_(views/add-views! view-system views) #_(views/add-views! view-system views)
(defn view-auth-fn
[{:keys [view-id parameters] :as view-sig} subscriber-key context]
(let [request context
username (get-in request [:session :user :username])]
(if-not (auth/using-authorization?)
true
(case view-id
; views where the user-id parameter is always last
(:stats/owned-total :stats/owned-foil-total :stats/distinct-owned-total :stats/color-totals
:stats/basic-type-totals :stats/most-common-types :stats/total-sets-owned-from
:stats/total-sets-owned-all-from :stats/most-owned-sets :stats/most-copies-of-card
:stats/most-nonland-copies-of-card :stats/total-price :stats/agg-price-stats :stats/most-valuable-cards
:stats/num-cards-worth-over-1-dollar :stats/card-rarity-totals :full-card-info)
(= username (last parameters))
; views where the user-id parameter is second
(:cards :count-of-cards)
(= username (second parameters))
; assume otherwise that the view is not one that requires an auth check (no user-id parameter)
true))))
(defn view-on-unauth-fn
[{:keys [view-id parameters] :as view-sig} subscriber-key context]
(let [request context
user-profile (get-in request [:session :user])]
(log/warn "Unauthorized view subscription attempt: " view-id ", " parameters " - user profile: " user-profile)))
(defn init! (defn init!
[] []
(vr/init! view-system @sente-socket (vr/init! view-system @sente-socket
{:views views {:views views
:use-default-sente-router? true})) :use-default-sente-router? true
:auth-fn view-auth-fn
:on-unauth-fn view-on-unauth-fn}))
(defn shutdown! (defn shutdown!
[] []

View file

@ -24,7 +24,9 @@
where c.id = ?" id]) where c.id = ?" id])
(defn full-card-info (defn full-card-info
[id] [id list-id user-id]
(let [list-id (int list-id)
public-only? (nil? user-id)]
["select c.id, ["select c.id,
c.set_code, c.set_code,
c.layout, c.layout,
@ -66,11 +68,15 @@
s.online_only, s.online_only,
c.paper_price, c.paper_price,
c.online_price, c.online_price,
c.owned_count, lc.quantity,
c.owned_foil_count lc.foil_quantity
from cards c from cards c
join sets s on c.set_code = s.code join sets s on c.set_code = s.code
where c.id = ?" id]) join lists l on l.id = ?
left join lists_card_quantities lc on (lc.card_id = c.id and lc.list_id = l.id)
where c.id = ?
and l.is_public in (true, ?)"
list-id id public-only?]))
(defn card-names (defn card-names
[id] [id]
@ -164,20 +170,24 @@
:number (text-comparison-fn [:number] true) :number (text-comparison-fn [:number] true)
:power (text-comparison-fn [:power] true) :power (text-comparison-fn [:power] true)
:toughness (text-comparison-fn [:toughness] true) :toughness (text-comparison-fn [:toughness] true)
:owned-count (numeric-comparison-fn [:owned_count]) :owned-count (numeric-comparison-fn [:quantity])
:owned-foil-count (numeric-comparison-fn [:owned_foil_count]) :owned-foil-count (numeric-comparison-fn [:foil_quantity])
:paper-price (numeric-comparison-fn [:paper_price]) :paper-price (numeric-comparison-fn [:paper_price])
:online-price (numeric-comparison-fn [:online_price]) :online-price (numeric-comparison-fn [:online_price])
:owned? (fn [value comparison] :owned? (fn [value comparison]
(assert (= := comparison)) (assert (= := comparison))
(case value (case value
true [:> :owned_count 0] true [:> :quantity 0]
false [:= :owned_count 0])) false [:or
[:is :quantity nil]
[:= :quantity 0]]))
:owned-foil? (fn [value comparison] :owned-foil? (fn [value comparison]
(assert (= := comparison)) (assert (= := comparison))
(case value (case value
true [:> :owned_foil_count 0] true [:> :foil_quantity 0]
false [:= :owned_foil_count 0]))}) false [:or
[:is :foil_quantity nil]
[:= :foil_quantity 0]]))})
(defn- filter->hsql-where-criteria (defn- filter->hsql-where-criteria
[{:keys [field value comparison]}] [{:keys [field value comparison]}]
@ -185,7 +195,7 @@
(f value comparison))) (f value comparison)))
(defn- base-card-search-query (defn- base-card-search-query
[hsql-filters & [order-by]] [list-id public-only? hsql-filters & [order-by]]
(let [q {:from [[(merge (let [q {:from [[(merge
{:select [:c.id {:select [:c.id
:c.name :c.name
@ -207,10 +217,16 @@
:c.loyalty :c.loyalty
:c.paper_price :c.paper_price
:c.online_price :c.online_price
:c.owned_count :lc.quantity
:c.owned_foil_count] :lc.foil_quantity]
:from [[:cards :c]] :from [[:cards :c]]
:join [[:sets :s] [:= :c.set_code :s.code]]} :join [[:sets :s] [:= :c.set_code :s.code]
[:lists :l] [:and
[:= :l.id list-id]
[:in :l.is_public [true public-only?]]]]
:left-join [[:lists_card_quantities :lc] [:and
[:= :c.id :lc.card_id]
[:= :lc.list_id list-id]]]}
(if order-by (if order-by
{:order-by [order-by [:c.id]]})) {:order-by [order-by [:c.id]]}))
:cards_list]]}] :cards_list]]}]
@ -219,8 +235,9 @@
q))) q)))
(defn cards (defn cards
[filters & [sort-by ascending? page-num page-size]] [list-id user-id filters & [sort-by ascending? page-num page-size]]
(let [sort-by (case sort-by (let [public-only? (nil? user-id)
sort-by (case sort-by
:name :name :name :name
:set :set_code :set :set_code
:mana-cost :converted_mana_cost :mana-cost :converted_mana_cost
@ -228,10 +245,10 @@
:rarity :rarity :rarity :rarity
:paper-price :paper_price :paper-price :paper_price
:online-price :online_price :online-price :online_price
:inventory :owned_count :inventory :quantity
:name) :name)
sort-dir (if ascending? :asc :desc) sort-dir (if ascending? :asc :desc)
nulls (if (some #{sort-by} #{:converted_mana_cost :paper_price :online_price :owned_count}) nulls (if (some #{sort-by} #{:converted_mana_cost :paper_price :online_price :quantity})
(if-not ascending? :nulls-last :nulls-first)) (if-not ascending? :nulls-last :nulls-first))
page-size (or page-size 25) page-size (or page-size 25)
page-size (if (> page-size 200) 200 page-size) page-size (if (> page-size 200) 200 page-size)
@ -241,6 +258,8 @@
page-num) page-num)
hsql-filters (mapv filter->hsql-where-criteria filters) hsql-filters (mapv filter->hsql-where-criteria filters)
q (base-card-search-query q (base-card-search-query
list-id
public-only?
hsql-filters hsql-filters
(if nulls (if nulls
[sort-by sort-dir nulls] [sort-by sort-dir nulls]
@ -251,10 +270,11 @@
(hsql/format q))) (hsql/format q)))
(defn count-of-cards (defn count-of-cards
[filters] [list-id user-id filters]
(let [hsql-filters (mapv filter->hsql-where-criteria filters) (let [public-only? (nil? user-id)
q (base-card-search-query hsql-filters) hsql-filters (mapv filter->hsql-where-criteria filters)
q (base-card-search-query list-id public-only? hsql-filters)
q (assoc q :select [:%count.*])] q (assoc q :select [:%count.*])]
(hsql/format q))) (hsql/format q)))
#_(cards [{:field :name :value "z" :comparison :like}] :name true 10000 20) #_(cards 0 nil [{:field :name :value "z" :comparison :like}] :name true 10000 20)

View file

@ -4,12 +4,12 @@
[card-id] [card-id]
["select quality, quantity, foil ["select quality, quantity, foil
from collection from collection
where card_id = ?" where card_id = ? AND list_id = 0"
card-id]) card-id])
(defn total-owned-of-card (defn total-owned-of-card
[card-id] [card-id]
["select count(*) ["select count(*)
from collection from collection
where card_id = ?" where card_id = ? AND list_id = 0"
card-id]) card-id])

View file

@ -18,7 +18,7 @@
select count(*) select count(*)
from collection cl from collection cl
join cards c on cl.card_id = c.id join cards c on cl.card_id = c.id
where c.set_code = s.code and cl.quantity > 0 where c.set_code = s.code and cl.quantity > 0 and cl.list_id = 0
) as owned_count ) as owned_count
from sets s from sets s
where s.code = ?" code]) where s.code = ?" code])
@ -47,6 +47,6 @@
select count(*) select count(*)
from collection cl from collection cl
join cards c on cl.card_id = c.id join cards c on cl.card_id = c.id
where c.set_code = s.code and cl.quantity > 0 where c.set_code = s.code and cl.quantity > 0 and cl.list_id = 0
) as owned_count ) as owned_count
from sets s"]) from sets s"])

View file

@ -1,147 +1,272 @@
(ns mtgcoll.views.functions.statistics) (ns mtgcoll.views.functions.statistics)
(defn owned-total (defn owned-total
[online?] [online? list-id user-id]
["select coalesce(sum(quantity), 0) as total (let [online? (boolean online?)
from collection list-id (int list-id)
where online = ?" public-only? (nil? user-id)]
(boolean online?)]) ["select coalesce(sum(cl.quantity), 0) as total
from collection cl
join lists l on cl.list_id = l.id
where cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))"
online? list-id public-only?]))
(defn distinct-owned-total (defn distinct-owned-total
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select count(distinct c.id) ["select count(distinct c.id)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ?" join lists l on cl.list_id = l.id
(boolean online?)]) where cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))"
online? list-id public-only?]))
(defn owned-foil-total (defn owned-foil-total
[online?] [online? list-id user-id]
["select coalesce(sum(quantity), 0) as total (let [online? (boolean online?)
from collection list-id (int list-id)
where online = ? and foil = true" public-only? (nil? user-id)]
(boolean online?)]) ["select coalesce(sum(cl.quantity), 0) as total
from collection cl
join lists l on cl.list_id = l.id
where cl.online = ?
and cl.foil = true
and cl.list_id = ?
and (l.is_public in (true, ?))"
online? list-id public-only?]))
(defn color-totals (defn color-totals
[online?] [online? list-id user-id]
(let [online? (boolean online?)] ;; TODO: i really dislike how this query is written ... try to clean this up at some point maybe?
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select ["select
( (
select sum(cl.quantity) select sum(cl.quantity)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.color_identity like '%B%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.color_identity like '%B%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as black, ) as black,
( (
select sum(cl.quantity) select sum(cl.quantity)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.color_identity like '%U%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.color_identity like '%U%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as blue, ) as blue,
( (
select sum(cl.quantity) select sum(cl.quantity)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.color_identity like '%G%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.color_identity like '%G%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as green, ) as green,
( (
select sum(cl.quantity) select sum(cl.quantity)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.color_identity like '%R%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.color_identity like '%R%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as red, ) as red,
( (
select sum(cl.quantity) select sum(cl.quantity)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.color_identity like '%W%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.color_identity like '%W%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as white, ) as white,
( (
select sum(cl.quantity) select sum(cl.quantity)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.color_identity = '' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.color_identity = ''
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as colorless" ) as colorless"
online? online? online? online? online? online?])) online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?]))
(defn basic-type-totals (defn basic-type-totals
[online?] [online? list-id user-id]
(let [online? (boolean online?)] ;; TODO: i really dislike how this query is written ... try to clean this up at some point maybe?
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select ["select
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Artifact%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Artifact%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as artifacts, ) as artifacts,
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Creature%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Creature%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as creatures, ) as creatures,
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Enchantment%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Enchantment%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as enchantments, ) as enchantments,
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Instant%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Instant%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as instants, ) as instants,
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Land%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Land%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as lands, ) as lands,
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Planeswalker%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Planeswalker%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as planeswalkers, ) as planeswalkers,
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Tribal%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Tribal%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as tribals, ) as tribals,
( (
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where c.types like '%Sorcery%' and cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where c.types like '%Sorcery%'
and cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as sorcerys" ) as sorcerys"
online? online? online? online? online? online? online? online?])) online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?
online? list-id public-only?]))
(defn most-common-types (defn most-common-types
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select * ["select *
from ( from (
select sum(cl.quantity) as quantity, c.types select sum(cl.quantity) as quantity, c.types
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
group by c.types group by c.types
) types_totals ) types_totals
order by quantity desc order by quantity desc
limit 10" limit 10"
(boolean online?)]) online? list-id public-only?]))
(defn total-sets-owned-from (defn total-sets-owned-from
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select count(distinct c.set_code) ["select count(distinct c.set_code)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ?" join lists l on cl.list_id = l.id
(boolean online?)]) where cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))"
online? list-id public-only?]))
(defn total-sets-owned-all-from (defn total-sets-owned-all-from
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select count(*) ["select count(*)
from ( from (
select select
@ -154,75 +279,112 @@
select coalesce(sum(cl.quantity), 0) select coalesce(sum(cl.quantity), 0)
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? and c.set_code = s.code join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and c.set_code = s.code
and cl.list_id = ?
and (l.is_public in (true, ?))
) as owned_in_set, ) as owned_in_set,
s.code s.code
from sets s from sets s
) as set_owned_counts ) as set_owned_counts
where set_owned_counts.num_in_set = set_owned_counts.owned_in_set" where set_owned_counts.num_in_set = set_owned_counts.owned_in_set"
(boolean online?)]) online? list-id public-only?]))
(defn most-owned-sets (defn most-owned-sets
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select * ["select *
from ( from (
select sum(cl.quantity) as quantity, c.set_code select sum(cl.quantity) as quantity, c.set_code
from cards c from cards c
join sets s on c.set_code = s.code join sets s on c.set_code = s.code
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
group by c.set_code group by c.set_code
) sets_totals ) sets_totals
order by quantity desc order by quantity desc
limit 10" limit 10"
(boolean online?)]) online? list-id public-only?]))
(defn most-copies-of-card (defn most-copies-of-card
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select quantity, c.id, c.name, c.set_code ["select quantity, c.id, c.name, c.set_code
from ( from (
select sum(cl.quantity) as quantity, c2.id as card_id select sum(cl.quantity) as quantity, c2.id as card_id
from cards c2 from cards c2
join collection cl on c2.id = cl.card_id join collection cl on c2.id = cl.card_id
where cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
group by c2.id group by c2.id
) copies_of_cards ) copies_of_cards
join cards c on c.id = card_id join cards c on c.id = card_id
order by quantity desc order by quantity desc
limit 10" limit 10"
(boolean online?)]) online? list-id public-only?]))
(defn most-nonland-copies-of-card (defn most-nonland-copies-of-card
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select quantity, c.id, c.name, c.set_code ["select quantity, c.id, c.name, c.set_code
from ( from (
select sum(cl.quantity) as quantity, c2.id as card_id select sum(cl.quantity) as quantity, c2.id as card_id
from cards c2 from cards c2
join collection cl on c2.id = cl.card_id join collection cl on c2.id = cl.card_id
where cl.quantity > 0 and cl.online = ? and c2.type not like '%Land%' join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and c2.type not like '%Land%'
and cl.list_id = ?
and (l.is_public in (true, ?))
group by c2.id group by c2.id
) copies_of_cards ) copies_of_cards
join cards c on c.id = card_id join cards c on c.id = card_id
order by quantity desc order by quantity desc
limit 10" limit 10"
(boolean online?)]) online? list-id public-only?]))
(defn total-price (defn total-price
[online? price-source] [online? price-source list-id user-id]
(let [online? (boolean online?)] (let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select cast(coalesce(sum(sub_total), 0) as decimal(10, 2)) as total ["select cast(coalesce(sum(sub_total), 0) as decimal(10, 2)) as total
from ( from (
select (cl.quantity * cp.price) as sub_total select (cl.quantity * cp.price) as sub_total
from cards c from cards c
join card_prices cp on c.id = cp.card_id join card_prices cp on c.id = cp.card_id
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? and cp.online = ? and cp.source = ? join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and cp.online = ?
and cp.source = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
) as sub_totals" ) as sub_totals"
online? online? price-source])) online? online? price-source list-id public-only?]))
(defn agg-price-stats (defn agg-price-stats
[online? price-source] [online? price-source list-id user-id]
(let [online? (boolean online?)] (let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select cast(coalesce(min(cp.price), 0) as decimal(10, 2)) as min_price, ["select cast(coalesce(min(cp.price), 0) as decimal(10, 2)) as min_price,
cast(coalesce(max(cp.price), 0) as decimal(10, 2)) as max_price, cast(coalesce(max(cp.price), 0) as decimal(10, 2)) as max_price,
cast(coalesce(avg(cp.price), 0) as decimal(10, 2)) as avg_price, cast(coalesce(avg(cp.price), 0) as decimal(10, 2)) as avg_price,
@ -230,37 +392,67 @@
from cards c from cards c
join card_prices cp on c.id = cp.card_id join card_prices cp on c.id = cp.card_id
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? and cp.online = ? and cp.source = ?" join lists l on cl.list_id = l.id
online? online? price-source])) where cl.quantity > 0
and cl.online = ?
and cp.online = ?
and cp.source = ?
and cl.list_id = ?
and (l.is_public in (true, ?))"
online? online? price-source list-id public-only?]))
(defn most-valuable-cards (defn most-valuable-cards
[online? price-source] [online? price-source list-id user-id]
(let [online? (boolean online?)] (let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select c.id, c.name, c.set_code, cp.price ["select c.id, c.name, c.set_code, cp.price
from cards c from cards c
join card_prices cp on c.id = cp.card_id join card_prices cp on c.id = cp.card_id
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? and cp.online = ? and cp.source = ? join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and cp.online = ?
and cp.source = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
order by cp.price desc order by cp.price desc
limit 10" limit 10"
online? online? price-source])) online? online? price-source list-id public-only?]))
(defn num-cards-worth-over-1-dollar (defn num-cards-worth-over-1-dollar
[online? price-source] [online? price-source list-id user-id]
(let [online? (boolean online?)] (let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select coalesce(sum(cl.quantity), 0) as count ["select coalesce(sum(cl.quantity), 0) as count
from cards c from cards c
join card_prices cp on c.id = cp.card_id join card_prices cp on c.id = cp.card_id
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? and cp.online = ? and cp.source = ? and cp.price >= 1.0" join lists l on cl.list_id = l.id
online? online? price-source])) where cl.quantity > 0
and cl.online = ?
and cp.online = ?
and cp.source = ?
and cp.price >= 1.0
and cl.list_id = ?
and (l.is_public in (true, ?))"
online? online? price-source list-id public-only?]))
(defn card-rarity-totals (defn card-rarity-totals
[online?] [online? list-id user-id]
(let [online? (boolean online?)
list-id (int list-id)
public-only? (nil? user-id)]
["select coalesce(sum(cl.quantity), 0) as total, c.rarity ["select coalesce(sum(cl.quantity), 0) as total, c.rarity
from cards c from cards c
join collection cl on c.id = cl.card_id join collection cl on c.id = cl.card_id
where cl.quantity > 0 and cl.online = ? join lists l on cl.list_id = l.id
where cl.quantity > 0
and cl.online = ?
and cl.list_id = ?
and (l.is_public in (true, ?))
group by c.rarity group by c.rarity
order by total desc" order by total desc"
(boolean online?)]) online? list-id public-only?]))