Cubing and Emacs: Checking out the competition

| cubing, emacs

There's an upcoming cubing competition. For the 3x3 event, the top 75% of the first round will get to advance to the second round. I wanted to know what our chances were of making it in. There's an unofficial REST API for the World Cube Association (WCA) results so I don't need to download and unpack megabytes of data.

Here's the basic code I used:

(let* ((comp-id "COMP-ID-GOES-HERE")
       (url (format "https://www.worldcubeassociation.org/competitions/%s/registrations" comp-id))
       (dom (with-temp-buffer (insert (plz 'get url)) (libxml-parse-html-region)))
       (data-dir (expand-file-name "data" (expand-file-name comp-id "~/proj/cubing/")))
       len
       list)
  (unless (file-directory-p data-dir)
    (make-directory data-dir t))
  (setq list (sort
              (seq-keep
               (lambda (o)
                 (let* ((id (replace-regexp-in-string "/persons/" "" (dom-attr o 'href)))
                        (file (expand-file-name (concat id ".json") data-dir))
                        best)
                   (unless (file-exists-p file)
                     (with-temp-file file
                       (insert
                        (plz 'get (format "https://raw.githubusercontent.com/robiningelbrecht/wca-rest-api/master/api/persons/%s.json" id)))))
                   (let-alist (with-temp-buffer
                                (insert-file-contents file)
                                (json-parse-buffer :object-type 'alist))
                     (setq best
                           (alist-get 'best
                                      (seq-find (lambda (o) (string= (alist-get 'eventId o) "333")) .rank.averages)))
                     (when best
                       (list .id .name (format "%.2f" (/ best 100.0)))))))
               (dom-by-tag (dom-by-id dom "competition-data") 'a))
              (lambda (a b)
                (< (string-to-number (elt a 2)) (string-to-number (elt b 2))))))
  (setq len (length list))
  (seq-map-indexed
   (lambda (o i)
     (cons (format "%d" (/ (* 100.0 i) len))
           o))
   list))

It makes a table with percentile, ID, name, and average time for 3x3. Then I can find out where the 75% mark and see if we can make it in. I think I'll be a bit too slow, but the kiddo might be able to make it to the second round. Could be fun.

Posting here in case someone else might find it handy someday!

You can comment with Disqus or you can e-mail me at sacha@sachachua.com.