Scripting personalized problem data¶
1. General¶
It is possible to create the personalized problem data (PPD) by a script embedded in the TeX source of the problem. The script is specified as the content of the ppdscript
environment. Here is an example:
\begin{ppdscript}
x0 = rand.createRandomMInteger(10, 10, NON_ZERO);
x1 = x0 + 1;
x2 = x0  1;
y = rand.createRandomMInteger(x0  5, x0 + 5);
q = rand.createRandomMRational(6, 36, 12, 72);
q = q.cancelDown();
ppd["user/problem/x1"] = x1;
ppd["user/problem/x2"] = x2;
ppd["user/problem/y"] = y;
ppd["user/problem/q"] = q;
\end{ppdscript}
The script language is based on [[http:_groovy.codehaus.orgGroovy]]. It is easy to learn but powerful, providing features like control structures (loops, conditional branches, etc.) and objectoriented programming (cf. the [[http:_groovy.codehaus.org/User+GuideGroovy User Guide]] for a detailed reference).
2. Number types¶
The script language supports both the standard Groovy number types (which are just the standard Java number types) as well as the Mumiespecific number types defined in the Mathlet Factory. Number literals are of the standard Groovy types:
x = 12; // x is a Groovy Integer
To get a Mathlet Factory number, use one of the respective constructors:
x = new MInteger(12); // x is a Mathlet Factory MInteger
Groovy and Mathlet Factory numbers can be mixed in arithmetic expressions; the result is always a Mathlet Factory number:
x = new MInteger(12); // Mathlet Factory MInteger
y = 7; // Groovy Integer
z = x + y; // Mathlet Factory MInteger
3. Predefined objects¶
There are two predefined global objects in the script:

rand
: A helper object to create random values. The corresponding methods are described in the next section. 
ppd
: The PPD datasheet. Any data that should become personalized data of the problem must be stored here. Section 5 describes how to do this.
= 4. Creating random data¶
The predefined global object rand
provides the following methods to create random data. In all cases, the random numbers are uniformly distributed in the respective set.
4.1. createRandomDouble¶
Synopsis:
createRandomDouble (min, max)
Returns a number of type Double
which is randomly chosen from the interval [min, max]. min and max are numbers of any type which fulfill the condition min < max.
Examples:
x = rand.createRandomDouble(0.5, 2.5);
y = rand.createRandomDouble(1.25, 3);
z = rand.createRandomDouble(0, new MRational(1,2);
4.2. createRandomInt¶
Synopsis:
createRandomInt (min, max)
createRandomInt (min, max, nonzero)
Returns a number of type Integer
which is randomly chosen from the set {min, ..., max} resp. {min, ..., max}\{0}. min and max are numbers of any integral type which fulfill the condition min < max. Whether 0 is excluded or not depends on the nonzero flag nonzero. Its value must be either a boolean or one of the integers 0 and 1. For the latter, the predefined constants ALLOW_ZERO
resp. NON_ZERO
can be used. The meanings of the values are as follows:
true
: Zero is excluded, i.e., the returned random number is guaranteed to be nonzero.false
: Zero is allowed, i.e., the returned random number can be zero if min $\le$ 0 $\le$ max. 0 or
ALLOW_ZERO
: Same asfalse
 1 or
NON_ZERO
: Same astrue
If the nonzero flag is omitted, false
is assumed as default.
Examples:
x = rand.createRandomInt(2, 2);
y = rand.createRandomInt(2, 2, NON_ZERO);
z = rand.createRandomInt(2, 2, true);
4.3. createRandomMDouble¶
Synopsis:
createRandomMDouble (min, max)
Returns a number of type MDouble
(Mathlet Factory type) which is randomly chosen from the interval [min, max]. min and max are numbers of any type which fulfill the condition min < max.
Examples:
x = rand.createMRandomDouble(0.5, 2.5);
y = rand.createMRandomDouble(1.25, 3);
z = rand.createMRandomDouble(0, new MRational(1,2);
4.4. createRandomMInteger¶
Synopsis:
createRandomMInteger (min, max)
createRandomMInteger (min, max, nonzero)
Returns a number of type MInteger
(Mathlet Factory type) which is randomly chosen from the set {min, ..., max} resp. {min, ..., max}\{0}. min and max are numbers of any integral type which fulfill the condition min < max. Whether 0 is excluded or not depends on the nonzero flag nonzero. Its allowed values, meaning, and default are the same as with the createRandomInt
method (see subsection 4.2).
Examples:
x = rand.createRandomMInteger(2, 2);
y = rand.createRandomMInteger(2, 2, NON_ZERO);
z = rand.createRandomMInteger(2, 2, ALLOW_ZERO);
p = rand.createRandomMInteger(2, 2, true);
4.5. createRandomMRational¶
Synopsis:
createRandomMRational (numMin, numMax, denMin, denMax)
createRandomMRational (numMin, numMax, denMin, denMax, nonzero)
Returns a number of type MRational
(Mathlet Factory type), thus, a fraction. The numerator is randomly chosen from the set {numMin, ..., numMax} resp. {numMin, ..., numMax}\{0}, the denominator is randomly chosen from the set {denMin, ..., denMax}\{0}. numMin, numMax, denMin, denMax must be integral numbers which fulfill the conditions numMin < numMax and denMin < denMax. Whether 0 is excluded for the numerator depends on the nonzero flag nonzero. Its allowed values, meaning, and default are the same as with the createRandomInt
method (see subsection 4.2). Forthe denominator, 0 is always excluded.
x = rand.createRandomMRational(1, 8, 2, 4);
y = rand.createRandomMRational(5, 6, 4, 4, NON_ZERO);
5. Storing values in the datasheet¶
The global predefined variable ppd
is a reference to a datasheet object containing the personalized data. To store a value in the datasheet under a certain path, the datasheet's put
method can be used. Its synopsis is as follows:
put (path, value)
value may be of almost any type, including numbers (both Groovy and Mathlet Factory), boolen, and string. (See the API documentation of the Java class net.mumie.srv.datasheet.Datasheet
for detailed information on the supported types. Note that within PPD scripts, the Mathlet Factory number types are supported, too, which is not the case with the normal Datasheet
class.)
Examples:
ppd.put("user/problem/x", 3);
ppd.put("user/problem/y", new MDouble(3.5));
ppd.put("user/problem/z", rand.createRandomMRational(1, 8, 2, 4));
p = rand.createRandomMInteger(2, 2, NON_ZERO);
ppd.put("user/problem/factor", p);
ppd.put("user/problem/strict", true);
ppd.put("user/problem/name", "Peter");
Instead of
ppd.put(path, value)
the syntax
ppd[path] = value
can be used. The above examples then become:
ppd["user/problem/y"] = new MDouble(3.5);
ppd["user/problem/z"] = rand.createRandomMRational(1, 8, 2, 4);
p = rand.createRandomMInteger(2, 2, NON_ZERO);
ppd["user/problem/factor"] = p;
ppd["user/problem/strict"] = true;
ppd["user/problem/name"] = "Peter";