Here is a toy example:
qnam[q_, a_, alt_, nr_] :=
DynamicModule[
{ln, funs, var, enb, layout, cusum, vis = "", perc},
ln = Length[q];
enb = Table[Unique["e"], {ln}];
Map[(#[_] := True) &, enb];
funs = Table[Unique["f"], {ln}];
var = Table[Unique["v"], {ln}];
MapThread[(#1[u_] := If[u == #2, 1, 0]) &, {funs, a}];
layout = MapThread[Column[{
#1,
RadioButtonBar[Dynamic@#2, Thread[Range[Length@#3] -> #3],
Enabled -> Dynamic@#5[#2], Appearance -> "Vertical"],
Button["Lock in answer", #5[#2] := False]
}] &, {q, var, alt, funs, enb}];
cusum = Dynamic[Total@MapThread[#1[#2] &, {funs, var}]];
perc = NumberForm[
Dynamic[N@100 Total@MapThread[#1[#2] &, {funs, var}]/ln, 3], 2];
Quiet@Column[{
Grid[Partition[layout, nr]],
Row[{Button["Cumulative score",
If[! Or @@ MapThread[#1[#2] &, {enb, var}],
vis = Style[Row[{cusum/Length@q, "(", perc, "%)"}], 20, Red],
vis = ""]
], Dynamic@vis}]}, Frame -> True,
BaseStyle -> {FontFamily -> "Kartika", Blue, 20}]
]
tt[n_, na_, nr_] := Module[{r, q, a, or, an, alt, ans, res},
r = RandomInteger[{2, 12}, {n, 2}];
q = StringForm["`1`\[Times]`2`=", #[[1]], #[[2]]] & /@ r;
a = Times @@@ r;
or = Table[RandomSample[Range[na]], {n}];
an = MapThread[
Join[#1, {#2}] &, {RandomSample[DeleteCases[Range[4, 144], #],
na - 1] & /@ a, a}];
alt = MapThread[#1[[#2]] &, {an, or}];
ans = Flatten@MapThread[Position[#1, #2] &, {alt, a}];
qnam[q, ans, alt, nr]]
full[n_, na_, nr_] := DynamicModule[{res},
res = tt[n, na, nr];
Dynamic[Column[{res, Button["Reset", res = tt[n, na, nr]]}]]]
Now say you want to create a set of 12 questions: 3 x 4 (rxc) layout with 5 alternatives:
full[12, 5, 4]
And just for fun a smaller example:
I appreciate: (i) it does not tell you what the right answer is (ii)let you try again.
This was just for 'fun' and if I get a chance may be I will improve.
UPDATE
The following modification deal with some of the caveats. However, once you show the answers you can redo...but is there really any point?
qnamod[q_, a_, alt_, nr_] :=
DynamicModule[
{ln, funs, var, enb, layout, cusum, vis = "", perc, rr = ""},
ln = Length[q];
enb = Table[Unique["e"], {ln}];
Map[(#[_] := True) &, enb];
funs = Table[Unique["f"], {ln}];
var = Table[Unique["v"], {ln}];
MapThread[(#1[u_] := If[u == #2, 1, 0]) &, {funs, a}];
layout = MapThread[Column[{
#1,
RadioButtonBar[Dynamic@#2, Thread[Range[Length@#3] -> #3],
Enabled -> Dynamic@#5[#2], Appearance -> "Vertical"],
Button["Lock in answer", #5[#2] := False]
}] &, {q, var, alt, funs, enb}];
cusum = Dynamic[Total@MapThread[#1[#2] &, {funs, var}]];
perc = NumberForm[
Dynamic[N@100 Total@MapThread[#1[#2] &, {funs, var}]/ln, 3], 2];
Quiet@Column[{
Grid[Partition[layout, nr]],
Row[{Button["Cumulative score",
If[! Or @@ MapThread[#1[#2] &, {enb, var}],
vis = Style[Row[{cusum/Length@q, "(", perc, "%)"}], 20, Red],
vis = ""]
], Dynamic@vis}],
Column[{Button["Answers",
If[! Or @@ MapThread[#1[#2] &, {enb, var}],
rr = Grid[Thread[{q, MapThread[#1[[#2]] &, {alt, a}]}]],
rr = ""]], Dynamic@rr}],
Button["Try again",
Dynamic@MapThread[(#1[#2] := True) &, {enb, var}]]},
Frame -> True, BaseStyle -> {FontFamily -> "Kartika", Blue, 20}]
]
ttm[n_, na_, nr_] := Module[{r, q, a, or, an, alt, ans, res},
r = RandomInteger[{2, 12}, {n, 2}];
q = StringForm["`1`\[Times]`2`=", #[[1]], #[[2]]] & /@ r;
a = Times @@@ r;
or = Table[RandomSample[Range[na]], {n}];
an = MapThread[
Join[#1, {#2}] &, {RandomSample[DeleteCases[Range[4, 144], #],
na - 1] & /@ a, a}];
alt = MapThread[#1[[#2]] &, {an, or}];
ans = Flatten@MapThread[Position[#1, #2] &, {alt, a}];
qnamod[q, ans, alt, nr]]
fullm[n_, na_, nr_] := DynamicModule[{res},
res = ttm[n, na, nr];
Dynamic[Column[{res, Button["Reset", res = ttm[n, na, nr]]}]]]
Example:
fullm[4, 4, 2]
Enter
key is used only to submit answers. TheTab
key is used to go to the next answer. $\endgroup$