Version 22 of FuzzyClock

Updated 2015-03-14 03:00:52 by MiHa

if 0 {

General Notes

MiHa 2015-02-24 - A fuzzy clock shows approximate time only, that is, with a precision of a few minutes.

For example, for any time between 03:08 and 03:12 you would get a string like "Ten minutes past three o'clock",

There are already some programs that do that, examples are:

My fuzzy clock doesn't output a string, it highlights fixed panels with a list of words on them,
like turning on lamps inside panels which have a cover labeled with one of those words.

Some inspiration came from the following programs and pages here :

Other programs that are doing something with time:

Designers notes

  • I use 3*8 rectangles as "panels" on a canvas
  • Each such area has a word (like "ten", "minutes", "before"),
    and tags for adressing.
  • The current time gets read with "clock format clock seconds",
  • this "raw time" gets displayed at the top of the window (for testing),
  • and then I use a table-lookup to figure out which panels to light up.
  • This table has an entry for each minute of the hour, with a list of tags.
  • (When implemening this in hardware, I would instead use 32bit-values,
    where each bit represents one of the panels)
  • The clock is a 12-hour design , but instead of AM/PM, I use morning/evening,
    where "morning" behaves like AM, but "evening" only starts at 18:00.
  • With "It is"/"It gets"/"It was", my time is fuzzy/precise within two minutes,
  • so I limited the update-frequency to once every 10 seconds..
  • My choice of words went towards "five" and "ten",
    which can in german both be lit to be nicely combined to get the equivalent of "fifteen".
    For a proper english fuzzy clock, you might want "quarter" as a separate word.
  • In hindsight, for designing and changing the layout, it is easier
    to have an addressing scheme for the panels like for cells in a spreadsheet.

Notes about working with tcl

  • "catch {console show}" and "puts" is very useful for development and test
  • string/list/dict - not sure when to use what, and no easy guidelines for that
  • Doku/Help - it is hard to find any topic, there are almost no useful examples included.

Example: looking for "create text" - the search shows lots of hits, but the page I want
turns out to be Tk Built-In Commands - canvas manual .
That is far from obvious.
And on that page, the thing I wanted is pathName create type ... ,
where type can be arc, bitmap, line, rect ... and, after scrolling almost all the way down, also text.
That was not the most helpful way to present the information.
In fact, I can hardly imagine the noob that would make it so far.
I think this is a serious obstacle for newcomers.

For a reference-manual this might be ok, but when looking for help to get something done, this is not enough.
Helpful people on IRC are nice to have, but shouldn't be a substitute for good docs.
And examples are also very much missing in that helpfile.

I would expect links to lots of short, self-contained, working snippets of code included in such a helpfile.

  • Bug in clock with "%I" - from help-file for Tcl 8.6.1.0: "%I - On output, produces a two-digit number giving the hour of the day (12-11) on a 12-hour clock." But sometimes I get one-digit numbers.
  • Date and Time Issues - http://wiki.tcl.tk/948

Program


}

 # FuzzyClock43.tcl - Mike Hase - 2015-02-24
 # http://wiki.tcl.tk/41162

  package require Tk

  set Prog(title)   "FuzzyClock"
  set Prog(version) "v0.9"
  set Prog(date)    "2015-03-03"


 ### Colortable: (ToDo)

  set Co(bg)    grey
 #set bg  white
  set bg  grey
  set ol  black

  set hi1 cyan
  set hi2 yellow

  set tx1 blue
  set tx2 white

  set hiC $hi1
  set txC $tx1

 ### Display:

  proc makeText {w tag name rectCoords} {
     set id1 [$w create rect $rectCoords -tag $tag  -fill $::bg  -outline  $::ol]

     foreach {x y} $rectCoords break
     incr x
     incr y
     set id2 [$w create text $x $y -tag t$tag -anchor w  -text $name]
     $w addtag time withtag $tag
     $w addtag txt  withtag t$tag

   # puts "$id1 $id2 : $x $y $tag $name"        ;##
     $w scale $id1 0 0 25 15
     $w scale $id2 0 0 25 15
 }

 proc reset {tag} {
   foreach id [ .c find withtag time] { .c itemconfigure $id -fill $::bg }
   foreach id [ .c find withtag txt ] { .c itemconfigure $id -fill black }
 }
 proc hi {tag} {
   foreach id [ .c find withtag  $tag ] { .c itemconfigure $id -fill $::hiC }
   foreach id [ .c find withtag t$tag ] { .c itemconfigure $id -fill $::txC }
 }

 ### Update display:

  proc upd {} {
    global cs td hh ii mm am tH tM tA mTab

   #wm title . "$td"
    wm title . "$td / $ii:$mm $am"
   #wm title . "$ii:$mm $am"

   set tH "t_$ii"
   set tA "t_$am"
  #puts "$ii / $tH $tA"  ;##

   set tM "$mm"
  #puts "$tM"  ;##

   set i 0
  #puts "$tM : mTab($tM) -->"
   foreach t $mTab($tM) {
    #incr i; puts " $i. $t"; hi $t
     if { $t=="hH" } {         ;# show next hour
       incr ii;
       if { $ii>=13 } { set ii 1 }       ;# max. 12 o'clock
      #puts "++ii: $ii"
    }
   }
   set tH "t_$ii"
  #puts "++ $tH $tA"  ;##

   hi $tH
   foreach t $mTab($mm) {
     #incr i; puts " $i. $t"        ;##
      hi $t
    }
    hi t_C
    hi $tA
  }

  proc u {} {
    reset time
    reset txt
    upd

    if { $::hiC==$::hi1 } { set ::hiC yellow } else { set ::hiC cyan }  ;# change colors
  }

 ### Test+Debug:

  proc x {} {
    set ::mm "10"
  }
  proc y {} {
    set ::ii "12"
    set ::mm "02"
  }
  proc z {} {
    set ::mm "00"
  }
  proc h {} {
    incr ::ii
  }
  proc m {} {
    incr ::mm
  }

  proc e {} {exit}

 ### Time:

  proc now {} {
    global cs  td hh ii mm am  tH tM tA mTab

    set cs [clock seconds]
    set td [clock format $cs  -format "%H:%M:%S - %l:%M %p" ]
    set hh [clock format $cs  -format "%H" ]
    set ii [clock format $cs  -format "%l" ]  ;# %I %k %l
    set mm [clock format $cs  -format "%M" ]
    set am [clock format $cs  -format "%p" ]

    if { $am=="PM" && $hh<"18"} { set am "_" }        ;# no "PM" before 18:00

    incr ii; incr ii -1                  ;# !! workaround !!
    if { $ii>=13 } { set ii 1 }          ;# max. 12 o'clock

    puts "$hh:$mm -> $ii:$mm $am"        ;##

  }

 ### Time/Repeat/Wait:

  proc every {ms body} {
    if 1 $body
    after $ms [list after idle [info level 0]]
  }
  proc run  {} {every 10000 {now; u} }
  proc stop {} {foreach id [after info] {after cancel $id}; }

  proc sync0 {} {
  # wait for seconds to reach a multiple of 10

    update
    for {set i 1} {$i<=30} {incr i} {
      set ::cs [clock seconds]
      set   s0 [expr $::cs % 10]

      puts "$i $::cs $s0"  ;##
      if { $s0 == 0 } { break }
      after 333
    }

  }


 ### Positions, spreadsheet-style:

  set a1  { 1  1  4  3 }
  set b1  { 4  1  7  3 }
  set c1  { 7  1 10  3 }

  set a2  { 1  3  4  5 }
  set b2  { 4  3  7  5 }
  set c2  { 7  3 10  5 }

  set a3  { 1  5  4  7 }
  set b3  { 4  5  7  7 }
  set c3  { 7  5 10  7 }

  set a4  { 1  7  4  9 }
  set b4  { 4  7  7  9 }
  set c4  { 7  7 10  9 }

  set a5  { 1  9  4 11 }
  set b5  { 4  9  7 11 }
  set c5  { 7  9 10 11 }

  set a6  { 1 11  4 13 }
  set b6  { 4 11  7 13 }
  set c6  { 7 11 10 13 }

  set a7  { 1 13  4 15 }
  set b7  { 4 13  7 15 }
  set c7  { 7 13 10 15 }

  set a8  { 1 15  4 17 }
  set b8  { 4 15  7 17 }
  set c8  { 7 15 10 17 }


 ### Fuzzyness starts here:

  proc start01 {w} {
  # setup for german fuzzyclock#1, 8x3 panels: "fünf Minuten vor halb vier Uhr"

    destroy $w;  pack [canvas $w  -width 260  -height 260  -background grey]

    makeText $w t_N  "Es wird" { 1  1  4  3 }
    makeText $w t_I  "Es ist"  { 4  1  7  3 }
    makeText $w t_W  "Es war"  { 7  1 10  3 }

    makeText $w t_v  "fünf"    { 1  3  4  5 }
    makeText $w t_x  "zehn"    { 4  3  7  5 }
    makeText $w t_M  "Minuten" { 7  3 10  5 }

    makeText $w t_B  "vor"     { 1  5  4  7 }
    makeText $w t_P  "nach"    { 4  5  7  7 }
    makeText $w t_h  "halb"    { 7  5 10  7 }

    makeText $w t_1  "ein"     { 1  7  4  9 }
    makeText $w t_2  "zwei"    { 4  7  7  9 }
    makeText $w t_3  "drei"    { 7  7 10  9 }

    makeText $w t_4  "vier"    { 1  9  4 11 }
    makeText $w t_5  "fünf"    { 4  9  7 11 }
    makeText $w t_6  "sechs"   { 7  9 10 11 }

    makeText $w t_7  "sieben"  { 1 11  4 13 }
    makeText $w t_8  "acht"    { 4 11  7 13 }
    makeText $w t_9  "neun"    { 7 11 10 13 }

    makeText $w t_10 "zehn"    { 1 13  4 15 }
    makeText $w t_11 "elf"     { 4 13  7 15 }
    makeText $w t_12 "zwölf"   { 7 13 10 15 }

    makeText $w t_C  "Uhr"     { 1 15  4 17 }
    makeText $w t_AM "morgens" { 4 15  7 17 }
    makeText $w t_PM "abends"  { 7 15 10 17 }

    array set ::mTab {
      00  { t_I }
      01  { t_W }
      02  { t_W }

      03  { t_N t_P t_v t_M }
      04  { t_N t_P t_v t_M }
      05  { t_I t_P t_v t_M }
      06  { t_W t_P t_v t_M }
      07  { t_W t_P t_v t_M }

      08  { t_N t_P t_x t_M }
      09  { t_N t_P t_x t_M }
      10  { t_I t_P t_x t_M }
      11  { t_W t_P t_x t_M }
      12  { t_W t_P t_x t_M }

      13  { t_N t_P t_v t_x t_M }
      14  { t_N t_P t_v t_x t_M }
      15  { t_I t_P t_v t_x t_M }
      16  { t_W t_P t_v t_x t_M }
      17  { t_W t_P t_v t_x t_M }

      18  { t_N t_B t_x t_h t_M hH }
      19  { t_N t_B t_x t_h t_M hH }
      20  { t_I t_B t_x t_h t_M hH }
      21  { t_W t_B t_x t_h t_M hH }
      22  { t_W t_B t_x t_h t_M hH }

      23  { t_N t_B t_v t_h t_M hH }
      24  { t_N t_B t_v t_h t_M hH }
      25  { t_I t_B t_v t_h t_M hH }
      26  { t_W t_B t_v t_h t_M hH }
      27  { t_W t_B t_v t_h t_M hH }

      28  { t_N t_h hH }
      29  { t_N t_h hH }
      30  { t_I t_h hH }
      31  { t_W t_h hH }
      32  { t_W t_h hH }

      33  { t_N t_P t_v t_h t_M hH }
      34  { t_N t_P t_v t_h t_M hH }
      35  { t_I t_P t_v t_h t_M hH }
      36  { t_W t_P t_v t_h t_M hH }
      37  { t_W t_P t_v t_h t_M hH }

      38  { t_N t_P t_x t_h t_M hH }
      39  { t_N t_P t_x t_h t_M hH }
      40  { t_I t_P t_x t_h t_M hH }
      41  { t_W t_P t_x t_h t_M hH }
      42  { t_W t_P t_x t_h t_M hH }

      43  { t_N t_B t_v t_x t_M hH }
      44  { t_N t_B t_v t_x t_M hH }
      45  { t_I t_B t_v t_x t_M hH }
      46  { t_W t_B t_v t_x t_M hH }
      47  { t_W t_B t_v t_x t_M hH }

      48  { t_N t_B t_x t_M hH }
      49  { t_N t_B t_x t_M hH }
      50  { t_I t_B t_x t_M hH }
      51  { t_W t_B t_x t_M hH }
      52  { t_W t_B t_x t_M hH }

      53  { t_N t_B t_v t_M hH }
      54  { t_N t_B t_v t_M hH }
      55  { t_I t_B t_v t_M hH }
      56  { t_W t_B t_v t_M hH }
      57  { t_W t_B t_v t_M hH }

      58  { t_N hH }
      59  { t_N hH }
    }
  ## puts $::mTab(05)
  }


  proc start02 {w} {
  # setup for german fuzzyclock#2, 8x3 panels: "drei Uhr fünf und zwanzig Minuten"

    destroy $w;  pack [canvas $w  -width 260  -height 260  -background grey]

    makeText $w t_I  "Es ist"   { 1  1  4  3 }
    makeText $w t_AM "morgens"  { 4  1  7  3 }
    makeText $w t_0  "null"     { 7  1 10  3 }

    makeText $w t_1  "ein"      { 1  3  4  5 }
    makeText $w t_2  "zwei"     { 4  3  7  5 }
    makeText $w t_3  "drei"     { 7  3 10  5 }

    makeText $w t_4  "vier"     { 1  5  4  7 }
    makeText $w t_5  "fünf"     { 4  5  7  7 }
    makeText $w t_6  "sechs"    { 7  5 10  7 }

    makeText $w t_7  "sieben"   { 1  7  4  9 }
    makeText $w t_8  "acht"     { 4  7  7  9 }
    makeText $w t_9  "neun"     { 7  7 10  9 }

    makeText $w t_10 "zehn"     { 1  9  4 11 }
    makeText $w t_11 "elf"      { 4  9  7 11 }
    makeText $w t_12 "zwölf"    { 7  9 10 11 }

    makeText $w t_C  "Uhr"      { 1 11  4 13 }
    makeText $w t_v  "fünf"     { 4 11  7 13 }
    makeText $w t_x  "zehn"     { 7 11 10 13 }

    makeText $w t_+  "und"      { 1 13  4 15 }
    makeText $w t_xx "zwanzig"  { 4 13  7 15 }
    makeText $w t_30 "dreissig" { 7 13 10 15 }

    makeText $w t_40 "vierzig"  { 1 15  4 17 }
    makeText $w t_50 "fünfzig"  { 4 15  7 17 }
    makeText $w t_M  "Minuten"  { 7 15 10 17 }

    array set ::mTab {
      00  { t_I }
      01  { t_I }
      02  { t_I }

      03  { t_I t_v t_M }
      04  { t_I t_v t_M }
      05  { t_I t_v t_M }
      06  { t_I t_v t_M }
      07  { t_I t_v t_M }

      08  { t_I t_x t_M }
      09  { t_I t_x t_M }
      10  { t_I t_x t_M }
      11  { t_I t_x t_M }
      12  { t_I t_x t_M }

      13  { t_I t_v t_x t_M }
      14  { t_I t_v t_x t_M }
      15  { t_I t_v t_x t_M }
      16  { t_I t_v t_x t_M }
      17  { t_I t_v t_x t_M }

      18  { t_I t_xx t_M }
      19  { t_I t_xx t_M }
      20  { t_I t_xx t_M }
      21  { t_I t_xx t_M }
      22  { t_I t_xx t_M }

      23  { t_I t_v t_+ t_xx t_M }
      24  { t_I t_v t_+ t_xx t_M }
      25  { t_I t_v t_+ t_xx t_M }
      26  { t_I t_v t_+ t_xx t_M }
      27  { t_I t_v t_+ t_xx t_M }

      28  { t_I t_+ t_30 t_M }
      29  { t_I t_+ t_30 t_M }
      30  { t_I t_+ t_30 t_M }
      31  { t_I t_+ t_30 t_M }
      32  { t_I t_+ t_30 t_M }

      33  { t_I t_v t_+  t_30 t_M }
      34  { t_I t_v t_+  t_30 t_M }
      35  { t_I t_v t_+  t_30 t_M }
      36  { t_I t_v t_+  t_30 t_M }
      37  { t_I t_v t_+  t_30 t_M }

      38  { t_I t_+ t_40 t_M }
      39  { t_I t_+ t_40 t_M }
      40  { t_I t_+ t_40 t_M }
      41  { t_I t_+ t_40 t_M }
      42  { t_I t_+ t_40 t_M }

      43  { t_I t_v t_+  t_40 t_M }
      44  { t_I t_v t_+  t_40 t_M }
      45  { t_I t_v t_+  t_40 t_M }
      46  { t_I t_v t_+  t_40 t_M }
      47  { t_I t_v t_+  t_40 t_M }

      48  { t_I t_+ t_50 t_M }
      49  { t_I t_+ t_50 t_M }
      50  { t_I t_+ t_50 t_M }
      51  { t_I t_+ t_50 t_M }
      52  { t_I t_+ t_50 t_M }

      53  { t_I t_v t_+  t_50 t_M }
      54  { t_I t_v t_+  t_50 t_M }
      55  { t_I t_v t_+  t_50 t_M }
      56  { t_I t_v t_+  t_50 t_M }
      57  { t_I t_v t_+  t_50 t_M }

      58  { t_I  hH }
      59  { t_I  hH }
   }
   .c configure  -background black
 }


  proc start03 {w} {
  # setup for german fuzzyclock#3, 8x3 panels: "morgens viertel nach elf"

    destroy $w;  pack [canvas $w  -width 260  -height 260  -background grey]


   #makeText $w t_N  "Es wird" { 1  1  4  3 }
    makeText $w t_N  "Es wird" $::a1
    makeText $w t_I  "Es ist"  $::b1
    makeText $w t_W  "Es war"  $::c1

    makeText $w t_AM "morgens" $::a2
    makeText $w t_PM "abends"  $::b2
    makeText $w t_v  "fünf"    $::c2

    makeText $w t_x  "zehn"    $::a3
   #makeText $w t_M  "Minuten" $::b3
    makeText $w t_q  "viertel" $::b3
    makeText $w t_B  "vor"     $::c3

    makeText $w t_P  "nach"    $::a4
    makeText $w t_h  "halb"    $::b4
    makeText $w t_0  "null"    $::c4

    makeText $w t_1  "ein"     $::a5
    makeText $w t_2  "zwei"    $::b5
    makeText $w t_3  "drei"    $::c5

    makeText $w t_4  "vier"    $::a6
    makeText $w t_5  "fünf"    $::b6
    makeText $w t_6  "sechs"   $::c6

    makeText $w t_7  "sieben"  $::a7
    makeText $w t_8  "acht"    $::b7
    makeText $w t_9  "neun"    $::c7

    makeText $w t_10 "zehn"    $::a8
    makeText $w t_11 "elf"     $::b8
    makeText $w t_12 "zwölf"   $::c8

   #makeText $w t_C_  "Uhr"    $::c9

    array set ::mTab {
      00  { t_I }
      01  { t_W }
      02  { t_W }

      03  { t_N t_P t_v t_M }
      04  { t_N t_P t_v t_M }
      05  { t_I t_P t_v t_M }
      06  { t_W t_P t_v t_M }
      07  { t_W t_P t_v t_M }

      08  { t_N t_P t_x t_M }
      09  { t_N t_P t_x t_M }
      10  { t_I t_P t_x t_M }
      11  { t_W t_P t_x t_M }
      12  { t_W t_P t_x t_M }

      13  { t_N t_P t_q t_M }
      14  { t_N t_P t_q t_M }
      15  { t_I t_P t_q t_M }
      16  { t_W t_P t_q t_M }
      17  { t_W t_P t_q t_M }

      18  { t_N t_B t_x t_h t_M hH }
      19  { t_N t_B t_x t_h t_M hH }
      20  { t_I t_B t_x t_h t_M hH }
      21  { t_W t_B t_x t_h t_M hH }
      22  { t_W t_B t_x t_h t_M hH }

      23  { t_N t_B t_v t_h t_M hH }
      24  { t_N t_B t_v t_h t_M hH }
      25  { t_I t_B t_v t_h t_M hH }
      26  { t_W t_B t_v t_h t_M hH }
      27  { t_W t_B t_v t_h t_M hH }

      28  { t_N t_h hH }
      29  { t_N t_h hH }
      30  { t_I t_h hH }
      31  { t_W t_h hH }
      32  { t_W t_h hH }

      33  { t_N t_P t_v t_h t_M hH }
      34  { t_N t_P t_v t_h t_M hH }
      35  { t_I t_P t_v t_h t_M hH }
      36  { t_W t_P t_v t_h t_M hH }
      37  { t_W t_P t_v t_h t_M hH }

      38  { t_N t_P t_x t_h t_M hH }
      39  { t_N t_P t_x t_h t_M hH }
      40  { t_I t_P t_x t_h t_M hH }
      41  { t_W t_P t_x t_h t_M hH }
      42  { t_W t_P t_x t_h t_M hH }

      43  { t_N t_B t_q t_M hH }
      44  { t_N t_B t_q t_M hH }
      45  { t_I t_B t_q t_M hH }
      46  { t_W t_B t_q t_M hH }
      47  { t_W t_B t_q t_M hH }

      48  { t_N t_B t_x t_M hH }
      49  { t_N t_B t_x t_M hH }
      50  { t_I t_B t_x t_M hH }
      51  { t_W t_B t_x t_M hH }
      52  { t_W t_B t_x t_M hH }

      53  { t_N t_B t_v t_M hH }
      54  { t_N t_B t_v t_M hH }
      55  { t_I t_B t_v t_M hH }
      56  { t_W t_B t_v t_M hH }
      57  { t_W t_B t_v t_M hH }

      58  { t_N hH }
      59  { t_N hH }
   }
   .c configure  -background maroon
 }


  proc start04 {w} {
  # setup for german fuzzyclock#4, 8x3 panels: "morgens viertel nach elf Uhr"

    destroy $w;  pack [canvas $w  -width 260  -height 260  -background grey]


   #makeText $w t_N  "Es wird" { 1  1  4  3 }
    makeText $w t_N  "Es wird" $::a1
    makeText $w t_I  "Es ist"  $::b1
    makeText $w t_W  "Es war"  $::c1

    makeText $w t_AM "morgens" $::a2
   #makeText $w t_PM "abends"  $::b2
    makeText $w t_v  "fünf"    $::b2
    makeText $w t_x  "zehn"    $::c2
   #makeText $w t_M  "Minuten" $::c2

    makeText $w t_q  "viertel" $::a3
    makeText $w t_B  "vor"     $::b3
    makeText $w t_P  "nach"    $::c3

    makeText $w t_h  "halb"    $::a4
    makeText $w t_0  "null"    $::b4
    makeText $w t_1  "ein"     $::c4

    makeText $w t_2  "zwei"    $::a5
    makeText $w t_3  "drei"    $::b5
    makeText $w t_4  "vier"    $::c5

    makeText $w t_5  "fünf"    $::a6
    makeText $w t_6  "sechs"   $::b6
    makeText $w t_7  "sieben"  $::c6

    makeText $w t_8  "acht"    $::a7
    makeText $w t_9  "neun"    $::b7
    makeText $w t_10 "zehn"    $::c7

    makeText $w t_11 "elf"     $::a8
    makeText $w t_12 "zwölf"   $::b8
    makeText $w t_C  "Uhr"     $::c8

    array set ::mTab {
      00  { t_I }
      01  { t_W }
      02  { t_W }

      03  { t_N t_P t_v t_M }
      04  { t_N t_P t_v t_M }
      05  { t_I t_P t_v t_M }
      06  { t_W t_P t_v t_M }
      07  { t_W t_P t_v t_M }

      08  { t_N t_P t_x t_M }
      09  { t_N t_P t_x t_M }
      10  { t_I t_P t_x t_M }
      11  { t_W t_P t_x t_M }
      12  { t_W t_P t_x t_M }

      13  { t_N t_P t_q t_M }
      14  { t_N t_P t_q t_M }
      15  { t_I t_P t_q t_M }
      16  { t_W t_P t_q t_M }
      17  { t_W t_P t_q t_M }

      18  { t_N t_B t_x t_h t_M hH }
      19  { t_N t_B t_x t_h t_M hH }
      20  { t_I t_B t_x t_h t_M hH }
      21  { t_W t_B t_x t_h t_M hH }
      22  { t_W t_B t_x t_h t_M hH }

      23  { t_N t_B t_v t_h t_M hH }
      24  { t_N t_B t_v t_h t_M hH }
      25  { t_I t_B t_v t_h t_M hH }
      26  { t_W t_B t_v t_h t_M hH }
      27  { t_W t_B t_v t_h t_M hH }

      28  { t_N t_h hH }
      29  { t_N t_h hH }
      30  { t_I t_h hH }
      31  { t_W t_h hH }
      32  { t_W t_h hH }

      33  { t_N t_P t_v t_h t_M hH }
      34  { t_N t_P t_v t_h t_M hH }
      35  { t_I t_P t_v t_h t_M hH }
      36  { t_W t_P t_v t_h t_M hH }
      37  { t_W t_P t_v t_h t_M hH }

      38  { t_N t_P t_x t_h t_M hH }
      39  { t_N t_P t_x t_h t_M hH }
      40  { t_I t_P t_x t_h t_M hH }
      41  { t_W t_P t_x t_h t_M hH }
      42  { t_W t_P t_x t_h t_M hH }

      43  { t_N t_B t_q t_M hH }
      44  { t_N t_B t_q t_M hH }
      45  { t_I t_B t_q t_M hH }
      46  { t_W t_B t_q t_M hH }
      47  { t_W t_B t_q t_M hH }

      48  { t_N t_B t_x t_M hH }
      49  { t_N t_B t_x t_M hH }
      50  { t_I t_B t_x t_M hH }
      51  { t_W t_B t_x t_M hH }
      52  { t_W t_B t_x t_M hH }

      53  { t_N t_B t_v t_M hH }
      54  { t_N t_B t_v t_M hH }
      55  { t_I t_B t_v t_M hH }
      56  { t_W t_B t_v t_M hH }
      57  { t_W t_B t_v t_M hH }

      58  { t_N hH }
      59  { t_N hH }
   }
   .c configure  -background MediumVioletRed  ;# MediumPurple MediumOrchid
 }


  proc start11 {w} {
  # setup for international fuzzyclock#1, 8x3 panels: "three o'clock twenty five minutes"

    destroy $w;  pack [canvas $w  -width 260  -height 260  -background grey]


   #makeText $w t_I  "It is"   { 1  1  4  3 }
    makeText $w t_I  "It is"   $::a1
    makeText $w t_AM "AM"      $::b1
    makeText $w t_0  "zero"    $::c1

    makeText $w t_1  "one"     $::a2
    makeText $w t_2  "two"     $::b2
    makeText $w t_3  "three"   $::c2

    makeText $w t_4  "four"    $::a3
    makeText $w t_5  "five"    $::b3
    makeText $w t_6  "six"     $::c3

    makeText $w t_7  "seven"   $::a4
    makeText $w t_8  "eight"   $::b4
    makeText $w t_9  "nine"    $::c4

    makeText $w t_10 "ten"     $::a5
    makeText $w t_11 "eleven"  $::b5
    makeText $w t_12 "twelve"  $::c5

    makeText $w t_C  "o'clock" $::a6
    makeText $w t_x  "ten"     $::b6
    makeText $w t_xv "fifteen" $::c6

    makeText $w t_xx "twenty"  $::a7
    makeText $w t_30 "thirty"  $::b7
    makeText $w t_40 "fourty"  $::c7

    makeText $w t_50 "fifty"   $::a8
    makeText $w t_v  "five"    $::b8
    makeText $w t_M  "minutes" $::c8

    array set ::mTab {
      00  { t_I }
      01  { t_I }
      02  { t_I }

      03  { t_I t_v t_M }
      04  { t_I t_v t_M }
      05  { t_I t_v t_M }
      06  { t_I t_v t_M }
      07  { t_I t_v t_M }

      08  { t_I t_x t_M }
      09  { t_I t_x t_M }
      10  { t_I t_x t_M }
      11  { t_I t_x t_M }
      12  { t_I t_x t_M }

      13  { t_I t_xv t_M }
      14  { t_I t_xv t_M }
      15  { t_I t_xv t_M }
      16  { t_I t_xv t_M }
      17  { t_I t_xv t_M }

      18  { t_I t_xx t_M }
      19  { t_I t_xx t_M }
      20  { t_I t_xx t_M }
      21  { t_I t_xx t_M }
      22  { t_I t_xx t_M }

      23  { t_I t_v t_+ t_xx t_M }
      24  { t_I t_v t_+ t_xx t_M }
      25  { t_I t_v t_+ t_xx t_M }
      26  { t_I t_v t_+ t_xx t_M }
      27  { t_I t_v t_+ t_xx t_M }

      28  { t_I t_30 t_M }
      29  { t_I t_30 t_M }
      30  { t_I t_30 t_M }
      31  { t_I t_30 t_M }
      32  { t_I t_30 t_M }

      33  { t_I t_v t_+  t_30 t_M }
      34  { t_I t_v t_+  t_30 t_M }
      35  { t_I t_v t_+  t_30 t_M }
      36  { t_I t_v t_+  t_30 t_M }
      37  { t_I t_v t_+  t_30 t_M }

      38  { t_I t_40 t_M }
      39  { t_I t_40 t_M }
      40  { t_I t_40 t_M }
      41  { t_I t_40 t_M }
      42  { t_I t_40 t_M }

      43  { t_I t_v t_+  t_40 t_M }
      44  { t_I t_v t_+  t_40 t_M }
      45  { t_I t_v t_+  t_40 t_M }
      46  { t_I t_v t_+  t_40 t_M }
      47  { t_I t_v t_+  t_40 t_M }

      48  { t_I t_50 t_M }
      49  { t_I t_50 t_M }
      50  { t_I t_50 t_M }
      51  { t_I t_50 t_M }
      52  { t_I t_50 t_M }

      53  { t_I t_v t_50 t_M }
      54  { t_I t_v t_50 t_M }
      55  { t_I t_v t_50 t_M }
      56  { t_I t_v t_50 t_M }
      57  { t_I t_v t_50 t_M }

      58  { t_I  hH }
      59  { t_I  hH }
   }
   .c configure  -background blue
 }


 ### Main:

  #start01 .c   ;#1 : german fuzzyclock:        "fünf Minuten vor halb vier Uhr"
  #start02 .c   ;#2 : german fuzzyclock:        "drei Uhr fünf und zwanzig Minuten"
  #start03 .c   ;#3 : german fuzzyclock:        "viertel nach drei"
  #start04 .c   ;#4 : german fuzzyclock:        "viertel nach drei Uhr"
  #
   start11 .c   ;#11: international fuzzyclock: "three o'clock twenty five minutes"

   focus -f .c
   update

   bind .  <F1>     { console show }
   catch {console show}        ;##
   catch {console hide}

   wm title . "$Prog(title) $Prog(version)"
   puts       "$Prog(title) $Prog(version)"
   puts       "tcl: $tcl_patchLevel"
   puts       "tk : $tk_patchLevel"

   puts "now,h,m,x,y,z:change time,  u:update, run, stop, e:exit"

   now
   after 250
   u

   sync0
   run

 ### EOF ###

