Set Counter Keyword
Keyword to define and
manipulate counters. For a discussion on the uses of counters see the
Simple Counter and the
More Complex Counter sections in the built in
Preferred usage evaluates
using a modified and significantly expanded version
of CALC.C that Bob Brodt wrote in 1985 and assigns the result to
First deprecated usage sets Counter N1
to value N2,
second deprecated usage sets counter N
to some value depending on the string
text. Counters are used to
control branching in DMDX, more specifically for building looping mechanisms.
Before a counter can be used it must be setup at least once with a
keyword, after that it can be incremented or decremented, conditionally incremented
or decremented depending on the subjects response (see the
for a full list of possibilities),
into the output file, tested against with the
or set to another value with <SetCounter>
again. Counter's values are signed 32 bit integers.
Note that if you like named counters (and who doesn't?) using the named
macros you can define a macro to
the counter's number initially (with <md .namedcounter.
3> once at the beginning of the item file say) and then use constructs
like <set c~.namedcounter. = 10> instead of
<set c3 = 10> for example and in places where
just the counter number is valid you can just omit the
c as in <bicgt
~.namedcounter., 10, 100> to branch if counter 3 is greater than 10 to
A counter's value can be stored in the output data file with
and can be displayed with
<AppendCounter>. (not recommended)
or the <sprintf>
keyword (recommended). A counter's value can also be used to set the frame
Possible tokens in
expression and values for
||The value of counter
for example <set 3,counter2>
would set (and create if necessary) counter 3 to the value counter 2 had when
this keyword is parsed.
||Absolute value of the
last Reaction Time gathered in whole milliseconds (rounded down).
Because expressions are evaluated as the item is parsed this RT is the
item's RT, not the RT that might be gathered by the item the expression is in.
||Last Reaction Time
(previous item) gathered in whole milliseconds (rounded down). This
will be negative if the response was incorrect.
||The error rate at the
end of the previous item (useful for multiple tests against the error rate as
branch on the error rate
will reset it). There's an example of how to display the error rate in
time that the clock was last turned on. This has two possible values
depending on whether
is turned on. If <rcot>
is on then loading a counter with clockontime
will return the time the most recent clock on
occurred since the first clock on in the item file, otherwise it is the time since
the item file commenced execution.
time when the expression is evaluated (usually the time the item is parsed
but it can be later with
<AbortItemExpression>) since the item file commenced execution.
||The current video
retrace count when the expression is evaluated since the item file commenced
||The current video
mode width in pixels.
||The current video
mode height in pixels.
||The integer value of the
previous item's text string entered with
value of the job status variable that tracks the job state at the time of
parsing. Only useful for the
Rules regarding evaluation of
are as follows:
* Calculator program - 9 May 1985
* Bob Brodt
* 34 Mehrhof Rd.
* Little Ferry, NJ 07643
* This is a simple integer arithmetic calculator program. It uses infix
* notation, i.e. 1+2*3 as opposed to "reverse polish" notation: 1 2 3 * +.
* Numbers may be input as in C using 0x notation for hex,
* leading zero for octal, everything else is assumed to
Single character constants can be
used in single quotes, reserved
will throw syntax errors if used (for example '"', '>',
'$' and ';'), there are no escape sequences for non-printing
characters (' is legal as in ''').
* DMDX constants at time of evaluation:
* DMDX counters referenced by counterN or cN
* The following operators are supported (from highest precedence
* ( )
* ~ !
one's complement, logical NOT
* * / %
multiply, divide and modulo
* + -
unary and binary add & subtract (note unary operators have problems until
* .SHL. .SHR.
shift left and right
* .LT. .GT. .LE. .GE. less than,
greater than, less than or equal to and
greater than or equal to
* .EQ. .NE.
equal to and not equal to
bitwise exclusive OR
bitwise inclusive OR
comma - separates function arguments
* All operators associate from left to right with the exception
* the assignment (=) operator. Logical operations
resolve to 1 if true and 0
* if false.
* The calculator also has built-in function capabilities:
* max(a, b) - larger of a or b
* min(a, b) - smaller of a or b
* abs(a) - absolute value of a
* random(a) - random number between 0 and a-1 (a should
be less than 32768)
* Precedence of functions is a little weird, currently random(a) + b
evaluates to random(a + b) because
* function call brackets are just brackets, so random a + b is valid
syntax with + having the higher
* precedence. So the safe use of functions is currently (random a)
* Similar kind of thing for unary operators -5 + 15 evaluated to
-20, eek. Worse -5 .ge. 0 evaluates to
* -1 instead of 0.
So you had to have (-5) + 15 and (-5) .ge. 0. Brute forced a fix in
Typical use of a counter involves
setting it to some initial value and decrementing it and using one of the counter
till the counter reaches 0. In the following item 10 will be displayed
0 "looping demo" <set c1 = 5>;
+10 * "display"
Using the named counters usage
from above that example might be written as:
~1 <md .loopcounter. 1> <! we do have
to be a little careful here as setting a macro
and using it can't happen in one item>;
0 "looping demo" <set c~.loopcounter. = 5>;
+10 * "display"
Possible things to be aware of are
that expressions (both in <SetCounter>
<BranchIf> keywords), non conditional arithmetic
and most other actions in counter related keywords are performed as the item is
parsed before display so multiple uses of those keywords in the same item are possible.
Whereas conditional arithmetic keywords (<incic>,
are evaluated after the item is displayed and the RT gathered (thus necessitating
special control structures within DMDX) and are limited to one operation per counter
per item, in the case of multiple uses only the last will have any effect.
Branches other than <BranchIf>
are evaluated at the beginning of the next item after everything else.
Another typical use of counters involves
tracking multiple error rates and branching if the error rates are too high.
In the following each class of test needs an 80% or higher success rate:
100 "start" <set c10=0> <set c11=0>
<set c20=0> <set c21=0>
<set c30=0> <set c31=0>;
+1000 "class 1 test" * <incic
10> <inc 11>;
test" * <incic 20> <inc 21>;
test" * <incic 30> <inc 31>;
repeat items 1000, 2000 and 3000 as needed;
~200 <emit 10> <emit
<emit 20> <emit 21>
<emit 30> <emit 31>
100, (c10 * 100 / c11 .lt. 80) .or.
(c20 * 100 / c21 .lt. 80) .or.
(c30 * 100 / c31 .lt. 80)>;
keyword for a fairly complex counter using example.
keyword for neat subroutine to assign a macro to the ASCII value of a counter
which will then allow you to use a counter's value for setting parameters DMDX
doesn't otherwise allow counters to be used for. Also pretty handy for
treating a range of counters as an array and iterating over them.