diff --git a/lib/VipsAssignment.php b/lib/VipsAssignment.php
index 55d4767b41b2926ad845ccde2b3c8b1213c328cc..52cc2a9d43a88485728117ebab3aa22013d19feb 100644
--- a/lib/VipsAssignment.php
+++ b/lib/VipsAssignment.php
@@ -171,12 +171,32 @@ class VipsAssignment extends SimpleORMap
         if ($test->notes) {
             $data['options']['notes'] = trim($test->notes);
         }
+
+        if ($test->limit['access-code']) {
+            $data['options']['access_code'] = (string) $test->limit['access-code'];
+        }
+        if ($test->limit['ip-ranges']) {
+            $data['options']['ip_range'] = (string) $test->limit['ip-ranges'];
+        }
         if ($test->limit['resets']) {
             $data['options']['resets'] = (int) $test->limit['resets'];
         }
         if ($test->limit['tries']) {
             $data['options']['max_tries'] = (int) $test->limit['tries'];
         }
+
+        if ($test->option['scoring-mode'] == 'negative_points') {
+            $data['options']['evaluation_mode'] = 1;
+        } else if ($test->option['scoring-mode'] == 'all_or_nothing') {
+            $data['options']['evaluation_mode'] = 2;
+        }
+        if ($test->option['shuffle-answers'] == 'true') {
+            $data['options']['shuffle_answers'] = 1;
+        }
+        if ($test->option['shuffle-exercises'] == 'true') {
+            $data['options']['shuffle_exercises'] = 1;
+        }
+
         if ($test['start']) {
             $data['start'] = date('Y-m-d H:i:s', strtotime($test['start']));
         }
diff --git a/schema/vips-test.rnc b/schema/vips-test.rnc
index 8956a0c62f6b5884ea6c8d3786191f4e205ccd76..38c2094fc8fcaea59655ec1514f69101f3c4e2a1 100644
--- a/schema/vips-test.rnc
+++ b/schema/vips-test.rnc
@@ -12,9 +12,16 @@ element test {
     element description { text }?,
     element notes { text }?,
     element limit {
+        attribute access-code { xsd:string }?,
+        attribute ip-ranges { xsd:string }?,
         attribute resets { xsd:integer }?,
         attribute tries { xsd:integer }?
     }?,
+    element option {
+        attribute scoring-mode { token }?,
+        attribute shuffle-answers { xsd:boolean }?,
+        attribute shuffle-exercises { xsd:boolean }?
+    }?,
     element exercises {
         element exercise {
             attribute id { xsd:ID },
diff --git a/schema/vips-test.xsd b/schema/vips-test.xsd
index de5630e04002818811a7802c35096891c697fbcf..0ce28bacaf3b08d3a1e2f08a5321334dde1fd57b 100644
--- a/schema/vips-test.xsd
+++ b/schema/vips-test.xsd
@@ -7,6 +7,7 @@
         <xs:element minOccurs="0" name="description" type="xs:string"/>
         <xs:element minOccurs="0" ref="ns1:notes"/>
         <xs:element minOccurs="0" ref="ns1:limit"/>
+        <xs:element minOccurs="0" ref="ns1:option"/>
         <xs:element ref="ns1:exercises"/>
         <xs:element minOccurs="0" ref="ns1:files"/>
       </xs:sequence>
@@ -30,10 +31,19 @@
   <xs:element name="notes" type="xs:string"/>
   <xs:element name="limit">
     <xs:complexType>
+      <xs:attribute name="access-code" type="xs:string"/>
+      <xs:attribute name="ip-ranges" type="xs:string"/>
       <xs:attribute name="resets" type="xs:integer"/>
       <xs:attribute name="tries" type="xs:integer"/>
     </xs:complexType>
   </xs:element>
+  <xs:element name="option">
+    <xs:complexType>
+      <xs:attribute name="scoring-mode" type="xs:token"/>
+      <xs:attribute name="shuffle-answers" type="xs:boolean"/>
+      <xs:attribute name="shuffle-exercises" type="xs:boolean"/>
+    </xs:complexType>
+  </xs:element>
   <xs:element name="exercises">
     <xs:complexType>
       <xs:sequence>
diff --git a/views/sheets/export_assignment.php b/views/sheets/export_assignment.php
index cce5b93c6b0019b9f58a49560f87f21d143bd003..159f0fcd248eebbf93b763202be4c0c40fd30dc2 100644
--- a/views/sheets/export_assignment.php
+++ b/views/sheets/export_assignment.php
@@ -23,13 +23,33 @@
             <?= vips_xml_encode($assignment->options['notes']) ?>
         </notes>
     <? endif ?>
-    <? if ($assignment->type === 'selftest'): ?>
-        <limit <? if ($assignment->options['resets'] === 0): ?>resets="0"<? endif ?>
-        <? if ($assignment->options['max_tries']): ?>
-            tries="<?= (int) $assignment->options['max_tries'] ?>"
-        <? endif ?>
-        />
+    <limit
+    <? if (isset($assignment->options['access_code'])): ?>
+        access-code="<?= vips_xml_encode($assignment->options['access_code']) ?>"
     <? endif ?>
+    <? if (isset($assignment->options['ip_range'])): ?>
+        ip-ranges="<?= vips_xml_encode($assignment->options['ip_range']) ?>"
+    <? endif ?>
+    <? if ($assignment->options['resets'] === 0): ?>
+        resets="0"
+    <? endif ?>
+    <? if ($assignment->options['max_tries']): ?>
+        tries="<?= (int) $assignment->options['max_tries'] ?>"
+    <? endif ?>
+    />
+    <option
+    <? if ($assignment->options['evaluation_mode'] == 1): ?>
+        scoring-mode="negative_points"
+    <? elseif ($assignment->options['evaluation_mode'] == 2): ?>
+        scoring-mode="all_or_nothing"
+    <? endif ?>
+    <? if ($assignment->isShuffled()): ?>
+        shuffle-answers="true"
+    <? endif ?>
+    <? if ($assignment->isExerciseShuffled()): ?>
+        shuffle-exercises="true"
+    <? endif ?>
+    />
     <exercises>
         <? foreach ($assignment->test->exercise_refs as $exercise_ref): ?>
             <?= $this->render_partial($exercise_ref->exercise->getXMLTemplate($assignment), ['points' => $exercise_ref->points]) ?>