proc ui {} { canvas .c -width 120 -height 100 -bg grey -borderwidth 2 -relief sunken bind .c <1> {response \t} set ::g(item) [.c create text 60 50 -font {Courier 64 bold}] radio .r ::g(mode) {mouse space 0-9 0-9a-z} button .start -text Start -command challenge button .clear -text C -command reset label .l -textvar g(result) -width 32 grid .c .r - -sticky news grid ^ .start .clear -sticky news grid .l - - -sticky news bind . <Key> {response %A} reset } proc radio {w varName values} { frame $w set i 0 foreach val $values { radiobutton $w.[incr i] -text $val -variable $varName -value $val } set $varName [lindex $values 0] eval pack [winfo children $w] -side top -anchor w -pady 0 } proc challenge {} { global g .start config -text Stop -command stop set g(expected) [switch -- $g(mode) { 0-9 {lpick {0 1 2 3 4 5 6 7 8 9}} 0-9a-z {lpick {0 2 3 4 5 6 7 8 9 a b c d e f g h i j k m n o p q r s t u v w x y z}} space {subst " "} mouse {subst \t} }] incr g(nTries) after [expr {round(500 + rand() * 1000)}] { .c config -bg green .c itemconfig $g(item) -text $g(expected) set g(t0) [clock clicks -millisec] } } proc stop {} { foreach event [after info] {after cancel $event} .start config -text Start -command challenge .c config -bg grey .c itemconfig $::g(item) -text "" } proc response char { global g set dt [expr {[clock clicks -millisec] - $g(t0)}] set g(tLast) $dt if {$char == $g(expected)} { incr g(tSum) $dt if {$dt > $g(tMax)} {set g(tMax) $dt} if {$dt < $g(tMin)} {set g(tMin) $dt} .c config -bg grey .c itemconfig $g(item) -text "" } else { .c config -bg red incr g(nErrors) } set g(expected) "" display after 100 challenge } proc reset {} { array set ::g {nTries 0 nErrors 0 tMin 99999 tMax 0 tSum 0 tLast -} .c itemconfig $::g(item) -text "" display } proc display {} { global g set errorRate [expr {$g(nTries)? $g(nErrors)*100./$g(nTries) : 0}] set g(result) "$g(nTries) tries, $g(nErrors) errors" append g(result) " ([format %.1f $errorRate] %) - last: $g(tLast) ms" set valid [expr {$g(nTries) - $g(nErrors)}] set average [expr {$valid? $g(tSum)/$valid : 0}] append g(result) "\nmin: $g(tMin) max:$g(tMax) avg: $average ms" } proc lpick list {lindex $list [expr {int([llength $list]*rand())}]} #------------------------------------------------------------------ ui bind . <Escape> {exec wish $argv0 &; exit} bind . <F1> {console show}
SS 7Sep2004: Very interesting! but I think it should count it as an error when the user presses the mouse button before the box become green, otherwise to cheat is too easy.RLH For whatever reason, the whole page was clipped. I copied from an older version to get the page back.