biome-api-query: generating unique keys seems to work

This commit is contained in:
Pavel Korytov 2023-07-07 17:26:50 +03:00
parent 53c6d8aae8
commit 3f1a95cb9c

View file

@ -26,6 +26,7 @@
;;; Code: ;;; Code:
(require 'biome-api-data) (require 'biome-api-data)
(require 'compat)
(require 'transient) (require 'transient)
(defconst biome-query-groups '("daily" "hourly" "minutely_15" "hourly") (defconst biome-query-groups '("daily" "hourly" "minutely_15" "hourly")
@ -36,6 +37,9 @@ Forecast\" report you can choose between \"daily\" and \"hourly\". In
principle, the API can return results for both groups, but they would principle, the API can return results for both groups, but they would
have to be displayed separately.") have to be displayed separately.")
(defconst biome-query--ignore-items '("m" "cm")
"Items to ignore when generating unique keys.")
(defvar biome-query-current nil (defvar biome-query-current nil
"Current report. "Current report.
@ -80,27 +84,81 @@ It is an alist with the following keys:
"Generate unique key candidates for NAME." "Generate unique key candidates for NAME."
(let ((name-low (replace-regexp-in-string (rx (not alnum)) " " (downcase name))) (let ((name-low (replace-regexp-in-string (rx (not alnum)) " " (downcase name)))
(generated-keys (make-hash-table :test 'equal))) (generated-keys (make-hash-table :test 'equal)))
(let* ((items (split-string name-low)) (let* ((items (seq-filter
(lambda (i)
(not (member i biome-query--ignore-items)))
(split-string name-low)))
(sequences (mapcar (lambda (item) (sequences (mapcar (lambda (item)
(if (string-match-p (rx num) item) (if (string-match-p (rx num) item)
(number-sequence 0 (length item) (length item)) (number-sequence 0 (length item) (length item))
(number-sequence 0 (length item) 1))) (number-sequence 0 (length item) 1)))
items))) items)))
(dolist (item-take (reduce #'biome-query--cartesian-product (nreverse sequences))) (dolist (item-take (thread-last
(reverse sequences)
(reduce #'biome-query--cartesian-product)
(mapcar (lambda (it) (if (listp it) (nreverse it) (list it))))
(seq-sort-by
(lambda (it)
(cl-loop for take in it
for seq in sequences
if (= 2 (length seq)) sum 1
else sum take))
#'<)))
(let ((val (cl-loop for i from 0 (let ((val (cl-loop for i from 0
for item in items for item in items
for take = (nth (- (1- (length items)) i) item-take) for take = (nth i item-take)
concat (seq-take item take)))) concat (seq-take item take))))
(unless (or (gethash val generated-keys) (unless (or (gethash val generated-keys)
(string-empty-p val)) (string-empty-p val)
(string-match-p (rx bos (+ num) eos) val))
(puthash val t generated-keys) (puthash val t generated-keys)
(iter-yield val))))))) (iter-yield val)))))))
(defun biome-query--unique-keys (name keys) ;; (setq my/test (biome-query--unique-key-cands "Tempe 200"))
"Get a unique key for NAME. ;; (iter-next my/test)
NAME is a field name. KEYS is a hash-map of used key names." (defun biome-query--unique-keys (names)
(seq-some )) "Get unique keys for NAMES.
NAMES is a list of strings."
(let ((keys-by-name (make-hash-table :test 'equal))
(names-by-key (make-hash-table :test 'equal))
(iters (make-hash-table :test 'equal)))
(cl-loop for name in names
do (puthash name (biome-query--unique-key-cands name) iters))
(while-let ((names-to-update
(append
;; Unset keys
(cl-loop for name in names
if (null (gethash name keys-by-name))
collect name)
;; Duplicate keys
(cl-loop for key being the hash-key of names-by-key
using (hash-values names)
if (< 1 (length names))
collect (car (seq-sort-by #'length #'> names)))
;; Duplicate subkeys
(cl-loop for key being the hash-key of names-by-key
append (cl-loop
for i from 1 to (1- (length key))
for subkey = (seq-take key i)
for dupe-names = (gethash subkey names-by-key)
when dupe-names append dupe-names)))))
(cl-loop
for name in names-to-update
for old-key = (gethash name keys-by-name)
for key = (iter-next (gethash name iters))
if old-key do (puthash old-key (remove name (gethash old-key names-by-key)) names-by-key)
do (puthash key (cons name (gethash key names-by-key)) names-by-key)
do (puthash name key keys-by-name)))
keys-by-name))
(setq my/test (mapcar (lambda (l) (alist-get :name l))
(car (alist-get :fields (nth 1 (alist-get :sections (cdar biome-api-data)))))))
(setq my/test2
(cl-loop for key being the hash-key of (biome-query--unique-keys my/test)
using (hash-values name)
collect (cons key name)))
(defun biome-query--section-children (section) (defun biome-query--section-children (section)
(let ((sections (alist-get :sections section)) (let ((sections (alist-get :sections section))