Remarks

if 0 {

MiHa 2015-02-24 - Some bugfixes for the minute-table, and improved wiki-formatting.

MiHa 2015-03-03 - I added two more versions for a german fuzzyclock "morgens viertel nach elf Uhr", meaning "quarter past eleven".
Rearranging the panels is much more easy to do now with the spreadsheet-addressing, then with the old list of coordinates.
To avoid adding another row of panels, the entries for "PM"/"evening" and "minutes" had to be dropped.

Some ideas for further programming:

  • change font of text in lit panels to be bold
  • ESC --> Quit
  • click on panel "it is" --> update clock
  • click on panels "one", "two" etc. --> change layout
  • click on panels "before"/"after" --> change color
  • catch resize-event, and resize panels and text
  • Color-Table (needs some concept)
  • F1 --> Help / Balloon-help when hovering over panels

To sum up the experience:

  • Tcl by itself is quite simple.
  • A demo-program that shows every feature should be possible in about one printed page
  • Things to lookout:
    • keeping quotes and braces balanced inside comments
    • when to use / not use $ with variablenames ( set i 1; puts $i; incr i $i )
  • Tk is much bigger, and needs going to the docs quite often
  • The help-docs are not bad as such, but are very frustrating to use -->
    • here is still much room for improvement
  • IDE: Geany - code completion for tcl needs work

kpv Also check out Word Clock for another textual clock.

MiHa Yes - it has already been on the list, right before "Designers notes".

Old

MiHa 2015-03-04 - Now finally with an international fuzzyclock "quarter before/past".

MiHa 2015-03-05 - I changed the coordinates and scale, to get finer grained text-positioning,
as well as adjustable columnwidth for each of the layouts.
Further, I gave each layout its very own position on the screen.

When starting, the program now looks at argv, and processes the commandline-arguments.
That works both with tclsh and wish.

Currently implemented commandline-arguments to control layout, sound, and placement on the screen:

  • -s0 -s1 -s2 : no sound / simple chime (beep) at the full hour / ship's bell every half hour.
    The default is no sound.
  • -p0 -p1 -p2 : no setting of screen-position / top left / top right.
    The default is to give each layout a unique position on screen.
  • Everything else is understood as a key to select the layout.
    If not recognized, some default-layout is used.
    Recognized are DE1,DE2,DE3,DE4 for the german clocks,
    I1,I2 for the international clocks, and G,SB for the ship's bells.

With all that plumbing in place, it is now easy to show all the layouts at once, and compare them.
(Re-using my test-setup as a showcase:)

To see this in action, use a batchfile (for Windows) such as the following
to start one tcl-interpreter for each of the layouts:


  start wish FuzzyClock.tcl DE1
  start wish FuzzyClock.tcl DE2
  start wish FuzzyClock.tcl DE3
  start wish FuzzyClock.tcl DE4

  start wish FuzzyClock.tcl I1
  start wish FuzzyClock.tcl I2
  start wish FuzzyClock.tcl G
  start wish FuzzyClock.tcl SB -s2

That means, all these clocks are running with no sound, except for the one with -s2,
and all the layouts get distributed to different places across the screen.


New

MiHa 2015-03-13 - I have created layouts for ship's bell / "Glasenuhr"
http://en.wikipedia.org/wiki/Ship%27s_bell / http://de.wikipedia.org/wiki/Glasenuhr
with both a german and an international version.

My international ship's bell uses the "simpler system" according to the wikipedia-page,
that is, without the dogwatch split into two parts.
Not being a sailor, that looks like the Standard merchant watch system to me.

To summarise the concept for the ship's clock:

  • In the days of sailing ships, they used hour-glasses for timing,
    one glass running 4 hours and another glass running for 30 minutes.
  • The turning of the glasses are signalled with the ship's bell.
  • The day is divided into "watches" (working shifts) that last 4 hours.
    The current watch is not announced with the bell - everyone on board has to know that it is day/night/afternoon etc.
  • Each watch is divided into half-hour periods, so each watch lasts "8 bells",
    i.e. it starts with "8 bells" ending the previous watch, gets to "1 bell" after half an hour,
    "2 bells" after one hour, etc., and ends with "8 bells" after 4 hours.

To bring those shipclocks to the same "fuzzy precision" as the other clocks, I added 5-minute "lights".

Finally, I changed the "every" and "sync"-mechanism to use a more gentle approach
to bring the screen-updates to occur on multiples of 10 seconds.
The old coding made the program unresponsive during the first few seconds.

Have fun !

}