;; Starwisp Copyright (C) 2013 Dave Griffiths ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Affero General Public License as ;; published by the Free Software Foundation, either version 3 of the ;; License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU Affero General Public License for more details. ;; ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; strings ;; colours (define trans-col (list 0 0 0 0)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; persistent database (define db "/sdcard/starwisp/local-symbai.db") (db-open db) (setup db "local") (setup db "sync") (setup db "stream") (insert-entity-if-not-exists db "local" "app-settings" "null" 1 (list (ktv "user-id" "varchar" "No name yet..."))) ;;(display (db-all db "local" "app-settings"))(newline) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; user interface abstraction ;;;;;;;;;;;;; i18n ;;;;;;;;;;;;;;;;;;;;;; (define i18n-lang 0) (define i18n-text (list (list 'test-num (list "1.0000000" "1.0000000" "1.0000000")) (list 'title (list "Symbai" "Symbai" "Symbai")) (list 'sync (list "Sync" "Sync" "Sync")) (list 'languages (list "Choose language" "Choose language" "Choose language")) (list 'english (list "English" "English" "English")) (list 'khasi (list "Khasi" "Khasi" "Khasi")) (list 'hindi (list "Hindi" "Hindi" "Hindi")) (list 'user-id (list "User ID" "User ID" "User ID")) (list 'ok (list "Ok" "Ok" "Ok")) (list 'cancel (list "Cancel" "Cancel" "Cancel")) (list 'new-village (list "+" "+" "+")) (list 'villages (list "Villages" "Villages" "Villages")) ;; village screen (list 'name (list "Village name" "Village name" "Village name")) (list 'block (list "Block" "Block" "Block")) (list 'district (list "District" "District" "District")) (list 'car (list "Accessible by car")) (list 'household-list (list "Household list")) (list 'amenities (list "Amenities")) (list 'school (list "School")) (list 'present (list "Present")) (list 'closest-access (list "Closest place of access")) (list 'gps (list "GPS")) (list 'school (list "School")) (list 'hospital (list "Hospital/Health care centre")) (list 'post-office (list "Post Office")) (list 'railway-station (list "Railway station")) (list 'state-bus-service (list "Inter-state bus service")) (list 'district-bus-service (list "Inter-village/district bus service")) (list 'panchayat (list "Village Panchayat Office")) (list 'NGO (list "Presence of NGO's working with them")) (list 'market (list "Market")) )) (define (mtext-lookup id) (alog id) (define (_ l) (cond ((null? l) (string-append (symbol->string id) " not translated")) ((eq? (car (car l)) id) (let ((translations (cadr (car l)))) (if (<= (length translations) i18n-lang) (string-append (symbol->string id) " not translated") (list-ref translations i18n-lang)))) (else (_ (cdr l))))) (_ i18n-text)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (symbol->id id) (when (not (symbol? id)) (msg "symbol->id: [" id "] is not a symbol")) (make-id (symbol->string id))) (define (mbutton id fn) (button (symbol->id id) (mtext-lookup id) 40 (layout 'fill-parent 'wrap-content -1 'centre 5) fn)) (define (mbutton-scale id fn) (button (symbol->id id) (mtext-lookup id) 40 (layout 'fill-parent 'wrap-content 1 'centre 5) fn)) (define (mtoggle-button id fn) (toggle-button (symbol->id id) (mtext-lookup id) 30 (layout 'fill-parent 'wrap-content -1 'centre 0) "fancy" fn)) (define (mtoggle-button-scale id fn) (toggle-button (symbol->id id) (mtext-lookup id) 30 (layout 'fill-parent 'wrap-content 1 'centre 0) "fancy" fn)) (define (mtext id) (text-view (symbol->id id) (mtext-lookup id) 30 (layout 'wrap-content 'wrap-content -1 'centre 0))) (define (mtext-fixed w id) (text-view (symbol->id id) (mtext-lookup id) 30 (layout w 'wrap-content -1 'centre 0))) (define (mtext-scale id) (text-view (symbol->id id) (mtext-lookup id) 30 (layout 'wrap-content 'wrap-content 1 'centre 0))) (define (mtitle id) (text-view (symbol->id id) (mtext-lookup id) 50 (layout 'fill-parent 'wrap-content -1 'centre 0))) (define (medit-text id type fn) (vert (mtext id) (edit-text (symbol->id id) "" 30 type (layout 'fill-parent 'wrap-content -1 'centre 0) fn))) (define (medit-text-scale id type fn) (vert (mtext id) (edit-text (symbol->id id) "" 30 type (layout 'fill-parent 'wrap-content 1 'centre 0) fn))) (define (mspinner id types fn) (horiz (text-view (symbol->id id) (mtext-lookup id) 30 (layout 'wrap-content 'wrap-content -1 'centre 10)) (spinner (make-id (string-append (symbol->string id) "-spinner")) (map mtext-lookup types) fillwrap (lambda (c) (fn c))))) (define (mspinner-other id types fn) (horiz (mspinner id types fn (lambda (c) (fn c))) (vert (mtext 'other) (edit-text (make-id (string-append (symbol->string id) "-edit-text")) "" 30 "normal" fillwrap (lambda (t) (fn t)))))) (define (mclear-toggles id-list) (map (lambda (id) (update-widget 'toggle-button (get-id id) 'checked 0)) id-list)) (define (mclear-toggles-not-me me id-list) (foldl (lambda (id r) (if (equal? me id) r (cons (update-widget 'toggle-button (get-id id) 'checked 0) r))) '() id-list)) ;;;; (define (db-mongooses-by-pack) (db-all-where db "sync" "mongoose" (ktv "pack-id" "varchar" (ktv-get (get-current 'pack '()) "unique_id")))) (define (db-mongooses-by-pack-male) (db-all-where2or db "sync" "mongoose" (ktv "pack-id" "varchar" (ktv-get (get-current 'pack '()) "unique_id")) (ktv "gender" "varchar" "Male") "Unknown")) (define (db-mongooses-by-pack-female) (db-all-where2or db "sync" "mongoose" (ktv "pack-id" "varchar" (ktv-get (get-current 'pack '()) "unique_id")) (ktv "gender" "varchar" "Female") "Unknown")) ;; (y m d h m s) (define (date-minus-months d ms) (let ((year (list-ref d 0)) (month (- (list-ref d 1) 1))) (let ((new-month (- month ms))) (list (if (< new-month 0) (- year 1) year) (+ (if (< new-month 0) (+ new-month 12) new-month) 1) (list-ref d 2) (list-ref d 3) (list-ref d 4) (list-ref d 5))))) (define (db-mongooses-by-pack-pups) (db-all-newer db "sync" "mongoose" (ktv "pack-id" "varchar" (ktv-get (get-current 'pack '()) "unique_id")) (ktv "dob" "varchar" (date->string (date-minus-months (date-time) 6))))) (define (db-mongooses-by-pack-adults) (db-all-older db "sync" "mongoose" (ktv "pack-id" "varchar" (ktv-get (get-current 'pack '()) "unique_id")) (ktv "dob" "varchar" (date->string (date-minus-months (date-time) 6))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; (define (debug! txt) (set-current! 'debug-text (string-append txt "\n" (get-current 'debug-text "")))) (define (update-debug) (update-widget 'debug-text-view (get-id "sync-debug") 'text (get-current 'debug-text ""))) (define (debug-timer-cb) (append (cond ((get-current 'sync-on #f) (set-current! 'upload 0) (set-current! 'download 0) (connect-to-net (lambda () (append (list (toast "sync-cb")) (upload-dirty db) (suck-new db "sync"))))) (else '())) (list (delayed "debug-timer" (+ 5000 (random 5000)) debug-timer-cb) (update-debug)))) (define pf-length 20) ;; minutes... (define (timer-cb) (set-current! 'timer-seconds (- (get-current 'timer-seconds 59) 1)) (append (cond ((< (get-current 'timer-seconds 59) 0) (set-current! 'timer-minutes (- (get-current 'timer-minutes pf-length) 1)) (set-current! 'timer-seconds 59) (cond ((< (get-current 'timer-minutes pf-length) 1) (list (alert-dialog "pup-focal-end" "Pup focal time is up, have you finished?" (lambda (v) (cond ((eqv? v 1) (list (finish-activity 1))) (else (set-current! 'timer-minutes 1) (list))))))) (else (list (replace-fragment (get-id "pf-top") "pf-scan1"))))) (else '())) (list (delayed "timer" 1000 timer-cb) (update-widget 'text-view (get-id "pf-timer-time-minutes") 'text (string-append (number->string (get-current 'timer-minutes pf-length)))) (update-widget 'text-view (get-id "pf-timer-time") 'text (string-append (number->string (get-current 'timer-seconds 59)))) ))) (define (force-pause) (list (delayed "timer" 1000 (lambda () '())) (update-widget 'toggle-button (get-id "pf-pause") 'checked 1))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; fragments (define-fragment-list (fragment "top" (horiz (image-view 0 "face" (layout 48 64 -1 'centre 0)) (text-view (make-id "title") "Insert title here" 30 (layout 'fill-parent 'fill-parent 0.25 'centre 10)) (linear-layout 0 'vertical (layout 'fill-parent 'wrap-content 0.75 'centre 0) (list 0 0 0 0) (list (text-view (make-id "") 'name 20 (layout 'fill-parent 'wrap-content 1 'centre 0)) (text-view (make-id "") 'photoid 20 (layout 'fill-parent 'wrap-content 1 'centre 0))))) (lambda (fragment arg) (activity-layout fragment)) (lambda (fragment arg) (list)) (lambda (fragment) '()) (lambda (fragment) '()) (lambda (fragment) '()) (lambda (fragment) '())) (fragment "bottom" (linear-layout 0 'horizontal (layout 'fill-parent 'fill-parent 1 'centre 0) (list 0 0 0 0) (list (mbutton-scale 'cancel (lambda () (list))) (mbutton-scale 'ok (lambda () (list))))) (lambda (fragment arg) (activity-layout fragment)) (lambda (fragment arg) (list)) (lambda (fragment) '()) (lambda (fragment) '()) (lambda (fragment) '()) (lambda (fragment) '())) ) (msg "one") (define (build-activity . contents) (vert-fill (relative '(("parent-top")) (list 100 100 255 127) (build-fragment "top" (make-id "top") fillwrap)) (scroll-view-vert 0 (layout 'fill-parent 'fill-parent 1 'centre 0) (list (apply vert-fill contents))) (relative '(("parent-bottom")) (list 100 100 255 127) (vert (spacer 5) (build-fragment "bottom" (make-id "bottom") fillwrap))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; activities (define-activity-list (activity "main" (vert-fill (relative '(("parent-top")) (list 100 100 255 127) (build-fragment "top" (make-id "top") fillwrap)) (scroll-view-vert 0 (layout 'fill-parent 'fill-parent 1 'centre 0) (list (vert-fill (mtitle 'title) (horiz (medit-text 'user-id "normal" (lambda () (list))) (mbutton-scale 'sync (lambda () (list)))) (mspinner 'languages (list 'english 'khasi 'hindi) (lambda (c) (list))) (horiz (mtext 'villages) (mbutton 'new-village (lambda () (list (start-activity "village" 0 "")))))))) ;; village list here (relative '(("parent-bottom")) (list 100 100 255 127) (vert (spacer 5) (build-fragment "bottom" (make-id "bottom") fillwrap))) ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) (list)) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "village" (let ((place-widgets (lambda (id shade) (horiz-colour (if shade (list 0 0 255 100) (list 127 127 255 100)) (mtoggle-button-scale id (lambda (v) '())) (medit-text-scale 'closest-access "normal" (lambda (v) '())) (vert (mbutton-scale 'gps (lambda () '())) (mtext 'test-num) (mtext 'test-num)))))) (build-activity (horiz (medit-text 'name "normal" (lambda () '())) (medit-text 'block "normal" (lambda () '()))) (horiz (medit-text 'district "normal" (lambda () '())) (mtoggle-button-scale 'car (lambda () '()))) (mbutton 'household-list (lambda () '())) (mtitle 'amenities) (place-widgets 'school #t) (place-widgets 'hospital #f) (place-widgets 'post-office #t) (place-widgets 'railway-station #f) (place-widgets 'state-bus-service #t) (place-widgets 'district-bus-service #f) (place-widgets 'panchayat #t) (place-widgets 'NGO #f) (place-widgets 'market #t))) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) (let ((user-id (ktv-get (get-entity db "local" 1) "user-id"))) (set-current! 'user-id user-id) (list))) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "household-list" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "household" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "individual" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "details" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "family" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "migration" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "income" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "geneaology" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "social" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "agreement" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "individual-chooser" (build-activity ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) (activity "sync" (vert ) (lambda (activity arg) (activity-layout activity)) (lambda (activity arg) (set-current! 'sync-on #f) (append (debug-timer-cb) (list (update-widget 'debug-text-view (get-id "sync-debug") 'text (get-current 'debug-text "")) (update-widget 'text-view (get-id "sync-dirty") 'text (build-dirty)) ))) (lambda (activity) '()) (lambda (activity) (list (delayed "debug-timer" 1000 (lambda () '())))) (lambda (activity) (list (delayed "debug-timer" 1000 (lambda () '())))) (lambda (activity) '()) (lambda (activity requestcode resultcode) '())) )