
<h2>OEF的高级技巧</h2>

<h3>隐藏图形名称</h3>
如果你的练习需要识别随机选取的图形, 图形文件名就是一个重要的提示.
为了隐藏此文件名, 你可以写 in parts
<span class="tt wims_code_variable">statement</span>,
<span class="tt wims_code_variable">feedback</span>, etc

<pre>\img{\imagedir/picture.jpg alt="picture"}</pre>

这样学生在浏览器里看到的是

<pre>&lt;img src="a_random_unrelated_file_name" alt="picture"&gt;</pre>

真实文件名被隐藏了.

<p><b>注意</b>. 不要直接使用WIMS命令 <em>rename</em> 处理文件名,
否则练习将不能在被保存的环境里正常工作.

<h3>分步练习</h3>
分步练习可通过命令 <span class="tt">\steps</span> 定义. 举例来说, 如果你定义

<pre>\steps{choice 1, reply 1
choice 2, reply 2, reply 3
choice 3
}</pre>
<p>
此练习将分成3步, 第一步要求多重选择(choice 1)以及自由格式的回答(reply 1),
第2步是一个多重选择以及两个自由格式的回答的回答, 等等.
</p><p>
<span class="tt">\steps</span> 的内容接受(前面已定义的)参数以及条件定义,
正如对参数的定义一样. 这样就使得你可以选择性地展示回答栏(根据参数的随机变量),
甚至只含一步的情形也是如此.
</p><p>
请注意, 如果用户在前面的步骤里出了错, 以后的步骤就不出现了(可以认为全都错了).
</p><p>
在练习的陈述里, 当前的步数可通过变量 <span class="tt">\step</span> 获得,
此变量随着用户回答的进展而逐步取值 1,2,...
</p><p>
为了设计动态的分步练习(步数随用户的回答而发生变化),
你可以使用命令 <span class="tt">\nextstep{...}</span>. <span class="tt">\nextstep</span> 类似于 <span class="tt">\steps</span>,
但只有第一行是有效的. 它仅当其内容是由这样的变量给出时才能使用,
这个变量应该由 post-reply 的参数定义所改变.
当在某一步时 <span class="tt">\nextstep</span> 的内容变成空了, 练习就停止了.
</p><p>
在任何情形, 在一个OEF源码内, 最多只能出现一个 <span class="tt">\steps</span> 或
<span class="tt">\nextstep</span> 的声明.
</p>
<h3>条件分叉与循环</h3>

可用的命令:

<pre>
\if{条件}{if的内容}
\if{条件}{if的内容}{其它内容}
\ifval{条件}{if的内容}
\ifval{条件}{if的内容}{其它内容}
\for{var=n1 to n2}{循环内容}
\while{条件}{循环内容} (只用在主环境)
</pre>

这些命令(<span class="tt">while</span> 除外)可以被用于陈述(<span class="tt">statement</span>)、提示(<span class="tt">hint</span>)、解答(<span class="tt">solution</span>)或反馈(<span class="tt">feedback</span>)内,
或用于主环境里.
在最后一种情形, 条件执行只影响参数的定义.

<h3>预处理资源</h3>

本功能不能用于创建练习(createxo). 你可在模块工具(Modtool)下使用它来写OEF(及Deductio)练习.
<p>
它使你可以把源码的公共部分包含在几个oef文件里.
你也可以利用它从一个预资源批生成几个oef, 它们相互之间相差一些宏定义.
</p><p>
为使用这个功能, 应在 src 下建立一个子目录 cpp/.
预资源文件以 .cpp 作为后缀放入此子目录. 在这些文件里,
你可以加入 cpp 的指令如 <span class="tt">#include</span> 或 <span class="tt">#if</span>.
(请参看 cpp 手册或 c 的说明以了解语法详情.)
</p><p>
cpp文件的第一行应该定义一个目标表, 其格式为
</p>
<pre>
target=targ1 targ2 targ3 ...
</pre>
这行命令的意义是本cpp文件将生成 targ1.oef, targ2.oef, 等等.
(输出文件会自动添加后缀 .oef). 而且宏
<em>TARGET_targ1</em> 也被定义.
所以在cpp原文件里可以加入如下的行:
<pre>
#if define TARGET_targ1
 \title{练习1}
 \integer{v1=3}
 \text{t1=这是target 1}
#endif
#if define_TARGET_targ2
 \title{练习2}
 \integer{v1=5}
 \text{t1=这是target 2}
#endif
</pre>
使得生成的内容与目标有关.
<p>
文件名 (本例中是
<span class="tt wims_code_words">targ1</span>, ...)
保存在以下变量里
<span class="tt wims_code_words">OEFFILE</span>.
在以下例子里练习的标题是
<span class="tt wims_code_words">targ1</span>
</p>
<pre>
#if defined TARGET_targ1
 \title{OEFFILE}
 \integer{v1=3}
 \text{t1=dit is target 1}
#endif
</pre>

<p>
包含文件也应加上后缀 .inc 后放到 src/cpp 目录里. 命令行
</p>
<pre>
#include "common.inc"
</pre>
将把 common.inc 的内容插入生成的oef文件里.
请注意, 为了安全的原因, 禁止指明包含文件的目录.
<p>
特别提示; 如果你的cpp文件的文本里含有未关闭的单引号或双引号的话,
cpp会陷于混乱. 在这种情形,
你可以利用 c 的注解(<span class="tt">/* ... */</span>)把含有这样文本的命令保护起来.
</p>
<div class="wims_warning">
<span class="wims_warning">$wims_name_warning</span> : 在以 # 起首的命令,
如 <span class="tt">#include</span> 里, 字符 <span class="tt">#</span> 必须是这一行的第一个字符.
不可以把 <span class="tt">#</span> 用作注解字符.
</div>

<h3>练习环境</h3>
特殊变量 <span class="tt">\oefenv</span> 可用来测试练习的环境(如果在练习里没有对它重定义的话).
<p>
目前此变量能测试的内容只有
``debug''. 在以下情形里, debug将出现在 <span class="tt">\oefenv</span> 里:
</p>
<ol>
<li>当它在创建练习(createxo)内执行时.</li>
<li>当它在模块工具(modtool)内被测试时, 目的是为了开发.</li>
<li>当它是班级的练习, 而且被主持教师执行时.
</li>
</ol>
<p>
在这些情形, 许多类型的输入栏里都会显示正确的答案,
让你看到练习期望的结果是什么.
</p><p>
你可以用以下形式在练习里添加纠错信息
</p><pre>
\if{debug iswordof \oefenv}{欲添加的纠错信息}
</pre>
当练习被测试时, 这些信息会自动显示, 而且学生做作业时又自动隐藏.


