#!/var/lib/install/usr/bin/guile -s !# (use-modules (gnome-0)) (use-modules (gnome gtk) (gnome hildon)) (define prog (make #:app-title "Counting Agent")) (connect prog 'destroy (lambda (w) (gtk-main-quit))) (define view (make )) (set-appview prog view) (define nb (make )) (add view nb) (define v1 (make )) (append-page nb v1 (make #:label "Summary")) (define-class () (data #:init-value '())) (define-method (on-get-flags (pl )) #f) (define-method (on-get-iter (pl ) path) (let ((data (slot-ref pl 'data)) (i (car path))) (and (< i (length data)) (list-ref data i)))) (define-method (on-get-path (pl ) iter) (list (list-index (slot-ref pl 'data) iter))) (define-method (on-iter-next (pl ) iter) (let ((path (on-get-path pl iter))) (set-car! path (+ (car path) 1)) (on-get-iter pl path))) (define-method (on-iter-children (pl ) parent) (cond (parent #f) ((null? (slot-ref pl 'data)) #f) (else (car (slot-ref pl 'data))))) (define-method (on-iter-has-child (pl ) parent) #f) (define-method (on-iter-n-children (pl ) parent) (and (not parent) (length (slot-ref pl 'data)))) (define-method (on-iter-nth-child (pl ) parent n) (and (not parent) (on-get-iter pl (list n)))) (define-method (on-iter-parent (pl ) child) #f) (define-method (on-get-n-columns (pl )) 2) (define-method (on-get-column-type (pl ) index) (list-ref (list gtype:gchararray gtype:gchararray) index)) (define-method (on-get-value (pl ) iter index) (list-ref iter index)) (define-method (add-party (pl ) name) (let* ((data (slot-ref pl 'data)) (datalen (length data)) (new-entry (list name "0"))) (slot-set! pl 'data (append data (list new-entry))) (row-inserted pl (list datalen) (get-iter pl (list datalen))))) (define pl (make )) (for-each (lambda (p) (add-party pl p)) '("Liberal Democrat" "Labour" "Conservative" "Green" "IWCA" "Independent")) (define tv (make #:model pl #:headers-visible #t)) (let ((cr1 (make )) (cr2 (make )) (tvc1 (make #:title "Party")) (tvc2 (make #:title "Votes"))) (pack-start tvc1 cr1 #t) (add-attribute tvc1 cr1 "text" 0) (append-column tv tvc1) (pack-start tvc2 cr2 #t) (add-attribute tvc2 cr2 "text" 1) (append-column tv tvc2)) (pack-start v1 tv #t) (define h11 (make )) (pack-start h11 (make #:label "New party:") #f) (define pe (make )) (pack-start h11 pe #t) (define pb (make #:label "Add")) (pack-end h11 pb #f) (connect pb 'clicked (lambda (w) (add-party pl (get-text pe)) (set-text pe ""))) (pack-start v1 h11 #f) (define h12 (make )) (pack-start h12 (make #:label "New count:") #f) (define ce (make )) (pack-start h12 ce #t) (define cb (make #:label "Add")) (pack-end h12 cb #f) (connect cb 'clicked (lambda (w) (let ((box-name (get-text ce))) (append-page nb (make-count-page (make-result-store box-name)) (make #:label box-name))) (show-all nb) (set-text ce "") (maybe-save))) (pack-end v1 h12 #f) (define (make-result-store box-name) (set! results (cons (cons* box-name 0 (make-vector (length (slot-ref pl 'data)) 0)) results)) (cdar results)) (define results '()) (define (save-results fn) (with-output-to-file fn (lambda () (for-each (lambda (result) (write result) (newline)) results)))) (define maybe-save (let ((count 0)) (lambda () (set! count (+ count 1)) (if (zero? (remainder count 20)) (save-results "#results#"))))) (connect nb 'switch-page (lambda _ (let loop ((data (slot-ref pl 'data)) (i 0)) (or (null? data) (begin (set-car! (cdar data) (number->string (inexact->exact (floor (apply + (map (lambda (store) (let ((st (sampled-total store))) (if (zero? st) st (/ (* (car store) (vector-ref (cdr store) i)) st)))) (map cdr results))))))) (row-changed pl (list i) (get-iter pl (list i))) (loop (cdr data) (+ i 1))))))) (define (sampled-total store) (apply + (vector->list (cdr store)))) (define (make-count-page store) (let* ((parties (map car (slot-ref pl 'data))) (h (make )) (v1 (make )) (v2 (make )) (svt (make #:label "0")) (ps (make #:label "--"))) (let loop ((parties parties) (i 0)) (or (null? parties) (let ((b (make #:label (car parties)))) (connect b 'clicked (lambda _ (let ((votes (+ (vector-ref (cdr store) i) 1))) (vector-set! (cdr store) i votes) (set-label svt (format #f "~a" (sampled-total store))) (or (zero? (car store)) (set-label ps (format #f "~a%" (quotient (* 100 (sampled-total store)) (car store))))) (maybe-save) (set-label b (format #f "~a: ~a" (car parties) votes))))) (pack-start v1 b #t) (loop (cdr parties) (+ i 1))))) (pack-start h v1 #t) (pack-start v2 (make #:label "Actual votes") #f) (let ((e (make ))) (pack-start v2 e #f) (connect e 'changed (lambda _ (set-car! store (inexact->exact (floor (or (string->number (get-text e)) 0)))) (set-label ps (if (zero? (car store)) "--" (format #f "~a%" (quotient (* 100 (sampled-total store)) (car store)))))))) (pack-start v2 (make #:label "Sampled votes") #f) (pack-start v2 svt #f) (pack-start v2 (make #:label "% sampled") #f) (pack-start v2 ps #f) (pack-end h v2 #f) h)) (show-all prog) (gtk-main)