Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

When my daughter asked me help with her spelling homework, for me the obvious thing to do was to write a Mathematica program for it.

The words:

words = {"lightning", "thunder", "cloudy"};

The code:

Grid[
 Module[{x = 0, t = 0},
    {
     #,
     Button["Start", t = Hold@AbsoluteTime[] - AbsoluteTime[]], 
     Button[Style["\[Checkmark]", Darker@Green], t = ReleaseHold[t]; x++],
     Button[Style[    "\[Times]",        Red  ], t = ReleaseHold[t]; x--],
     Dynamic[x],
     Dynamic[Clock[]; ReleaseHold[t]]
     }
    ] & /@ words]

Which produces this output:

screenshot

So when I ask her a word, I click "start". Then I click ✔ or × if her answer is right or wrong respectively. I plan to keep track of time to answer, so the timer now shows how much time it took to answer.

So my question is: Why do I have to use Module instead of DynamicModule? For some reason the Grid command does not work if I use DynamicModule. On the other hand, if I use Module (as it is shown), then the syntax highlighter shows my "t" and "x" variables in red as if I am doing something wrong: enter image description here

Update: I have just realized that using Module instead of DynamicModule is not a viable option as the scores are lost when you reopen the notebook.

Update 2: For the record, this is the finished program incorporating the advice from Mr.Wizard and kguler

DynamicModule[{x, t, status, h},
 x[_] = 0;
 t[_] = 0;
 status[_] = False;
 h[_] = {};
 Column[{Grid[
    MapIndexed[{
       #,
       Button["Start", 
              Speak@#; status[#2] = True; 
              t[#2] = Hold@AbsoluteTime[] -AbsoluteTime[], 
              Enabled -> Dynamic[! status[#2]]],
       Button[Style["\[Checkmark]", Darker@Green], 
              t[#2] = ReleaseHold[t[#2]]; x[#2]++; AppendTo[h[#2], t[#2]]; 
              status[#2] = False,
              Enabled -> Dynamic[status[#2]]],
       Button[Style["\[Times]", Red],
              t[#2] = ReleaseHold[t[#2]]; x[#2]--; AppendTo[h[#2], -t[#2]];
              status[#2] = False, 
              Enabled -> Dynamic[status[#2]]],
       Button["spell", Speak@StringJoin[Riffle[Characters[#], ","]]],
       Dynamic[x[#2]],
       Dynamic[Clock[]; ReleaseHold[NumberForm[t[#2], 2]]],
       Dynamic@
        If[Length@h[#2] > 0, 
         Module[{z = Transpose[{Abs[#], Sign[#]} & /@ h[#2]]}, 
          Graphics[
           (Rectangle @@@ 
            (Partition[{Accumulate[First@z],Last@z}\[Transpose],2,1,{2,2},{{0, 0}}] /.
             {{x1_, y1_Integer}, {x2_, y2_Integer}} -> {{x1 + 0.2, 0}, {x2, y2}})) /.
             {Rectangle[{x1_,0}, {x2_, 1}] -> {Darker@Green, Rectangle[{x1, 0}, {x2, 1}]}, 
              Rectangle[{x1_,0}, {x2_,-1}] -> {Red, Rectangle[{x1,0}, {x2, -1}]}},
           ImageSize -> {Automatic, 20}, 
           PlotRange -> {-1, 1}]], 
         ""
        ]
    } &, words],
    Alignment -> Left],
    Row[{Button[
      "reset", (x[{#}] = 0; t[{#}] = 0; h[{#}] = {}) & /@ 
       Range@Length@words], Spacer[10]}]}]]

enter image description here

share|improve this question
1  
You should really look at Anki (which of course doesn't mean that we shouldn't solve this in Mathematica!) –  Szabolcs Feb 16 '12 at 13:16
4  
+1 for doing spelling homework using Mathematica! –  Eli Lansey Feb 16 '12 at 16:13
1  
+1. Using Beep is perhaps going too far, but ... Speak and Characters might come handy in this task: Speak["potatoes"] and StringJoin[Riffle[Characters["potatoes"], " "]]. –  kguler Feb 16 '12 at 18:36
    
I happened to glance at this again and I noticed that you did not localize pattern names with RuleDelayed. For example Rectangle[{x1_,0}, {x2_,-1}] -> {Red, Rectangle[{x1,0}, {x2, -1}] should be written Rectangle[{x1_,0}, {x2_,-1}] :> {Red, Rectangle[{x1,0}, {x2, -1}] to protect x1 and x2. –  Mr.Wizard Feb 14 '13 at 19:52

1 Answer 1

up vote 10 down vote accepted

This is because the object created by DynamicModule does not actually evaluate until it is displayed, therefore Grid has nothing to format other than the outer list.

words = {"lightning", "lightning", "cloudy"};

dynlist = 
  DynamicModule[{x = 0, t = 0},
    {
     #,
     Button["Start", t = Hold@AbsoluteTime[] - AbsoluteTime[]], 
     Button[Style["\[Checkmark]", Darker@Green], t = ReleaseHold[t]; x++],
     Button[Style[    "\[Times]",        Red  ], t = ReleaseHold[t]; x--],
     Dynamic[x],
     Dynamic[Clock[]; ReleaseHold[t]]
     }
    ] & /@ words;


ToString[ dynlist[[1]] ]

"DynamicModule[{x = 0, t = 0}, {lightning, Button[Start, t = \ Hold[AbsoluteTime[]] - AbsoluteTime[]], Button[[Checkmark], t = \ ReleaseHold[t]; x++], Button[[Times], t = ReleaseHold[t]; x--], \ Dynamic[x], Dynamic[Clock[]; ReleaseHold[t]]}, DynamicModuleValues :> \ {}]"

You could build the rows inside the module:

Column[
 DynamicModule[{x = 0, t = 0},
    Grid@{{
     #,
     Button["Start", t = Hold@AbsoluteTime[] - AbsoluteTime[]], 
     Button[Style["\[Checkmark]", Darker@Green], t = ReleaseHold[t]; x++],
     Button[Style[    "\[Times]",        Red  ], t = ReleaseHold[t]; x--],
     Dynamic[x],
     Dynamic[Clock[]; ReleaseHold[t]]
     }}
    ] & /@ words]

Mathematica graphics


Addressing your comment you could move the map operation inside Grid like this:

DynamicModule[{x, t},
 x[_] = 0;
 t[_] = 0;
 Grid[
  MapIndexed[
    {#, Button["Start", t[#2] = Hold@AbsoluteTime[] - AbsoluteTime[]], 
     Button[Style["\[Checkmark]", Darker@Green], 
      t[#2] = ReleaseHold[t[#2]]; x[#2]++], 
     Button[Style["\[Times]", Red], t[#2] = ReleaseHold[t[#2]]; 
      x[#2]--], Dynamic[x[#2]], 
     Dynamic[Clock[]; ReleaseHold[t[#2]]]} &,
   words
]]]

Mathematica graphics

share|improve this answer
    
Yes, but it needs to be on a grid. Otherwise it looks ugly as you have shown. –  Gustavo Delfino Feb 16 '12 at 15:49
    
@Gustavo see edit; sorry for sloppy formatting but I don't have time to make it pretty. –  Mr.Wizard Feb 16 '12 at 16:41
    
Thank you! I had tried unsuccessfully with Map, but I see you cleverly solved it using MapIndexed. –  Gustavo Delfino Feb 16 '12 at 17:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.