174 lines
5.5 KiB
Scheme
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))
|