Now also generating graph of number of donors.

This commit is contained in:
Simon Brooke 2026-09-27 16:36:37 +01:00
parent 68b714640a
commit b396015e34
2 changed files with 37 additions and 16 deletions

View file

@ -26,7 +26,7 @@ be supplied as `java.time.LocalDate` objects, or as strings in the format
`yyyy-mm-dd`. If `end-date` is not supplied, data for a single week will be `yyyy-mm-dd`. If `end-date` is not supplied, data for a single week will be
returned. returned.
### `chart-total-donations-by-weeks` ### `(chart-total-donations-by-weeks start-date end-date)`
Create and return an XY chart of data on total donations made between Create and return an XY chart of data on total donations made between
`start-date` and `end-date`. Arguments may be supplied as `start-date` and `end-date`. Arguments may be supplied as

View file

@ -1,5 +1,6 @@
(ns gaza-stats.core (ns gaza-stats.core
(:require [cljc.java-time.local-date :as ld] (:require [clojure.string :refer [capitalize]]
[cljc.java-time.local-date :as ld]
[com.hypirion.clj-xchart :refer [xy-chart]] [com.hypirion.clj-xchart :refer [xy-chart]]
[korma.core :refer [fields join select where]] [korma.core :refer [fields join select where]]
[korma.db :refer [defdb sqlite3]])) [korma.db :refer [defdb sqlite3]]))
@ -32,26 +33,46 @@
(loop [s sd (loop [s sd
i (ld/plus-days sd 7) i (ld/plus-days sd 7)
r nil] r nil]
(let [r' (cons (let [data (select 'campaign_donations
[s (reduce + (fields :amount)
(map :amount (where (and {:created_at [> s]}
(select 'campaign_donations {:created_at [<= i]})))
(fields :amount) amounts (map :amount data)
(where (and {:created_at [> s]} r' (cons
{:created_at [<= i]})))))] [s {:total (reduce + amounts)
:n (count data)
:max (apply max amounts)
:min (apply min amounts)}]
r)] r)]
(if (ld/is-before ed i) (reverse r') (if (ld/is-before ed i) (reverse r')
(recur i (ld/plus-days i 7) r'))))))) (recur i (ld/plus-days i 7) r')))))))
(defmacro datetime->date [x]
`(java.util.Date/from
(.toInstant (.atStartOfDay ~x)
(java.time.ZoneOffset/ofHours 0))))
(defn chart-donations-by-weeks
"Create and return an XY chart of data on field represented by `key` of
donations made between `start-date` and `end-date`. Arguments may be supplied as
`java.time.LocalDate` objects, or as strings in the format `yyyy-mm-dd`."
[start-date end-date key]
(let [data (total-donations-by-weeks start-date end-date)]
(xy-chart {(format "%s Donations" (capitalize (name key)))
[(map #(datetime->date (first %)) data)
(map #(:n (nth % 1)) data)]})))
(defn chart-total-donations-by-weeks (defn chart-total-donations-by-weeks
"Create and return an XY chart of data on total donations made between "Create and return an XY chart of data on total donations made between
`start-date` and `end-date`. Arguments may be supplied as `start-date` and `end-date`. Arguments may be supplied as
`java.time.LocalDate` objects, or as strings in the format `yyyy-mm-dd`." `java.time.LocalDate` objects, or as strings in the format `yyyy-mm-dd`."
[start-date end-date] [start-date end-date]
(let [data (total-donations-by-weeks start-date end-date)] (chart-donations-by-weeks start-date end-date :total))
(xy-chart {"Donations"
[(map #(java.util.Date/from (defn chart-number-donations-by-weeks
(.toInstant (.atStartOfDay (first %)) "Create and return an XY chart of data on number of donations made between
(java.time.ZoneOffset/ofHours 0))) `start-date` and `end-date`. Arguments may be supplied as
data) `java.time.LocalDate` objects, or as strings in the format `yyyy-mm-dd`."
(map #(nth % 1) data)]}))) [start-date end-date]
(chart-donations-by-weeks start-date end-date :n))