ywatds/webui/conns.scm

174 lines
5.5 KiB
Scheme

(use-modules (aux v2d) (aux math))
(define (conns-query->qstring qlist)
(let ((f (lambda (elem) (format #f "~d=~d" (car elem) (cdr elem)))))
(format #f "~{~a~^&~}" (map-in-order f qlist))))
(define (conns-handler-get-query qlist)
(let* ((valid-conns-string?
(lambda (str)
(and (string-every char-numeric? str)
(let ((snum (string->number str)))
(and (integer? snum) (< snum 16) (>= snum 0))))))
(query-filter
(lambda (elem)
(and (pair? elem)
(valid-conns-string? (car elem))
(valid-conns-string? (cdr elem)))))
(seen? (make-vector 256 #f))
(query-iter
(lambda (elem)
(and (query-filter elem)
(let* ((from (string->number (car elem)))
(to (string->number (cdr elem)))
(idx (+ (* 16 from) to)))
(and (not (vector-ref seen? idx))
(begin
(vector-set! seen? idx #t)
(cons from to))))))))
(delq! #f (map query-iter qlist))))
(define half-curve-memoization (make-vector 256 #f))
(define (clist->svg query)
(let* ((svg-size 512)
(adjust (lambda (x n) (modulo (+ x n) 16)))
(dir->pos-map
;; note that this vector maps north to -y
#((0 . -1) (1/2 . -1) (1 . -1) (1 . -1/2)
(1 . 0) (1 . 1/2) (1 . 1) (1/2 . 1)
(0 . 1) (-1/2 . 1) (-1 . 1) (-1 . 1/2)
(-1 . 0) (-1 . -1/2) (-1 . -1) (-1/2 . -1)))
(dir->pos (lambda (dir size)
(let ((pos-entry (vector-ref dir->pos-map dir)))
(v2d* (v2d+ pos-entry 1) size 1/2))))
(offset-pos (lambda (pos dir length)
(let ((ent (vector-ref dir->pos-map dir)))
(v2d+ (v2d-extend-to-length ent length) pos))))
(half-curve
(lambda (from to size width)
(let* ((idx (+ (* 16 from) to))
(memoization (vector-ref half-curve-memoization idx)))
(if memoization memoization
(let*
((aux (lambda (dir off)
(v2d-floor (offset-pos (dir->pos dir size)
(adjust dir off)
(/ width 2)))))
(p1 (aux from 4))
(p2 (aux to 12))
(p0 (v2d-floor (v2d+ (v2d*
(vector-ref dir->pos-map from)
width)
p1)))
(p3 (v2d-floor (v2d+ (v2d*
(vector-ref dir->pos-map to)
width)
p2)))
(d1 (v2d- (vector-ref dir->pos-map from)))
(d2 (v2d- (vector-ref dir->pos-map to)))
(c (v2d-intersection p1 p2 d1 d2))
(s (if c
(format
#f "~d~@dL~d~@dQ~d~@d~@d~@dL~d~@d"
(car p0) (cdr p0) (car p1) (cdr p1)
(floor-exact (car c))
(floor-exact (cdr c))
(car p2) (cdr p2) (car p3) (cdr p3))
(format
#f "~d~@dL~d~@dL~d~@dL~d~@d"
(car p0) (cdr p0) (car p1) (cdr p1)
(car p2) (cdr p2) (car p3) (cdr p3)))))
(vector-set! half-curve-memoization idx s)
s)))))
(make-path-entry
(lambda (elem)
(let* ((size svg-size)
(width (/ size 4))
(from (car elem))
(to (cdr elem))
(c1 (half-curve from to size width))
(c2 (half-curve to from size width)))
(if (and c1 c2)
(format #f "M~aL~aZ" c1 c2)
""))))
(path-string (string-concatenate (map make-path-entry query))))
`(,svg-size
,svg-size
(path (@ (d ,path-string)
(stroke "#000")
(stroke-width ,(floor-exact (/ svg-size 32)))
(fill "#be2d2c"))))))
(define (conns-handler-draw-svg original-query)
(let ((query (conns-handler-get-query original-query)))
(respond-svg (clist->svg query))))
(define (conns-handler-draw-preview-page original-query)
(let* ((dirnames
#("N" "NNE" "NE" "ENE" "E" "ESE" "SE" "SSE"
"S" "SSW" "SW" "WSW" "W" "WNW" "NW" "NNW"))
(query (conns-handler-get-query original-query))
(li-aux
(lambda (setter pair value)
(let ((cw (modulo (+ value 1) 16))
(ccw (modulo (+ value 15) 16)))
`((td (a (@ (href "/conns-preview?"
,(begin (setter pair ccw)
(conns-query->qstring query))))
"\u21b6"))
(td ,(format #f "~a" (vector-ref dirnames value)))
(td (a (@ (href "/conns-preview?"
,(begin (setter pair cw)
(conns-query->qstring query))))
"\u21b7"))
,(begin (setter pair value) "")))))
(colsep `(td (@ (style "margin:0;padding:0"))))
(rowsep `(tr (td (@ (style "margin:0;padding:0")
(colspan 9)))))
(li (lambda (elem)
`(tr
(td (a (@ (href "/conns-preview?"
,(conns-query->qstring
(delete elem query))))
"Delete"))
,colsep
,@(li-aux set-car! elem (car elem))
,colsep
,@(li-aux set-cdr! elem (cdr elem))))))
(respond-html
`("Conns preview"
(table (@ (class "standard-table align-center thick-table-borders")
(style "width:min-content"))
(tr (th "Action")
,colsep
(th (@ (colspan 3)) "From")
,colsep
(th (@ (colspan 3)) "To"))
,@(map-in-order li query)
(tr (td (a (@ (href "/conns-preview?"
,(conns-query->qstring
(append query '((0 . 8))))))
"(Add)"))
,colsep
(td (@ (class "unavailable") (colspan 3)) "N")
,colsep
(td (@ (class "unavailable") (colspan 3)) "S"))
,rowsep
(tr (th (@ (colspan 9)) "Preview"))
(tr (td (@ (colspan 9)
(style "margin:0;padding:0"))
(img (@ (src "/conns.svg?"
,(conns-query->qstring query))
(style "width:100%;height:auto;")))))
,rowsep
(tr (th (@ (colspan 9)) "Notes"))
(tr (td (@ (colspan 9)
(style "text-align:initial"))
"Duplicate entries are only shown once.")))))))
(set! dataserver-handlers
(cons* (cons '("conns.svg") conns-handler-draw-svg)
(cons '("conns-preview") conns-handler-draw-preview-page)
dataserver-handlers))