mirror of
https://github.com/SqrtMinusOne/biome.git
synced 2025-12-10 14:35:13 +03:00
biome: add biome-multi-history
This commit is contained in:
parent
b264e51e66
commit
b9a8657a14
4 changed files with 145 additions and 13 deletions
|
|
@ -40,6 +40,8 @@
|
|||
("BOM (Australia)" . "https://api.open-meteo.com/v1/bom")
|
||||
("CMA (China)" . "https://api.open-meteo.com/v1/cma")
|
||||
("Historical Weather" . "https://archive-api.open-meteo.com/v1/archive")
|
||||
("Historical Weather (on this day)"
|
||||
. "https://archive-api.open-meteo.com/v1/archive")
|
||||
("Ensemble Models" . "https://ensemble-api.open-meteo.com/v1/ensemble")
|
||||
("Previous Runs API" . "https://previous-runs-api.open-meteo.com/v1/forecast")
|
||||
("Climate Change" . "https://climate-api.open-meteo.com/v1/climate")
|
||||
|
|
|
|||
104
biome-multi.el
104
biome-multi.el
|
|
@ -29,6 +29,7 @@
|
|||
(require 'transient)
|
||||
|
||||
(require 'biome-query)
|
||||
(require 'biome-api-parse)
|
||||
|
||||
;; XXX Recursive imports T_T
|
||||
(declare-function biome-preset "biome")
|
||||
|
|
@ -287,5 +288,108 @@ as it is necessary for `biome-grid'."
|
|||
unit)))))
|
||||
(multi . ,(biome-multi--join-results queries query-names vars-mapping results))))))
|
||||
|
||||
(defun biome-multi--history-section ()
|
||||
"Create a section for `biome-multi-history'.
|
||||
|
||||
This is based on the Historical Weather section."
|
||||
(let* ((history-params
|
||||
(copy-tree (alist-get "Historical Weather" biome-api-data
|
||||
nil nil #'equal)))
|
||||
(time-section (biome-api-parse--postprocess-extract-section
|
||||
(alist-get :sections history-params)
|
||||
"coordinates and time"))
|
||||
(current-year (decoded-time-year (decode-time))))
|
||||
(push '("day_of_year" . ((:name . "Day of Year")
|
||||
(:type . date)))
|
||||
(alist-get :fields time-section))
|
||||
(push
|
||||
`("end_year" . ((:name . "End year")
|
||||
(:type . number)
|
||||
(:min . 1940)
|
||||
(:max . ,current-year)))
|
||||
(alist-get :fields time-section))
|
||||
(push
|
||||
`("start_year" . ((:name . "Start year")
|
||||
(:type . number)
|
||||
(:min . 1940)
|
||||
(:max . ,current-year)))
|
||||
(alist-get :fields time-section))
|
||||
(setf (alist-get :name history-params)
|
||||
"Historical Weather (on this day)")
|
||||
(setf (alist-get :fields time-section)
|
||||
(seq-filter
|
||||
(lambda (elem)
|
||||
(not (member (car elem) '("start_date" "end_date"))))
|
||||
(alist-get :fields time-section)))
|
||||
history-params))
|
||||
|
||||
(defun biome-multi-history--prepare-queries (query)
|
||||
"Create queries for `biome-multi-history'.
|
||||
|
||||
QUERY is a query as defined by `biome-query-current', prepared like
|
||||
for the normal Historical Weather section but with the following
|
||||
added fields:
|
||||
- start_year (number from 1940 to current)
|
||||
- end_year (number from 1940 to current)
|
||||
- day_of_year (timestamp)."
|
||||
(let ((start-year (alist-get "start_year"
|
||||
(alist-get :params query)
|
||||
nil nil #'equal))
|
||||
(end-year (alist-get "end_year"
|
||||
(alist-get :params query)
|
||||
nil nil #'equal))
|
||||
(day-of-year (alist-get "day_of_year"
|
||||
(alist-get :params query)
|
||||
nil nil #'equal)))
|
||||
(unless (and start-year end-year day-of-year)
|
||||
(user-error "Set Start Year, End Year and Day of Year"))
|
||||
(cl-loop with current-date = (decode-time (seconds-to-time day-of-year))
|
||||
for year from start-year to end-year
|
||||
for date = (copy-tree current-date)
|
||||
do (setf (decoded-time-year date) year)
|
||||
for time = (time-convert (encode-time date) 'integer)
|
||||
for year-query = (copy-tree query)
|
||||
do (setf (alist-get :params year-query)
|
||||
(seq-filter (lambda (elem)
|
||||
(not
|
||||
(member
|
||||
(car elem)
|
||||
'("day_of_year" "end_year" "start_year"))))
|
||||
(alist-get :params year-query)))
|
||||
do (push (cons "start_date" (- time (% time (* 60 60 24))))
|
||||
(alist-get :params year-query))
|
||||
do (push (cons "end_date" (- time (% time (* 60 60 24))))
|
||||
(alist-get :params year-query))
|
||||
collect year-query)))
|
||||
|
||||
(defun biome-multi--history-query (callback)
|
||||
"Get historical weather data on a particular day.
|
||||
|
||||
CALLBACK is called with a list of queries, one per day."
|
||||
(interactive (list nil))
|
||||
(let ((params (biome-multi--history-section)))
|
||||
(setq biome-query--callback
|
||||
(lambda (query)
|
||||
(let ((queries (biome-multi-history--prepare-queries query)))
|
||||
(when (y-or-n-p (format "Send %s requests to the API?"
|
||||
(length queries)))
|
||||
(funcall callback queries)))))
|
||||
(biome-query--section-open-params params)))
|
||||
|
||||
(defun biome-multi--concat-results (queries results)
|
||||
"Concat RESULTS from multiple Open Meteo responses.
|
||||
|
||||
QUERIES is a list of forms as defined by `biome-query-current'. Each
|
||||
query is assumed to have the same variables. RESULTS is a list of
|
||||
responses from Open Meteo."
|
||||
(let ((group (intern (alist-get :group (car queries)))))
|
||||
(cl-loop for result in (cdr results)
|
||||
do (cl-loop
|
||||
for (var . values) in (alist-get group result)
|
||||
do (setf (alist-get var (alist-get group (car results)))
|
||||
(vconcat (alist-get var (alist-get group (car results)))
|
||||
values))))
|
||||
(car results)))
|
||||
|
||||
(provide 'biome-multi)
|
||||
;;; biome-multi.el ends here
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@
|
|||
|
||||
;; XXX Recursive imports T_T
|
||||
(declare-function biome-preset "biome")
|
||||
(declare-function biome-multi "biome")
|
||||
(declare-function biome-multi "biome-multi")
|
||||
(declare-function biome-multi-history "biome-multi")
|
||||
|
||||
(defcustom biome-query-max-fields-in-row 20
|
||||
"Maximum number of fields in a row."
|
||||
|
|
@ -209,7 +210,7 @@ QUERY is a form as defined by `transient-define-prefix'."
|
|||
(setq lat (cdr item)))
|
||||
((equal (car item) "longitude")
|
||||
(setq lon (cdr item)))
|
||||
((member (car item) '("end_date" "start_date"))
|
||||
((member (car item) '("end_date" "start_date" "day_of_year"))
|
||||
(push
|
||||
(format "%s: %s" (propertize
|
||||
(biome-query--get-header (car item) var-names)
|
||||
|
|
@ -1027,18 +1028,27 @@ SECTION is a form as defined in `biome-api-parse--page'."
|
|||
(:parents . ,parents))))
|
||||
(put 'biome-query-section 'transient--layout nil)))
|
||||
|
||||
(defun biome-query--section-open-params (params)
|
||||
"Open section defined by PARAMS in `biome-query--section'.
|
||||
|
||||
PARAMS is a form as defiend by `biome-api-data'."
|
||||
(setq biome-query--current-section params)
|
||||
(when (and biome-query-current
|
||||
(not (equal (alist-get :name params)
|
||||
(alist-get :name biome-query-current))))
|
||||
(setq biome-query-current nil))
|
||||
(unless biome-query-current
|
||||
(biome-query--reset-report))
|
||||
(funcall-interactively #'biome-query--section params))
|
||||
|
||||
(defun biome-query--section-open (name)
|
||||
"Open section NAME in `biome-query--section'."
|
||||
(let ((params (alist-get name biome-api-data nil nil #'equal)))
|
||||
(unless params
|
||||
(error "No such section: %s" name))
|
||||
(setq biome-query--current-section params)
|
||||
(when (and biome-query-current
|
||||
(not (equal name (alist-get :name biome-query-current))))
|
||||
(setq biome-query-current nil))
|
||||
(unless biome-query-current
|
||||
(biome-query--reset-report))
|
||||
(funcall-interactively #'biome-query--section params)))
|
||||
(cond
|
||||
((equal name "Historical Weather (on this day)")
|
||||
(biome-multi-history))
|
||||
(params (biome-query--section-open-params params))
|
||||
(t (error "No such section: %s" name)))))
|
||||
|
||||
(transient-define-prefix biome-query (callback)
|
||||
["Open Meteo Data"
|
||||
|
|
@ -1053,11 +1063,15 @@ SECTION is a form as defined in `biome-api-parse--page'."
|
|||
(lambda () (interactive)
|
||||
(biome-query--section-open ,name))
|
||||
:transient transient--do-stack))))]
|
||||
["Aggregate Data"
|
||||
:class transient-column
|
||||
("i" "Historical Weather (on this day)" biome-multi-history
|
||||
:transient transient--do-stack)
|
||||
("u" "Join multiple queries" biome-multi :transient transient--do-stack)]
|
||||
["Actions"
|
||||
:class transient-row
|
||||
("r" "Resume" biome-resume :transient transient--do-replace)
|
||||
("r" "Resume" biome-resume :transient transient--do-stack)
|
||||
("p" "Preset" biome-preset :transient transient--do-stack)
|
||||
("u" "Join multiple queries" biome-multi :transient transient--do-stack)
|
||||
("q" "Quit" transient-quit-one)]
|
||||
(interactive (list nil))
|
||||
(unless callback
|
||||
|
|
|
|||
12
biome.el
12
biome.el
|
|
@ -106,6 +106,18 @@ preset definition\" in `biome' or `biome-multi'."
|
|||
(let ((merged (biome-multi--merge queries results)))
|
||||
(funcall biome-frontend (nth 0 merged) (nth 1 merged))))))))
|
||||
|
||||
(defun biome-multi-history ()
|
||||
"Get historical weather data on a particular day."
|
||||
(interactive)
|
||||
(funcall-interactively
|
||||
#'biome-multi--history-query
|
||||
(lambda (queries)
|
||||
(biome-api-get-multiple
|
||||
queries
|
||||
(lambda (queries results)
|
||||
(let ((concat-results (biome-multi--concat-results queries results)))
|
||||
(funcall biome-frontend (car queries) concat-results)))))))
|
||||
|
||||
(defmacro biome-def-preset (name params)
|
||||
"Declare a query preset.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue