1 (uiop:define-package
#:lw2.elicit-predictions
2 (:use
#:cl
#:iterate
#:lw2.utils
#:lw2.html-reader
#:lw2.backend
#:lw2.graphql
))
4 (in-package #:lw2.elicit-predictions
)
6 (named-readtables:in-readtable html-reader
)
8 (declaim (inline normal-pdf
))
9 (defun normal-pdf (x u o
)
10 (* (/ 1 (sqrt (* 2 pi o
))) (exp (/ (- (expt (- x u
) 2)) (* 2 o
)))))
12 (defun render-elicit-block (question-id)
14 (lw2-graphql-query (graphql-query-string "ElicitBlockData" (alist :question-id question-id
) '(:title
:notes
:resolves-by
:resolution
(:predictions
:prediction
(:creator
(:lw-user
:display-name
)))))
15 :decoder
(lambda (x) (cdadr (assoc :data
(lw2.backend
::deserialize-query-result x
)))))))
16 (alist-bind (title notes resolves-by resolution predictions
) elicit-data
17 <figure class
="prediction-poll">
18 <svg xmlns
="http://www.w3.org/2000/svg" version
="1.1" viewbox
="0 0 700 115">
21 (prediction-count (length predictions
))
22 (bandwidth-scale (/ (float (* 3 width
)) (sqrt prediction-count
)))
23 (histogram (make-array 99 :element-type
'fixnum
:initial-element
0))
24 (density (make-array (1+ (* 98 (/ width
100))) :element-type
'single-float
:initial-element
0f0
))
27 (with-html-stream-output (:stream stream
)
28 (iter (for prediction-data in predictions
)
29 (alist-bind (prediction) prediction-data
30 (when (and prediction
(< 0 prediction
100))
31 (let ((n (incf (aref histogram
(1- prediction
)))))
32 (when (> n max-bin
) (setf max-bin n
))))))
33 (let* ((hist-scale (/ (float height
) (1+ max-bin
))))
34 (iter (for bin from
1 to
99)
35 (let ((hval (aref histogram
(1- bin
))))
37 (format stream
"<rect x=~D y=~5F width=4 height=~5F fill='currentColor' opacity='0.2' />"
38 (- (* (/ width
100) bin
) 2)
39 (- height
(* hist-scale hval
))
40 (* hist-scale hval
)))))
41 (write-string "<path fill='none' stroke='currentColor' stroke-width='0.6667px' d='M " stream
)
42 (iter (for x from
(/ width
100) to
(* 99 (/ width
100)))
44 (iter (for prediction-data in predictions
)
45 (alist-bind (prediction) prediction-data
46 (sum (coerce (normal-pdf (float x
) (* prediction
(float (/ width
100))) bandwidth-scale
) 'single-float
))))))
47 (setf (aref density
(- x
(/ width
100))) y
)
48 (when (> y max-density
) (setf max-density y
))))
49 (let ((height-scale (/ (1- height
) (max (* (1+ max-bin
) (normal-pdf 0f0
0f0 bandwidth-scale
))
51 (iter (for x from
(/ width
100) to
(* 99 (/ width
100)))
52 (let ((y (aref density
(- x
(/ width
100)))))
53 (format stream
"~D,~5F " x
(- height
(* y height-scale
))))))
54 (write-string "' />" stream
)
55 (iter (for x from
1 to
9)
56 (format stream
"<text x=~5F y=~D font-size='12px' fill='currentColor'>~D%</text>" (* x
(/ width
10)) (+ height
14) (* x
10))))))
58 (when (nonempty-string title
) <figcaption
>(progn title
)</figcaption
>)