diff --git a/.hgtags b/.hgtags
index 3a5c914309bfe0839cf7a19ebc925e50958d4f78..327db5e6db67baa145f2cbfc5c4959db4e1b84ba 100644
--- a/.hgtags
+++ b/.hgtags
@@ -210,3 +210,5 @@ dc92e2661668e9867d401d8f929c02a6a3f92314 OpenOLAT 12.2.3
 30e784886f4e1aa610acf5f850511adab8e3623e OpenOLAT 12.2.5
 97e8d87f2416ba6dd43d47164100c2b4ec577ab7 OpenOLAT 12.2.6
 4ceae571c62f6e2e2bc5711e7f445836c368bb71 OpenOLAT 12.2.7
+b600dc769f2f7b69b57bdea60591488d8e27ee7d OpenOLAT 12.2.8
+93154b0f3bb64433fde186ce8d8566f71cabc9ce OpenOLAT 12.3.0
diff --git a/pom.xml b/pom.xml
index 196ef867364eedc36b5af3d4445df8037158394e..fd0f7cce32aee74b8ba491f5ef10e22a817be59a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>org.openolat</groupId>
 	<artifactId>openolat-lms</artifactId>
-	<version>12.3-SNAPSHOT</version>
+	<version>12.4-SNAPSHOT</version>
 	<packaging>war</packaging>
 	<name>OpenOLAT LMS</name>
 	<url>http://www.openolat.org</url>
diff --git a/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java b/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java
index 136c8394fb38308ab22cb05a2ec5a9d6aaf1f5ad..e69b10220a36d6df1b51cd80e8ce97bad9454960 100644
--- a/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java
+++ b/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java
@@ -54,6 +54,7 @@ import org.olat.ims.qti.QTIResultSet;
 import org.olat.modules.assessment.Role;
 import org.olat.modules.assessment.model.AssessmentEntryStatus;
 
+import de.bps.onyx.plugin.OnyxModule;
 import de.bps.onyx.plugin.OnyxResultManager;
 
 /**
@@ -98,6 +99,11 @@ public class ReturnWSService {
 	public void saveResult(@WebParam(name = "uniqueId") String uniqueId, @WebParam(name = "resultFile") byte[] resultFile, @WebParam(name = "params") MapWrapper params)
 			throws Exception {
 		
+		if(!CoreSpringFactory.getImpl(OnyxModule.class).isEnabled()) {
+			log.warn("ReturnWSService unauthorized attempt, service disabled");
+			throw new RuntimeException("Onyx plugin disabled");
+		}
+		
 		File temp = null;
 		try {
 
@@ -292,6 +298,11 @@ public class ReturnWSService {
 
 	@WebMethod
 	public void saveResultLocal(@WebParam(name = "uniqueId") String uniqueId, @WebParam(name = "resultLocalFile") String resultLocalFile) {
+		if(!CoreSpringFactory.getImpl(OnyxModule.class).isEnabled()) {
+			log.warn("ReturnWSService unauthorized attempt, service disabled");
+			throw new RuntimeException("Onyx plugin disabled");
+		}
+		
 		QTIResultSet qtiResultSet = OnyxResultManager.getResultSet(Long.parseLong(uniqueId));
 
 		if (resultLocalFile == null) {
diff --git a/src/main/java/de/bps/onyx/plugin/wsserver/TraineeStatusService.java b/src/main/java/de/bps/onyx/plugin/wsserver/TraineeStatusService.java
index d85c9cc72ae754be5fced393a0281a16b1db7c3a..0e5c30aadb584aaf7e619bdfb456d4d88c4873fe 100644
--- a/src/main/java/de/bps/onyx/plugin/wsserver/TraineeStatusService.java
+++ b/src/main/java/de/bps/onyx/plugin/wsserver/TraineeStatusService.java
@@ -27,10 +27,12 @@ import javax.jws.WebParam;
 import javax.jws.WebService;
 import javax.jws.soap.SOAPBinding;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 
+import de.bps.onyx.plugin.OnyxModule;
 import de.bps.onyx.util.ExamPoolManager;
 
 @WebService(name = "TraineeStatusService", serviceName = "TraineeStatusService", targetNamespace = "http://test.plugin.bps.de/")
@@ -46,6 +48,11 @@ public class TraineeStatusService {
 	@WebMethod(operationName = "updateStatus")
 	public void updateStatus(@WebParam(name = "testSessionId") Long testSessionId, @WebParam(name = "studentIds") StudentIdsWrapper studentIds,
 			@WebParam(name = "status") Integer status) {
+		if(!CoreSpringFactory.getImpl(OnyxModule.class).isEnabled()) {
+			log.warn("TraineeStatusService unauthorized attempt, service disabled");
+			throw new RuntimeException("Onyx plugin disabled");
+		}
+		
 		TestState testState = TestState.getState(status);
 		log.info("updateStatus: " + testSessionId + " # " + studentIds + " # " + testState);
 
diff --git a/src/main/java/org/olat/admin/layout/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/admin/layout/_i18n/LocalStrings_fr.properties
index f72a7c0c14841cef688416d6ed168a0b569ec151..13c4a3f8e2e29c05edca3a8b4d55d3c55ac5ff71 100644
--- a/src/main/java/org/olat/admin/layout/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/admin/layout/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Sun Dec 14 17:23:30 CET 2014
+#Thu Feb 01 22:20:11 CET 2018
 CustomizingAdminController.menu.title=Personnaliser la mise-en-page
 CustomizingAdminController.menu.title.alt=T\u00E9l\u00E9charger un logo et changer le pied de page.
 LayoutAdminControllerWithPersist.menu.title=Mise-en-page
@@ -16,6 +16,8 @@ footerLine.description=Texte du pied de page (liens e-mail et adresses sont auto
 footerUrl.default=http\://www.frentix.com
 footerUrl.description=Entrer l'URL pour les clics sur le pied-de-page (en option)
 form.theme=Mise en page syst\u00E8me
+form.theme.forceReload=Forcer le rechargement de toutes les ressources statiques
+form.theme.forceReload.help=Le rechargement est uniquement n\u00E9cessaire si des modifications ont \u00E9t\u00E9 apport\u00E9es \u00E0 une mise en page qui a d\u00E9j\u00E0 \u00E9t\u00E9 t\u00E9l\u00E9charg\u00E9e.
 invitee=invit\u00E9(e)
 layout.intro=Par la suite, vous pouvez exp\u00E9rimenter avec les th\u00E8mes de mise en page mises \u00E0 disposition. Choisissez un sujet dans la liste pour l'utiliser. Pour activer les modifications d'affichage, vous devez vous d\u00E9connecter et vous reconnecter sur OLAT.
 layout.title=Mise en page
diff --git a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_fr.properties
index aca5c29802f377c43c0bec6bca9eea69a3e0c1a3..8f52021483d5d5b0c9660bc096572d3a6fadccf2 100644
--- a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_fr.properties
@@ -1,10 +1,10 @@
-#Tue Apr 15 21:59:54 CEST 2014
+#Thu Feb 01 22:21:50 CET 2018
 admin.menu.title=S\u00E9curit\u00E9
 admin.menu.title.alt=Modifier les param\u00E8tres de s\u00E9curit\u00E9
 sec.description=S\u00E9curit\u00E9
 sec.force.download=Forcer le t\u00E9l\u00E9chargement dans les dossiers
 sec.title=Param\u00E8tres de s\u00E9curit\u00E9
+sec.top.frame.explanation=En raison d'incompatibilit\u00E9s avec certains composants d'OpenOLAT (TinyMCE), il n'est pas possible d'int\u00E9grer OpenOLAT dans une frame.
 sec.topframe=Emp\u00EAcher l'int\u00E9gration dans les cadres/frames
 sec.wiki=Bloquer la resource de type wiki
-sec.top.frame.explanation=En raison d'incompatibilit\u00E9s avec certains composants d'OpenOLAT (TinyMCE), il n'est pas possible d'int\u00E9grer OpenOLAT dans une frame.
-
+sec.xframe.sameorigin=Interdire l'encadrant dans une frame avec l'en-t\u00EAte "X-FRAME-OPTIONS\=SAMEDOMAIN"
diff --git a/src/main/java/org/olat/admin/site/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/admin/site/ui/_i18n/LocalStrings_fr.properties
index 58589d008030092434bb136882092af0f5714373..fd13456fa05694a860fced8247cea49c3390a066 100644
--- a/src/main/java/org/olat/admin/site/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/admin/site/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Nov 16 20:28:37 CET 2017
+#Thu Feb 01 18:38:36 CET 2018
 AdminSiteDef=Administration
 CatalogAdminSiteDef=Administration du catalogue
 CatalogSiteDef=Catalogue
@@ -30,6 +30,7 @@ disabledSiteSecurityCallback=D\u00E9sactiv\u00E9
 down=En bas
 managersSiteSecurityCallback=Tous les administrateurs
 poolPrivateMembersSiteSecurityCallback=Membres et administrateurs de pools de questions
+poolTaxonomySiteSecurityCallback=Administrateurs banque de questions et comp\u00E9tences
 registredOrGuestSiteSecurityCallback=Utilisateurs enregistr\u00E9 et invit\u00E9s sans invitations portfolio
 registredSiteSecurityCallback=Utilisateurs enregistr\u00E9s sauf les invit\u00E9 / les invitations eP
 restrictToAuthorSiteSecurityCallback=Auteurs
diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_fr.properties
index e1b8f2d5ebbfe33f34f6d0b5efafd345bd4e3891..895ef1b5a48aa2a0a14cccbf9b6598b9ca809de1 100644
--- a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Nov 16 19:06:40 CET 2017
+#Thu Feb 01 18:31:22 CET 2018
 AssessmentManager=Outil d'\u00E9valuation
 Binder=ePortfolio 2.0
 BinderTemplate=Mod\u00E8le de portfolio 2.0
@@ -47,6 +47,7 @@ PFCourseNode=Dossier participant
 ReturnboxController=Dossier de restitution
 SolutionController=Solutions mod\u00E8les
 TaxonomyLibrary=Biblioth\u00E8que de taxonomie
+Templates=Mod\u00E8le
 User=Utilisateur
 WikiPage=Wiki
 ajax.show.on=[Ajax-Beta-Mode]
diff --git a/src/main/java/org/olat/core/commons/controllers/filechooser/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/commons/controllers/filechooser/_i18n/LocalStrings_fr.properties
index 6dbdc37a5939e187965e09205f98724b7696895e..b2a93ebdff46a96a92a5d81be9059e4873945137 100644
--- a/src/main/java/org/olat/core/commons/controllers/filechooser/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/core/commons/controllers/filechooser/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Feb 26 21:09:16 CET 2015
+#Thu Feb 01 18:19:42 CET 2018
 button.create=Cr\u00E9er
 calloutTrigerLink.select.site=Choisir une page
 calloutTriggerLink=Choisir, cr\u00E9er, t\u00E9l\u00E9charger un fichier
@@ -7,6 +7,7 @@ chooseLink=Choisir un fichier
 command.create=Cr\u00E9er une page et l'ouvrir dans l'\u00E9diteur
 command.edit=Ouvrir la page dans l'\u00E9diteur
 command.preview.label=Choisir un fichier
+command.remove=Enlever la page
 createLink=Cr\u00E9er un fichier
 error.deleted=Le fichier configur\u00E9 n'existe pas. Cr\u00E9er \u00E0 nouveau le fichier ou choisissez un autre fichier.
 error.name.empty=S'il vous pla\u00EEt entrez un nom de fichier
diff --git a/src/main/java/org/olat/core/commons/services/analytics/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/services/analytics/ui/_i18n/LocalStrings_de.properties
index 5224c875a21a1a8fd03af6029a3488e785712089..4a37012ef8f7bb4a057922d577a9eeb597f8f28f 100644
--- a/src/main/java/org/olat/core/commons/services/analytics/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/services/analytics/ui/_i18n/LocalStrings_de.properties
@@ -7,6 +7,6 @@ analytics.privacy=Wir weisen Sie darauf hin, dass Sie als Betreiberin der Plattf
 analytics.disabled=Analytics Module nicht verwenden
 analytics.service=Analytics Service
 
-analytics.google.title=Google Analytics Koniguration
+analytics.google.title=Google Analytics Konfiguration
 analytics.google.desc=Wenn Sie ein Google Analytics Konto besitzen können Sie hier die Google Tracking ID eingeben um detaillierte statistische und real-time Auswertungen über die Nutzung Ihrer OpenOLAT Installation zu erhalten. 
 analytics.google.tracking.id=Tracking ID
diff --git a/src/main/java/org/olat/core/commons/services/analytics/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/commons/services/analytics/ui/_i18n/LocalStrings_fr.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1d9492b58bc2ab2ee824eddf81b6c29208b4bbad
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/services/analytics/ui/_i18n/LocalStrings_fr.properties
@@ -0,0 +1,11 @@
+#Thu Feb 01 21:22:39 CET 2018
+admin.menu.title=Analyse d'audience
+admin.menu.title.alt=Analyse du comportement des utilisateurs
+analytics.desc=Choisissez un des services d'analyses optionnels pour confier l'\u00E9valuation du comportement des utilisateurs \u00E0 un service externe.
+analytics.disabled=Le module d'analyse d'audience est d\u00E9sactiv\u00E9.
+analytics.google.desc=Si vous poss\u00E9dez un compte Google Analytics, vous pouvez entrer ici votre Google Tracking ID pour g\u00E9n\u00E9rer et observer en temps r\u00E9el des statistiques d\u00E9taill\u00E9es sur la mani\u00E8re dont votre installation OpenOLAT est utilis\u00E9e.
+analytics.google.title=Configuration Google Analytics
+analytics.google.tracking.id=Tracking ID
+analytics.privacy=Nous vous rendons attentif au fait qu'en tant qu'op\u00E9rateur de la plateforme vous devez vous engag\u00E9 \u00E0 informer vos utilisateurs de l'emploi de services d'analyse d'audience.
+analytics.service=Service d'analyses
+analytics.title=Module d'analyse d'audience
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/_i18n/LocalStrings_fr.properties
index 80a582678cd31e2e1f0ffa1256f4063f9a5e2d0a..e9907cb59f605888ef0b94e8ad296c596acd67e5 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Wed Sep 14 18:05:16 CEST 2016
+#Thu Feb 01 18:31:27 CET 2018
 confirm.delete.file=Voulez-vous vraiment effacer ce fichier?
 confirm.delete.file.title=Effacer un fichier
 day.short.di=Mar
@@ -27,6 +27,7 @@ month.long.mar=Mars
 month.long.nov=Novembre
 month.long.oct=Octobre
 month.long.sep=Septembre
+selection.no.value=-
 text.element.error.maxvalue=valeur maximale autoris\u00E9e\: {0}.
 text.element.error.minvalue=valeur minimale autoris\u00E9e\: {0}.
 text.element.error.notlongerthan=max. {0} signes autoris\u00E9s.
diff --git a/src/main/java/org/olat/core/util/i18n/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/util/i18n/ui/_i18n/LocalStrings_fr.properties
index 8bb1f8b2c6bae191824ff6f9dd1fcfe09cec61b6..358a94faebc35870b6cc855e9218bc616153b261 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/core/util/i18n/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Sat Oct 26 20:39:05 CEST 2013
+#Thu Feb 01 18:32:11 CET 2018
 cache.disabled=La m\u00E9moire cache de traduction n'est pas activ\u00E9. Ce r\u00E9glage doit \u00EAtre effectu\u00E9 dans le fichier olat.properties . Nous recommandons d'activer la m\u00E9moire cache.
 cache.flush=Effacer m\u00E9moire cache
 cache.flush.ok=La m\u00E9moire cache a \u00E9t\u00E9 vid\u00E9e.
@@ -83,6 +83,7 @@ edit.crumb.link=Cl\u00E9 de traduction
 edit.customize.crumb.hoover=Formulaire pour la traduction d'une cl\u00E9 de traduction
 edit.customize.intro=Copiez ce terme depuis la langue vers l'adaptation et modifiez le terme selon vos souhaits. Vous pouvez \u00E9galement sauter le terme et l'adapter plus t\u00E2rd. Affichez la langue de comparaison, pour v\u00E9rifier vos modifications dans une autre langue.
 edit.customize.target.hover=Cliquez dans le champ d'entr\u00E9e pour adapter cette cl\u00E9.
+edit.error.invalid.item=La traduction n'est pas valide\: {0}
 edit.error.noitem=Aucune cl\u00E9 de traduction n'a \u00E9t\u00E9 trouv\u00E9e. Retournez \u00E0 l'aper\u00E7u et r\u00E9essayez.
 edit.intro=Traduisez le terme depuis la langue de r\u00E9f\u00E9rence dans la langue cible. Vous pouvez aussi sauter le terme et traduire plus tard. Afficher la langue de comparaison pour v\u00E9rifier votre traduction dans une autre langue.
 edit.progressBar.unitLabel=Cl\u00E9 de traduction
diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties
index fe159d3a2ef9ad104283153804b86226d25f4371..16133e4503f5b8896d0d2632d8539a136021751f 100644
--- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties
@@ -1,6 +1,7 @@
-#Thu Nov 16 16:54:08 CET 2017
+#Thu Feb 01 18:31:51 CET 2018
 add.email=Ajouter
 contact.cp.from=Copie \u00E0 l'exp\u00E9diteur
+error.too.long=Le mod\u00E8le est trop grand. La taille maximale est {0}\!
 footer.no.userdata=<p>Ce message a \u00E9t\u00E9 envoy\u00E9 automatiquement via la plateforme d'apprentissage OpenOLAT\: {0}</p>
 footer.with.userdata=<p>Exp\u00E9diteur\: {2} {3} ({0}), {4} {5}</p><p>Ce message a \u00E9t\u00E9 envoy\u00E9 via la plateforme d'apprentissage OpenOLAT\: {1}</p>
 mail.action.emtpy=S\u00E9lectionnez au moins une adresse e-mail pour d\u00E9clencher un effet.
diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties
index ba0d9054ac59ac49b44eb2616d11c4be9f74778e..606435ac57e548d578c8b92ca34d51466e6bd58e 100644
--- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Jun 08 21:24:36 CEST 2017
+#Thu Feb 01 18:33:31 CET 2018
 checklist=Listes de contr\u00F4le
 cl=Listes de contr\u00F4le
 cmd.download=T\u00E9l\u00E9charger
@@ -81,6 +81,7 @@ menu.scorm.alt=R\u00E9sultats SCORM
 menu.wikis=Wikis
 menu.wikis.alt=Archiver Wikis
 nodechoose.config.error=Choisissez s'il vous pla\u00EEt au moins une option.
+nodechoose.intro.checklist=S\u00E9lectionner un \u00E9l\u00E9ment de cours pour archiver les r\u00E9sultats des listes de contr\u00F4les.
 nodechoose.intro.cl=S\u00E9lectionnez avec le dialogue suivant l'\u00E9l\u00E9ment de cours liste de contr\u00F4le que vous souhaitez \u00E9valuer.
 nodechoose.intro.config=L'archive contient\: tous les utilisateurs et toutes les questions. Modifier les options de t\u00E9l\u00E9chargement avec le bouton ci-dessus.
 nodechoose.intro.dialog=S\u00E9lectionnez un \u00E9l\u00E9ment de cours pour archiver ses discussions de fichiers.
diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_fr.properties
index f5a95e73dd7337121b992f848600cf560fa468ea..3af226a6afb6bf67de966391e85df56e9f90b999 100644
--- a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,6 @@
-#Thu Jun 08 21:28:13 CEST 2017
+#Fri Feb 02 08:43:36 CET 2018
+assessment.mode.now=Le mode d'\u00E9valuation est actif.
+assessment.modes.overview=Mode d'\u00E9valuation
 assessment.status.done=$org.olat.modules.assessment.ui\:assessment.status.done
 assessment.status.inProgress=$org.olat.modules.assessment.ui\:assessment.status.inProgress
 assessment.status.inReview=$org.olat.modules.assessment.ui\:assessment.status.inReview
@@ -41,11 +43,14 @@ overview=Aper\u00E7u
 participantgroups.title=Participant des groupes
 previous=Retour
 reopen=$org.olat.modules.assessment.ui\:reopen
+reset.attempts=R\u00E9initialiser le nombre de tentatives
+reset.attempts.explanation=Ce test a \u00E9t\u00E9 termin\u00E9. Vous pouvez r\u00E9initialiser le nombre de tentatives. Le participant au test recommencera le test depuis le d\u00E9but. Exception faite si vous avez r\u00E9ouvert le test avec la fonction "R\u00E9ouvrir un test d\u00E9j\u00E0 termin\u00E9". Dans ce cas, l'utilisateur pourra reprendre l\u00E0 o\u00F9 il s'est arr\u00EAt\u00E9.<br>Le nombre de tentatives sera mis \u00E0 z\u00E9ro. Les donn\u00E9es de tentatives pr\u00E9c\u00E9dentes resteront sauv\u00E9es de mani\u00E8re ind\u00E9pendantes des nouvelles tentatives.
 save.done=$org.olat.modules.assessment.ui\:save.done
 statistics.small.overview=$org.olat.modules.assessment.ui\:statistics.small.overview
 sub.details=D\u00E9tails
 table.entries=Entr\u00E9es
 table.header.assessmentStatus=$org.olat.modules.assessment.ui\:table.header.assessmentStatus
+table.header.completion=$org.olat.modules.assessment.ui\:table.header.completion
 table.header.description=Description
 table.header.elements.toReview=El\u00E9ment
 table.header.group.name=Noms
@@ -63,6 +68,12 @@ table.header.tools=$org.olat.modules.assessment.ui\:table.header.tools
 table.header.userVisibility=<i class\='o_icon o_icon-fw o_icon_results_hidden'> </i>
 title.infocoach=Informations sur l'\u00E9valuation
 tool.correction=Corriger
+tool.details=Montrer les d\u00E9tails / \u00E9valuer
+tool.reopen=R\u00E9ouvrir l'\u00E9valuation
+tool.reset.attempts=R\u00E9initialiser le nombre de tentatives
+tool.set.done=Mettre le status "clos"
+tool.set.not.visible=Rendre les r\u00E9sultats non visibles
+tool.set.visible=Rendre les r\u00E9sultats visibles
 tooltip.of={0} \u00E0 {1}
 user.visibility=R\u00E9sultats
 user.visibility.hidden=pas encore visible pour les utilisateurs
diff --git a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java
index 748088e412c573a7a332ab6ca0ccc227efc16652..39f4d5c76bbb07a3f563ba7d5b0bce38a7b6baf7 100644
--- a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java
+++ b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java
@@ -37,6 +37,7 @@ public class CourseAccessAndProperties {
 	private boolean canCopy;
 	private boolean canReference;
 	private boolean canDownload;	
+	private Boolean confirmationEmail;
 	
 	private List<OfferAccess> offerAccess;
 	private List<OfferAccess> deletedOfferAccess;
@@ -127,4 +128,12 @@ public class CourseAccessAndProperties {
 	public void setCanDownload(boolean canDownload) {
 		this.canDownload = canDownload;
 	}
+
+	public Boolean getConfirmationEmail() {
+		return confirmationEmail;
+	}
+
+	public void setConfirmationEmail(Boolean confirmationEmail) {
+		this.confirmationEmail = confirmationEmail;
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/editor/PublishProcess.java b/src/main/java/org/olat/course/editor/PublishProcess.java
index 0b59b5c73ec586317f8e6f6853630fac2068feb1..6446b40e37c282a3c81e95273330403b32560331 100644
--- a/src/main/java/org/olat/course/editor/PublishProcess.java
+++ b/src/main/java/org/olat/course/editor/PublishProcess.java
@@ -80,6 +80,7 @@ import org.olat.repository.controllers.EntryChangedEvent;
 import org.olat.repository.controllers.EntryChangedEvent.Change;
 import org.olat.repository.manager.CatalogManager;
 import org.olat.resource.accesscontrol.ACService;
+import org.olat.resource.accesscontrol.Offer;
 import org.olat.resource.accesscontrol.OfferAccess;
 import org.olat.resource.references.Reference;
 import org.olat.resource.references.ReferenceManager;
@@ -700,7 +701,7 @@ public class PublishProcess {
 		return publishTreeModel;
 	}
 
-	public void changeGeneralAccess(Identity author, int access, boolean membersOnly){
+	public void changeGeneralAccess(Identity author, int access, boolean membersOnly) {
 		RepositoryManager.getInstance().setAccess(repositoryEntry, access, membersOnly);
 		MultiUserEvent modifiedEvent = new EntryChangedEvent(repositoryEntry, author, Change.modifiedAtPublish, "publish");
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(modifiedEvent, repositoryEntry);
@@ -718,6 +719,16 @@ public class PublishProcess {
 		// 1: add new and update existing offerings
 		ACService acService = CoreSpringFactory.getImpl(ACService.class);
 		for (OfferAccess newLink : offerAccess) {
+			if(accessAndProps.getConfirmationEmail() != null) {
+				Offer offer = newLink.getOffer();
+				boolean confirmation = accessAndProps.getConfirmationEmail().booleanValue();
+				if(offer.isConfirmationEmail() != confirmation) {
+					offer.setConfirmationEmail(confirmation);
+					if(offer.getKey() != null) {
+						offer = acService.save(offer);
+					}
+				}
+			}
 			acService.saveOfferAccess(newLink);
 		}
 		// 2: remove offerings not available anymore
@@ -777,6 +788,7 @@ public class PublishProcess {
 			this.skippableNodes = new ArrayList<CourseEditorTreeNode>();
 		}
 
+		@Override
 		public void visit(INode node) {
 			/*
 			 * DO NOT add or delete nodes via editorTreeModel, .....................
@@ -787,10 +799,10 @@ public class PublishProcess {
         // root node changed and published
         CourseNode clone = (CourseNode)XStreamHelper.xstreamClone(cetn.getCourseNode());
         resultingCourseRun.setRootNode(clone);
-        editorModelModifiedNodes.add(cetn);// TODO:pb: Review	Change to fic OLAT-1644
+        editorModelModifiedNodes.add(cetn);
         return;
 			}
-      if (cetn == root) { // TODO:pb: Review Change to fix OLAT-1644
+      if (cetn == root) {
       	// root node
         CourseNode clone = (CourseNode)XStreamHelper.xstreamClone(cetn.getCourseNode());
         resultingCourseRun.setRootNode(clone);
@@ -818,7 +830,6 @@ public class PublishProcess {
 					// already published, add it as it is. Silent "re-publish"
 					addNodeTo(resultingCourseRun, cetn);
         } else {
-          // TODO:pb:REVIEW Change to fix OLAT-1644
         	// changed in edit but not published => take old from existingRun
         	addNodeTo(resultingCourseRun, existingRun.getNode(cetn.getIdent()), cetn);
         }
@@ -908,7 +919,6 @@ public class PublishProcess {
 			parentClone.addChild(clone);
 		}
 
-    //	 TODO:pb:REVIEW Change to fix OLAT-1644
 		/**
 		 * @param newRunStruct
 		 * @param cetn
@@ -926,19 +936,15 @@ public class PublishProcess {
 		/**
 		 * flat list of all CourseEditorTreeNodes starting from root
 		 * 
-		 * @param root
+		 * @param treeNode
 		 * @param rootNodeWithSubtree
 		 */
-		private void collectSubTreeNodesStartingFrom(CourseEditorTreeNode root, List<CourseEditorTreeNode> rootNodeWithSubtree) {
-			for (int i = 0; i < root.getChildCount(); i++) {
-				CourseEditorTreeNode node = (CourseEditorTreeNode)root.getChildAt(i);
+		private void collectSubTreeNodesStartingFrom(CourseEditorTreeNode treeNode, List<CourseEditorTreeNode> rootNodeWithSubtree) {
+			for (int i = 0; i < treeNode.getChildCount(); i++) {
+				CourseEditorTreeNode node = (CourseEditorTreeNode)treeNode.getChildAt(i);
 				rootNodeWithSubtree.add(node);
 				collectSubTreeNodesStartingFrom(node, rootNodeWithSubtree);
 			}
 		}
 	}// end nested class
-
-
-	
-	
 }
diff --git a/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java b/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java
index 5f92779af49c5e841f17edeea65cf98819bf1239..71014ca9b89b27cfb8c3bfba3ffca37950fc214d 100644
--- a/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java
+++ b/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java
@@ -28,6 +28,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.SelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.impl.Form;
@@ -82,6 +83,8 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 			RepositoryEntryAllowToLeaveOptions.never.name()
 		};
 	
+	private static final String[] onKeys = new String[] { "on" };
+	
 	private SingleSelection leaveEl;
 	
 	private RepositoryEntry entry;
@@ -104,7 +107,7 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 	private static final String MEMBERSONLY_KEY = "m";
 	private String[] publishedKeys;
 	
-	
+	private MultipleSelectionElement confirmationEmailEl;
 	private List<FormLink> addMethods = new ArrayList<>();
 	private List<OfferAccess> offerAccess = new ArrayList<>();
 	private List<OfferAccess> deletedOfferAccess = new ArrayList<>();
@@ -171,6 +174,11 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 		
 		accessProperties.setOfferAccess(offerAccess);
 		accessProperties.setDeletedOfferAccess(deletedOfferAccess);
+		if(confirmationEmailEl.isVisible()) {
+			accessProperties.setConfirmationEmail(confirmationEmailEl.isAtLeastSelected(1));
+		} else {
+			accessProperties.setConfirmationEmail(null);
+		}
 					
 		addToRunContext("accessAndProperties", accessProperties);	
 		
@@ -310,12 +318,25 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 			accessLayout.contextPut("methods", addMethods);
 		}
 		
+		String[] onValues = new String[] { "" };
+		confirmationEmailEl = uifactory.addCheckboxesHorizontal("confirmation.email", accessLayout, onKeys, onValues);
+		confirmationEmailEl.addActionListener(FormEvent.ONCHANGE);
+		confirmationEmailEl.setVisible(false);
+
 		String confPage = velocity_root + "/configuration_list.html";
 		confControllerContainer = FormLayoutContainer.createCustomFormLayout("conf-controllers", getTranslator(), confPage);
 		accessLayout.add(confControllerContainer);
 		
 		loadConfigurations();
 		
+		boolean confirmationEmail = false;
+		for(AccessInfo info:confControllers) {
+			confirmationEmail |= info.getLink().getOffer().isConfirmationEmail();
+		}
+		if(confirmationEmail) {
+			confirmationEmailEl.select(onKeys[0], true);
+		}
+		
 		confControllerContainer.contextPut("confControllers", confControllers);
 		
 		confControllerContainer.contextPut("emptyConfigGrantsFullAccess", Boolean.valueOf(emptyConfigGrantsFullAccess));		
@@ -351,6 +372,14 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 			delLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item");
 			confControllerContainer.add(delLink.getName(), delLink);
 		}
+		updateConfirmationEmail();
+	}
+	
+	private void updateConfirmationEmail() {
+		if(confirmationEmailEl.isVisible() != !confControllers.isEmpty()) {
+			confirmationEmailEl.setVisible(!confControllers.isEmpty());
+			accessLayout.setDirty(true);
+		}
 	}
 	
 	public class AccessInfo {
@@ -504,6 +533,12 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 		} else if(addMethods.contains(source)) {
 			AccessMethod method = (AccessMethod)source.getUserObject();
 			addMethod(ureq, method);
+		} else if(confirmationEmailEl == source) {
+			for(AccessInfo info:confControllers) {
+				if(!offerAccess.contains(info.getLink())) {
+					offerAccess.add(info.getLink());
+				}
+			}
 		} else if (source instanceof FormLink) {
 			FormLink button = (FormLink)source;
 			String cmd = button.getCmd();
@@ -515,6 +550,7 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 					deletedOfferAccess.add(deleteOffer);			
 				}
 				confControllers.remove(infos);
+				updateConfirmationEmail();
 				fireEvent(ureq, Event.CHANGED_EVENT);
 			} else if("edit".equals(cmd)) {
 				AccessInfo infos = (AccessInfo)source.getUserObject();
diff --git a/src/main/java/org/olat/course/editor/_content/access_configuration.html b/src/main/java/org/olat/course/editor/_content/access_configuration.html
index 0047566062bd6fad59505d6ed0513823ae76a52a..e530afecc3a5027d9e48c322bb1a87186aaa6bae 100644
--- a/src/main/java/org/olat/course/editor/_content/access_configuration.html
+++ b/src/main/java/org/olat/course/editor/_content/access_configuration.html
@@ -12,6 +12,12 @@
 		#if ($off_info) <div class="o_info">$off_info</div> #end
 	</div></div>
 #end
+	#if($r.visible("confirmation.email"))
+	<div class="form-group">
+		<label class="control-label col-sm-3">$r.translate("confirmation.email")</label>
+		<div class="col-sm-9">$r.render("confirmation.email")</div>
+	</div>
+	#end
 	<div class="form-group">
 		<label class="control-label col-sm-3">$r.translate("ac.methods.label") $r.render("acMethodsLabelHelp")</label>
 		<div class="col-sm-9">$r.render("conf-controllers")</div>
diff --git a/src/main/java/org/olat/course/groupsandrights/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/groupsandrights/_i18n/LocalStrings_fr.properties
index 18a213153129e25f0a8ea3c8216a254893b7ed81..98c2545654f9a0d6d45979c7f694565e3c42ce75 100644
--- a/src/main/java/org/olat/course/groupsandrights/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/groupsandrights/_i18n/LocalStrings_fr.properties
@@ -1,26 +1,20 @@
-#Sat Jun 06 12:03:17 CEST 2015
+#Thu Feb 01 18:35:11 CET 2018
 add.all=Ajouter toutes les permissions
 bgr.archive=Archivage des donn\u00E9es
 bgr.assess=Outil d'\u00E9valuation
+bgr.assessmode=Mode d'\u00E9valuation
 bgr.dbs=Base de donn\u00E9e du cours
 bgr.editor=Editeur de cours
 bgr.glossary=Outil glossaire
 bgr.groupmngt=Gestion de groupes
 bgr.membermngt=Gestion des membres
 bgr.statistics=Statistiques
-
-
-
-
-
-
-
-
-
 menu.rights=Permissions
 noRestriction=Aucune restriction
 participant=Participants
 remove.all=Effacer toutes les permissions
+repo.participant=Participant du cours
+repo.tutor=Coach du cours
 table.header.groups=Groupe
 table.header.remove=Effacer
 table.header.role=R\u00F4les
diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties
index b4e906e64aa31ffab93792048bef03764b7bba37..8a61a79d76e83e3976e52889e8437dd42f441fba 100644
--- a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Tue Dec 16 09:04:07 CET 2014
+#Tue Feb 06 08:33:13 CET 2018
 add.checkbox=Add checkbox
 assessment=Assessment
 assessment.checkbox.description=Edit per Checkbox\: Apply the checkbox filter to edit the same checkbox across all participants.
@@ -19,6 +19,7 @@ column.header.homepage=Home page
 column.header.node.passed=Passed course element
 column.header.node.points=Score course element
 column.header.points=$\:box.points
+column.header.seqnum=Sequence number
 comment.nocomment=$org.olat.course.nodes.ms\:comment.nocomment
 comment.title=$org.olat.course.nodes.ms\:comment.title
 condition.accessibility.title=Access
@@ -49,10 +50,10 @@ down=Down
 edit.checkbox=Edit checkbox
 file=File
 filter.all=Show all
-form.individual.assessment.docs=$org.olat.course.nodes.ms\:form.individual.assessment.docs
 form.error.date=A date must be indicated.
 form.error.scoreOutOfRange=$org.olat.course.assessment\:form.error.scoreOutOfRange
 form.error.wrongFloat=$org.olat.course.nodes.ms\:form.error.wrongFloat
+form.individual.assessment.docs=$org.olat.course.nodes.ms\:form.individual.assessment.docs
 info.title=$org.olat.course.nodes.ms\:info.title
 label=Label
 label.achieved=Achieved
diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties
index ba3aeee3911c408f20526a78ce8165e6d9445973..ce13b9ffb40af650a7643cf3fcb43933eacd9dbe 100644
--- a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Jun 08 20:30:59 CEST 2017
+#Thu Feb 01 22:07:04 CET 2018
 add.checkbox=Ajouter une case \u00E0 cocher
 assessment=Evaluation
 assessment.checkbox.description=Modifier en fonction de la case \u00E0 cocher\: modifier la case \u00E0 cocher s\u00E9lectionner gr\u00E2ce au filtre de tous les participants.
@@ -19,6 +19,7 @@ column.header.homepage=Page d'accueil
 column.header.node.passed=Element de cours r\u00E9ussi
 column.header.node.points=Points \u00E9l\u00E9ment de cours
 column.header.points=$\:box.points
+column.header.seqnum=Num\u00E9ro
 comment.nocomment=$org.olat.course.nodes.ms\:comment.nocomment
 comment.title=$org.olat.course.nodes.ms\:comment.title
 condition.accessibility.title=Acc\u00E8s
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties
index b842bd7174c98a9339eb74096d7e76eeaf82c37f..076a5029320b00182806646f2a5eae48249f08c4 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties
@@ -20,7 +20,7 @@ choosed.areas=Lernbereich
 choosed.groups=Gruppe
 coach.assessment=Bewerten
 coach.back.to.submission=Abgabe erneut \u00F6ffnen
-coach.back.to.submission.confirm.text=Sind Sie sicher dass Sie die Abgabe f\u00FCr "{0}" nochmals \u00F6ffnen m\u00F6chten?
+coach.back.to.submission.confirm.text=Sind Sie sicher dass Sie die Abgabe f\u00FCr "{0}" nochmals \u00F6ffnen m\u00F6chten? Es werden dabei <strong>alle bereits eingereichten Dokumente</strong> gelöscht. Trotzdem weiterfahren?
 coach.back.to.submission.confirm.title=Abgabe erneut \u00F6ffnen
 coach.back.to.submission.desc=Hat der Teilnehmer versehentlich die endg\u00FCltige Abgabe ausgel\u00F6st, so kann mit dieser Aktion der Status auf "nicht abgegeben" zur\u00FCckgesetzt werden.
 coach.close.revision.button=Revision akzeptieren
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties
index deffbd7ccb857dad7f81fe0e1f89352896c88f99..8ae8cc57914fc80d73a417e4894e4d90758987da 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties
@@ -20,7 +20,7 @@ choosed.areas=Areas
 choosed.groups=Groups
 coach.assessment=Grade
 coach.back.to.submission=Reopen submission
-coach.back.to.submission.confirm.text=Are you sure you wish to re-open the task submission for "{0}"?
+coach.back.to.submission.confirm.text=Are you sure you wish to re-open the task submission for "{0}"? It will <strong>delete all submitted documents</strong>.
 coach.back.to.submission.confirm.title=Reopen submission
 coach.back.to.submission.desc=This action allows you to reset the submission status if a participant has submitted by accident.
 coach.close.revision.button=Accept revision
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties
index 5e3a955559751b351c84117ed59dbd6c58d20bcd..2de55d638f9c177ada7b5af5cc62b3c47af070dd 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties
@@ -20,7 +20,7 @@ choosed.areas=Domaines d'\u00E9tudes
 choosed.groups=Groupes
 coach.assessment=Evaluer
 coach.back.to.submission=R\u00E9ouvrir la soumission
-coach.back.to.submission.confirm.text=Etes-vous s\u00FBr de rouvrirez la soumission du devoir pour "{0}"?
+coach.back.to.submission.confirm.text=Etes-vous s\u00FBr de rouvrirez la soumission du devoir pour "{0}"? Tous les documents déjà téléchargés seront <strong>effacés</strong>.
 coach.back.to.submission.confirm.title=R\u00E9ouvrir le d\u00E9p\u00F4t
 coach.back.to.submission.desc=Cette action permet d'annuler le d\u00E9p\u00F4t d'un devoir qu'un participant aurait involontairement rendu.
 coach.close.revision.button=Terminer le processus de r\u00E9vision
diff --git a/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
index d6b0534c3b1487ccb47f0e09f10662ba961d8485..b46cea2ceeb8a3e77d5ef347ef31e51dcfbbbd45 100644
--- a/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
@@ -42,7 +42,9 @@ import org.olat.core.gui.control.generic.iframe.IFrameDisplayController;
 import org.olat.core.gui.media.MediaResource;
 import org.olat.core.gui.media.NotFoundMediaResource;
 import org.olat.core.gui.translator.Translator;
+import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.UserConstants;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.Formatter;
 import org.olat.core.util.StringHelper;
@@ -785,7 +787,8 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 			CourseEnvironment courseEnv, CourseNode courseNode, RepositoryEntry testEntry, Date timestamp, Locale locale)  {
 		MailBundle bundle = new MailBundle();
 		bundle.setToId(candidateSession.getIdentity());
-		String fullname = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(candidateSession.getIdentity());
+		Identity assessedIdentity = candidateSession.getIdentity();
+		String fullname = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(assessedIdentity);
 		Date assessedDate = candidateSession.getFinishTime() == null ? timestamp : candidateSession.getFinishTime();
 
 		String[] args = new String[] {
@@ -796,7 +799,12 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 				testEntry.getDisplayname(),						// {4}
 				fullname,										// {5}
 				Formatter.getInstance(locale)
-					.formatDateAndTime(assessedDate) 			// {6}
+					.formatDateAndTime(assessedDate), 			// {6}
+				assessedIdentity.getName(),											// {7}
+				assessedIdentity.getUser()
+					.getProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, locale),	// {8}
+				assessedIdentity.getUser()
+					.getProperty(UserConstants.INSTITUTIONALNAME, locale),			// {9}
 		};
 
 		Translator translator = Util.createPackageTranslator(QTI21AssessmentRunController.class, locale);
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
index 0a8e8e7f86489c13239170d6b2803ea30766c634..74d209896ebe2d1b637360aaa47f755824b4833e 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
@@ -1,11 +1,13 @@
-#Thu Dec 07 19:14:06 CET 2017
-allowRelativeLinks=Allow links in the entire storage folder.
+#Tue Feb 06 08:34:50 CET 2018
 Intro.self=Press the start button to begin with your self-test.
 Intro.surv=Press the start button to begin with your questionnaire.
 Intro.test=Press the start button to begin with your test.
+allowRelativeLinks=Allow links in the entire storage folder.
 assessment.documents.title=Assessment documents
 attempts.nomoreattempts=There are no more attempts at your disposal.
 attempts.yourattempts=Number of attempts
+block.dates.start=You will be able to start the test at <strong>{0}</strong>.
+block.dates.start.end=The test can be started between the <strong>{0}</strong> and the <strong>{1}</strong>.
 button.export=Export results
 button.stats=$org.olat.ims.qti.statistics.ui\:menu.title
 changelog.title=Resource change log
@@ -181,10 +183,11 @@ table.header.extra.time=Extra
 table.header.lastModified=Last modified
 table.header.results=Results
 time.limit.max=Time limit
+time.limit.test.explain=The test takes a maximum of <strong>{0}</strong>.
 tool.delete.data=Reset all data
 tool.extra.time=Extend test time
 tool.pull=Pull running test
-warning.assessment.mode=Test in process:
+warning.assessment.mode=Test in process\:
 warning.assessment.mode.date={0} from {1} til {2}
 warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
 warning.users.extra.time=You need to select a least one user which test can be prolonged.
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_fr.properties
index 8e1da36c37156d2fe36363a5f8da91ef7b06fc88..e0f18af4d5fef780c3bea83d8d943c8b22c0ad64 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_fr.properties
@@ -1,11 +1,15 @@
-#Thu Jul 06 20:47:43 CEST 2017
-allowRelativeLinks=Permettre la cr\u00E9ation de liens dans tout le dossier de stockage
+#Fri Feb 02 08:45:52 CET 2018
 Intro.self=Pressez sur D\u00E9marrer pour commencer l'auto-test.
 Intro.surv=Pressez sur D\u00E9marrer pour commencer avec le questionnaire. 
 Intro.test=Pressez sur D\u00E9marrer pour commencer le test. 
+allowRelativeLinks=Permettre la cr\u00E9ation de liens dans tout le dossier de stockage
 assessment.documents.title=Documents d'\u00E9valuation
 attempts.nomoreattempts=Vous n'avez plus d'autres essais 
 attempts.yourattempts=Nombre d'essais effectu\u00E9es 
+block.dates.start=Vous pourrez d\u00E9marrer le test le <strong>{0}</strong>
+block.dates.start.end=Le test pourra \u00EAtre commencer entre le <strong>{0}</strong> et le <strong>{1}</strong>.
+button.export=Exporter les r\u00E9sultats
+button.stats=$org.olat.ims.qti.statistics.ui\:menu.title
 changelog.title=Historique des modifications de la ressource
 choosenfile.self=Auto-test
 choosenfile.surv=Questionnaire 
@@ -47,6 +51,7 @@ error.assessment.pulled=Le test a \u00E9t\u00E9 retir\u00E9 par votre coach.
 error.assessment.stopped=Le test est termin\u00E9.
 error.begin.after.end=La date de d\u00E9but doit se trouver avant la date de fin.
 error.entry.locked=La ressource d'\u00E9tude choisie est actuellement \u00E9dit\u00E9e par un utilisateur. Veuillez choisir une autre ressource d'\u00E9tude SVP.
+error.reopean.failed=Le test n'a pas pu \u00EAtre r\u00E9ouvert.
 error.resource.corrupted=L'object didactique n'a pas pu \u00EAtre lu. Il semble soit corrompu soit au mauvais format.
 error.self.undefined.long=Aucun auto-test d\u00E9fini pour "{0}". Choisissez dans "Configuration auto-test".
 error.self.undefined.short=Aucun auto-test d\u00E9fini pour "{0}".
@@ -54,6 +59,10 @@ error.surv.undefined.long=Aucun questionnaire d\u00E9fini pour "{0}". Choisissez
 error.surv.undefined.short=Aucun questionnaire d\u00E9fini pour "{0}".
 error.test.undefined.long=Aucun test d\u00E9fini pour "{0}". Choisissez dans "Configurez test".
 error.test.undefined.short=Aucun test d\u00E9fini pour "{0}".
+extra.time=Prolonger
+extra.time.explain.1=Prolonger le temps pour l'utilisateur "{0}" de
+extra.time.explain.2=minutes.
+extra.time.warning=<strong>Attention\:</strong> la p\u00E9riode du mode d'\u00E9valuation ne sera pas prolong\u00E9e. Le mode d'\u00E9valuation doit \u00EAtre prolonger dans le menu "Mode d'\u00E9valuation".
 fieldset.allowRelativeLinksForm=Param\u00E8tres de s\u00E9curit\u00E9
 fieldset.chosecreateeditfile=Texte informatif (page html)
 file.name=Fichier choisi
@@ -135,7 +144,13 @@ qti.form.summary.responses=R\u00E9ponse, soumise par le participant
 qti.form.summary.section=R\u00E9sum\u00E9 de section (sans solutions)
 qti.form.summary.sections=R\u00E9sum\u00E9 section
 qti.form.summary.solutions=Solution
+qti.form.test.date=D\u00E9finir une p\u00E9riode de test
+qti.form.test.date.confirm=Le test peut \u00EAtre commencer pendant la p\u00E9riode d\u00E9finie. D\u00E8s que la date de fin est atteinte, le test est automatiquement stopp\u00E9 quelque que soit la dur\u00E9e d\u00E9finie pour le test.
+qti.form.test.date.help=$\:qti.form.test.date.confirm
 qti.form.test.title=Test
+reopen=R\u00E9ouvrir
+reopen.explanation=Ce test a \u00E9t\u00E9 termin\u00E9. Vous pouvez r\u00E9ouvrir le test \u00E0 de nouvelles tentatives. Le participant pourra reprendre le test l\u00E0 o\u00F9 il s'est arr\u00EAt\u00E9. Si le nombre de tentatives est limit\u00E9es, peut-\u00EAtre devrez-vous \u00E9galement r\u00E9initialis\u00E9e le nombre de tentatives pour qu'il puisse reprendre le test.
+reopen.test=R\u00E9ouvrir un test d\u00E9j\u00E0 termin\u00E9
 replace.wizard.information.empty.results=<b>Indication\: ce test/questionnaire a d\u00E9j\u00E0 \u00E9t\u00E9 lanc\u00E9 par {0} participant/s\!</b> Tous les r\u00E9sultats d\u00E9j\u00E0 existants seront effac\u00E9s si vous cliquez sur "Terminer"au prochain pas.<br></br><b>Publiez votre cours le plus t\u00F4t possible\!</b> Les participants pourront lancer le nouveau test/questionnaire et les r\u00E9sultats pourront \u00EAtre enregistr\u00E9s seulement apr\u00E8s la publication.
 replace.wizard.information.paragraph1=<b>Indication\: ce test/questionnaire a d\u00E9j\u00E0 \u00E9t\u00E9 lanc\u00E9 par {0} participant/s et partiellement termin\u00E9\!</b> Tous les r\u00E9sultats d\u00E9j\u00E0 existants seront archiv\u00E9s si vous cliquez sur "Terminer" au prochain pas.<br></br> Les r\u00E9sultats archiv\u00E9s peuvent \u00EAtre t\u00E9l\u00E9charg\u00E9s ici\:<br />
 replace.wizard.information.paragraph2=Une copie de cette vue d'ensemble des r\u00E9sultats se trouve dans votre dossier personnel sous\:<br/><i>private/archive/{0}/{1}</i><br /><br /><b>Publiez votre cours le plus vite possible\!</b>Les participants pourront lancer le nouveau test/questionnaire et les r\u00E9sultats pourront \u00EAtre enregistr\u00E9s seulement apr\u00E8s la publication.
@@ -146,7 +161,11 @@ replace.wizard.title=Remplacer test ou questionnaire
 replace.wizard.title.step1=S\u00E9lectionner une nouvelle ressource didactique
 replace.wizard.title.step2=Informations sur les r\u00E9sultats
 replace.wizard.title.step3=Informer utilisateur
+report.config=Rapport
 reporter.unavailable=$de.bps.onyx.plugin.course.nodes.iq\:reporter.unavailable
+reset.test.data.title=R\u00E9initialiser les donn\u00E9es du test
+retrieve.tests.title=$org.olat.ims.qti.statistics.ui\:menu.pull.tests.title
+retrievetest.confirm.text=$org.olat.ims.qti\:retrievetest.confirm.text
 score.cut=Points n\u00E9cessaires pour "R\u00E9ussi" 
 score.max=Maximum de points 
 score.min=Minimum de points 
@@ -159,7 +178,16 @@ showResults.title=R\u00E9sultats
 showResults.visibility=Les r\u00E9sultats seront affich\u00E9s de "{0}" \u00E0 "{1}".
 showResults.visibility.future=Vos r\u00E9sultats seront visibles ici d\u00E8s que la correction en sera termin\u00E9e.
 start=D\u00E9marrer
+table.header.end.date=Date de fin
+table.header.extra.time=Suppl\u00E9ment
 table.header.lastModified=Derni\u00E8re mise \u00E0 jour
 table.header.results=R\u00E9sultats
 time.limit.max=Limite de temps
+time.limit.test.explain=Le test dure au plus <strong>{0}</strong>.
+tool.delete.data=R\u00E9initialiser toutes les donn\u00E9es
+tool.extra.time=Prolonger la dur\u00E9e du test
+tool.pull=Reprendre un test en cours
+warning.assessment.mode=La configuration d'examen suivante est active
+warning.assessment.mode.date={0} de {1} \u00E0 {2}
 warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
+warning.users.extra.time=Vous devez s\u00E9lectionner un utilisateur dont vous pouvez prolonger le test.
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
index 36d9c811f9fd4d78ed0e93c1e10323ad73ce5e95..4168d1e3a48f8560fb5747aeae3bc817bfd1ebbf 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
@@ -126,7 +126,12 @@ public class BusinessGroupMailing {
 
 		MailTemplate template = mailing == null ? null : mailing.getTemplate();
 		if(mailing == null || mailing.getTemplate() == null) {
-			template = getDefaultTemplate(type, group, ureqIdentity);
+			//booking by myself
+			if(type != null && type == MailType.addParticipant && ureqIdentity != null && ureqIdentity.equals(identity)) {
+				template = BGMailHelper.createAddMyselfMailTemplate(group, ureqIdentity);
+			} else {
+				template = getDefaultTemplate(type, group, ureqIdentity);
+			}
 		} else if(group != null && template.getContext() != null && needTemplateEnhancement(template)) {
 			BusinessGroupService businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
 			List<RepositoryEntryShort> repoEntries = businessGroupService.findShortRepositoryEntries(Collections.singletonList(group), 0, -1);
diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java
index 8c726fdf7b17349dd0d1ef8c6f17bd0dc85c9bce..2217d7905be61e614a7130e328a3a98c77810ebf 100644
--- a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java
+++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java
@@ -24,7 +24,6 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
-import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
@@ -38,7 +37,7 @@ import org.olat.resource.accesscontrol.ui.AccessConfigurationController;
 /**
  * 
  * Description:<br>
- * Add a check box to the standard access control controller
+ * Wrapper for the resource's access control.
  * 
  * <P>
  * Initial Date:  26 avr. 2011 <br>
@@ -75,22 +74,11 @@ public class BusinessGroupEditAccessController extends FormBasicController {
 		setFormTitle("accesscontrol.title");
 		setFormDescription("accesscontrol_group.desc");
 		setFormContextHelp("Group Administration#gruppensystem_buchung_ag");
+		formLayout.setElementCssClass("o_block_large_bottom");
 
 		if(configController != null) {
 			formLayout.add(configController.getInitialFormItem());
 		}
-		
-		if(configController != null && !managed) {
-			uifactory.addSpacerElement("spacer1", formLayout, false);
-		}
-		
-		if(!managed) {
-			final FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator());
-			buttonGroupLayout.setRootForm(mainForm);
-			formLayout.add(buttonGroupLayout);
-			
-			uifactory.addFormSubmitButton("save", formLayout);
-		}
 	}
 	
 	public void updateBusinessGroup(BusinessGroup businessGroup) {
@@ -109,10 +97,7 @@ public class BusinessGroupEditAccessController extends FormBasicController {
 
 	@Override
 	protected void formOK(UserRequest ureq) {
-		if(configController != null) {
-			configController.formOK(ureq);
-		}
-		fireEvent(ureq, Event.DONE_EVENT);
+		//
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/ims/qti21/QTI21Constants.java b/src/main/java/org/olat/ims/qti21/QTI21Constants.java
index fea31daebedde21dc052b4fd6248bc55af5de1f2..644a91c5766bf6931624774cea89c75df7f6d797 100644
--- a/src/main/java/org/olat/ims/qti21/QTI21Constants.java
+++ b/src/main/java/org/olat/ims/qti21/QTI21Constants.java
@@ -149,6 +149,8 @@ public class QTI21Constants {
 	
 	public static final String CSS_MATCH_DRAG_AND_DROP = "match_dnd";
 	
+	public static final String CSS_MATCH_TRUE_FALSE = "match_true_false";
+	
 	public static final String CSS_MATCH_KPRIM = "match_krpim";
 	
 	public static final String CSS_MATCH_SOURCE_TOP = "source-top";
diff --git a/src/main/java/org/olat/ims/qti21/QTI21DeliveryOptions.java b/src/main/java/org/olat/ims/qti21/QTI21DeliveryOptions.java
index 745c9dde45c684c5b4be500da0a582659c5eb791..c7b5e0e969f3e34a38cc701da39b3bae6ea2ec63 100644
--- a/src/main/java/org/olat/ims/qti21/QTI21DeliveryOptions.java
+++ b/src/main/java/org/olat/ims/qti21/QTI21DeliveryOptions.java
@@ -227,7 +227,7 @@ public class QTI21DeliveryOptions {
 		defaultSettings.displayScoreProgress = false;
 		defaultSettings.displayQuestionProgress = false;
 		defaultSettings.hideFeedbacks = false;
-		defaultSettings.hideLms = false;
+		defaultSettings.hideLms = true;
 		defaultSettings.showMenu = true;
 		defaultSettings.showTitles = true;
 		defaultSettings.personalNotes = false;
diff --git a/src/main/java/org/olat/ims/qti21/manager/openxml/QTI21WordExport.java b/src/main/java/org/olat/ims/qti21/manager/openxml/QTI21WordExport.java
index ba5463fb300267ae8e29cda9aae7caa11b8bde48..5278a31c438d052cacbe7df7ea426adca9cc205f 100644
--- a/src/main/java/org/olat/ims/qti21/manager/openxml/QTI21WordExport.java
+++ b/src/main/java/org/olat/ims/qti21/manager/openxml/QTI21WordExport.java
@@ -680,6 +680,8 @@ public class QTI21WordExport implements MediaResource {
 				} else {
 					startMatchDragAndDropVertical(matchInteraction);
 				}
+			} else if(cssClasses != null && cssClasses.contains(QTI21Constants.CSS_MATCH_TRUE_FALSE)) {
+				startMatchTrueFalse(matchInteraction);
 			} else {
 				startMatchMatrix(matchInteraction);
 			}
@@ -798,6 +800,58 @@ public class QTI21WordExport implements MediaResource {
 			endTable();
 		}
 		
+		private void startMatchTrueFalse(MatchInteraction matchInteraction) {
+			SimpleMatchSet questionMatchSetVertical = matchInteraction.getSimpleMatchSets().get(0);
+			SimpleMatchSet questionMatchSetHorizontal = matchInteraction.getSimpleMatchSets().get(1);
+			List<SimpleAssociableChoice> horizontalAssociableChoices = questionMatchSetHorizontal.getSimpleAssociableChoices();
+			List<SimpleAssociableChoice> verticalAssociableChoices = questionMatchSetVertical.getSimpleAssociableChoices();
+			
+			// calculate the width of the table () and of its columns
+			int tableWidthDxa = OpenXMLConstants.TABLE_FULL_WIDTH_DXA;
+			int tableWidthPct = OpenXMLConstants.TABLE_FULL_WIDTH_PCT;
+			int halfTableWidthDxa = tableWidthDxa / 2;
+			int halfTableWidthPct = tableWidthPct / 2;
+
+			int numOfColumns = horizontalAssociableChoices.size();
+			int columnWidthDxa = halfTableWidthDxa / numOfColumns;
+			int columnWidthPct = halfTableWidthPct / numOfColumns;
+			
+			Integer[] columnsWidth = new Integer[numOfColumns + 1];
+			for(int i=numOfColumns; i-->0; ) {
+				columnsWidth[i] = columnWidthDxa;
+			}
+			columnsWidth[numOfColumns] = halfTableWidthDxa;
+			startTable(columnsWidth);
+
+			currentTable.addRowEl();
+			
+			// horizontal headers
+			for(SimpleAssociableChoice choice:horizontalAssociableChoices) {
+				Element answerCell = currentTable.addCellEl(factory.createTableCell("E9EAF2", columnWidthPct, Unit.pct), 1);
+				appendSimpleAssociableChoice(choice, answerCell);
+			}
+			// white corner
+			Node emptyCell = currentTable.addCellEl(factory.createTableCell(null, halfTableWidthDxa, Unit.dxa), 1);
+			emptyCell.appendChild(factory.createParagraphEl(""));		
+			currentTable.closeRow();
+
+			for(SimpleAssociableChoice choice:verticalAssociableChoices) {
+				currentTable.addRowEl();
+				//checkbox
+				for(SimpleAssociableChoice horizontalChoice:horizontalAssociableChoices) {
+					boolean correct = isCorrectMatchResponse(choice.getIdentifier(), horizontalChoice.getIdentifier(), matchInteraction);
+					appendMatchCheckBox(correct, columnWidthPct, factory);
+				}
+				//answer
+				Element answerCell = currentTable.addCellEl(factory.createTableCell("E9EAF2", halfTableWidthPct, Unit.pct), 1);
+				appendSimpleAssociableChoice(choice, answerCell) ;
+				
+				currentTable.closeRow();
+			}
+			
+			endTable();
+		}
+		
 		/**
 		 * The sources are in one column, the targets are in the second.
 		 * @param matchInteraction
diff --git a/src/main/java/org/olat/ims/qti21/model/QTI21QuestionType.java b/src/main/java/org/olat/ims/qti21/model/QTI21QuestionType.java
index 219eb4b23a6a0ee72d60e76778f35fb2838027ab..4927ccf7340dbc1a797ebab41de4c1908ca9aeed 100644
--- a/src/main/java/org/olat/ims/qti21/model/QTI21QuestionType.java
+++ b/src/main/java/org/olat/ims/qti21/model/QTI21QuestionType.java
@@ -51,6 +51,7 @@ public enum QTI21QuestionType {
 	kprim(true, "kprim", "o_mi_qtikprim", QuestionType.KPRIM),
 	match(true, "match", "o_mi_qtimatch", QuestionType.MATCH),
 	matchdraganddrop(true, "matchdraganddrop", "o_mi_qtimatch_draganddrop", QuestionType.MATCHDRAGANDDROP),
+	matchtruefalse(true, "matchtruefalse", "o_mi_qtimatch_truefalse", QuestionType.MATCHTRUEFALSE),
 	fib(true, "fib", "o_mi_qtifib", QuestionType.FIB),
 	numerical(true, "numerical", "o_mi_qtinumerical", QuestionType.NUMERICAL),
 	hotspot(true, "hotspot", "o_mi_qtihotspot", QuestionType.HOTSPOT),
@@ -212,6 +213,8 @@ public enum QTI21QuestionType {
 			Cardinality cardinalty = responseDeclaration.getCardinality();
 			if(hasClass(interaction, QTI21Constants.CSS_MATCH_DRAG_AND_DROP)) {
 				return QTI21QuestionType.matchdraganddrop;
+			} else if(hasClass(interaction, QTI21Constants.CSS_MATCH_TRUE_FALSE)) {
+				return QTI21QuestionType.matchtruefalse;
 			} else if(cardinalty.isMultiple()) {
 				if(hasClass(interaction, QTI21Constants.CSS_MATCH_KPRIM)) {
 					return QTI21QuestionType.kprim;
diff --git a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java
index af53e6b42a460d766a715c6847b4b504a028367c..04a7e798d421c03bfefcc5ff4b4bc0bb707a2065 100644
--- a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java
+++ b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java
@@ -591,13 +591,13 @@ public class AssessmentItemFactory {
 		SimpleMatchSet sourceMatchSet = new SimpleMatchSet(matchInteraction);
 		matchInteraction.getSimpleMatchSets().add(sourceMatchSet);
 		
-		String[] classic = new String[]{ "A", "B" };
-		for(int i=0; i<2; i++) {
+		String[] sources = new String[]{ "A", "B" };
+		for(int i=0; i<sources.length; i++) {
 			SimpleAssociableChoice sourceChoice = new SimpleAssociableChoice(sourceMatchSet);
 			sourceChoice.setMatchMax(0);
 			sourceChoice.setMatchMin(0);
-			sourceChoice.setIdentifier(IdentifierGenerator.newNumberAsIdentifier(classic[i]));
-			P question = getParagraph(sourceChoice, classic[i]);
+			sourceChoice.setIdentifier(IdentifierGenerator.newNumberAsIdentifier(sources[i]));
+			P question = getParagraph(sourceChoice, sources[i]);
 			sourceChoice.getFlowStatics().add(question);
 			sourceMatchSet.getSimpleAssociableChoices().add(sourceChoice);
 		}
@@ -605,13 +605,13 @@ public class AssessmentItemFactory {
 		SimpleMatchSet targetMatchSet = new SimpleMatchSet(matchInteraction);
 		matchInteraction.getSimpleMatchSets().add(targetMatchSet);
 		
-		String[] target = new String[]{ "M", "N" };
-		for(int i=0; i<2; i++) {
+		String[] targets = new String[]{ "M", "N" };
+		for(int i=0; i<targets.length; i++) {
 			SimpleAssociableChoice targetChoice = new SimpleAssociableChoice(sourceMatchSet);
 			targetChoice.setMatchMax(0);
 			targetChoice.setMatchMin(0);
-			targetChoice.setIdentifier(IdentifierGenerator.newNumberAsIdentifier(target[i]));
-			P question = getParagraph(targetChoice, target[i]);
+			targetChoice.setIdentifier(IdentifierGenerator.newNumberAsIdentifier(targets[i]));
+			P question = getParagraph(targetChoice, targets[i]);
 			targetChoice.getFlowStatics().add(question);
 			targetMatchSet.getSimpleAssociableChoices().add(targetChoice);
 		}
@@ -619,6 +619,45 @@ public class AssessmentItemFactory {
 		return matchInteraction;
 	}
 	
+	public static MatchInteraction appendMatchInteractionTrueFalse(ItemBody itemBody,
+			String unanswered, String right, String wrong, Identifier responseDeclarationId) {
+		MatchInteraction matchInteraction = new MatchInteraction(itemBody);
+		matchInteraction.setResponseIdentifier(responseDeclarationId);
+		matchInteraction.setMaxAssociations(4);
+		matchInteraction.setShuffle(false);
+		itemBody.getBlocks().add(matchInteraction);
+		
+		PromptGroup prompts = new PromptGroup(matchInteraction);
+		matchInteraction.getNodeGroups().add(prompts);
+		
+		SimpleMatchSet sourceMatchSet = new SimpleMatchSet(matchInteraction);
+		matchInteraction.getSimpleMatchSets().add(sourceMatchSet);
+		
+		String[] sources = new String[]{ "A", "B" };
+		for(int i=0; i<sources.length; i++) {
+			appendSimpleAssociableChoice(sourceMatchSet, sources[i], 1, 1); 
+		}
+		
+		SimpleMatchSet targetMatchSet = new SimpleMatchSet(matchInteraction);
+		matchInteraction.getSimpleMatchSets().add(targetMatchSet);
+		String[] targets = new String[]{ unanswered, right, wrong };
+		for(int i=0; i<targets.length; i++) {
+			appendSimpleAssociableChoice(targetMatchSet, targets[i], 0, 0); 
+		}
+		
+		return matchInteraction;
+	}
+	
+	public static void appendSimpleAssociableChoice(SimpleMatchSet matchSet, String value, int matchMax, int matchMin) {
+		SimpleAssociableChoice choice = new SimpleAssociableChoice(matchSet);
+		choice.setMatchMax(matchMax);
+		choice.setMatchMin(matchMin);
+		choice.setIdentifier(IdentifierGenerator.newNumberAsIdentifier(value));
+		P question = getParagraph(choice, value);
+		choice.getFlowStatics().add(question);
+		matchSet.getSimpleAssociableChoices().add(choice);
+	}
+	
 	public static SimpleAssociableChoice createSimpleAssociableChoice(String text, SimpleMatchSet matchSet) {
 		SimpleAssociableChoice targetChoice = new SimpleAssociableChoice(matchSet);
 		targetChoice.setMatchMax(0);
@@ -629,22 +668,29 @@ public class AssessmentItemFactory {
 		return targetChoice;
 	}
 	
+	/**
+	 * Add the response declaration with correct answers (but without score mapping)
+	 * 
+	 * @param assessmentItem
+	 * @param declarationId
+	 * @param associations
+	 * @return
+	 */
 	public static ResponseDeclaration createMatchResponseDeclaration(AssessmentItem assessmentItem, Identifier declarationId,
-			Map<Identifier, List<Identifier>> associations, double maxScore) {
+			Map<Identifier, List<Identifier>> associations) {
 		ResponseDeclaration responseDeclaration = new ResponseDeclaration(assessmentItem);
 		responseDeclaration.setIdentifier(declarationId);
 		responseDeclaration.setCardinality(Cardinality.MULTIPLE);
 		responseDeclaration.setBaseType(BaseType.DIRECTED_PAIR);
-		return appendAssociationMatchResponseDeclaration(responseDeclaration, associations, maxScore);
+		return appendAssociationMatchResponseDeclaration(responseDeclaration, associations);
 	}
 	
 	public static ResponseDeclaration appendAssociationMatchResponseDeclaration(ResponseDeclaration responseDeclaration,
-			Map<Identifier, List<Identifier>> associations, double maxScore) {
+			Map<Identifier, List<Identifier>> associations) {
 		responseDeclaration.setCardinality(Cardinality.MULTIPLE);
 		responseDeclaration.setBaseType(BaseType.DIRECTED_PAIR);
 
 		//correct response
-		int numOfassociations = 0;
 		CorrectResponse correctResponse = new CorrectResponse(responseDeclaration);
 		responseDeclaration.setCorrectResponse(correctResponse);
 		for(Map.Entry<Identifier,List<Identifier>> association:associations.entrySet()) {
@@ -655,27 +701,6 @@ public class AssessmentItemFactory {
 				DirectedPairValue dpValue = new DirectedPairValue(sourceChoiceId, targetChoiceId);
 				FieldValue fValue = new FieldValue(correctResponse, dpValue);
 				correctResponse.getFieldValues().add(fValue);
-				numOfassociations++;
-			}
-		}
-		
-		double mappedValue = maxScore;
-		if(numOfassociations > 0) {
-			mappedValue = maxScore / numOfassociations;
-		}
-		
-		// mapping
-		Mapping mapping = new Mapping(responseDeclaration);
-		mapping.setDefaultValue(-mappedValue);
-		responseDeclaration.setMapping(mapping);
-		for(Map.Entry<Identifier,List<Identifier>> association:associations.entrySet()) {
-			Identifier sourceChoiceId = association.getKey();
-			List<Identifier> targetChoiceIds = association.getValue();
-			for(Identifier targetChoiceId:targetChoiceIds) {
-				MapEntry mapEntry = new MapEntry(mapping);
-				mapEntry.setMapKey(new DirectedPairValue(sourceChoiceId, targetChoiceId));
-				mapEntry.setMappedValue(mappedValue);
-				mapping.getMapEntries().add(mapEntry);
 			}
 		}
 		
diff --git a/src/main/java/org/olat/ims/qti21/model/xml/interactions/MatchAssessmentItemBuilder.java b/src/main/java/org/olat/ims/qti21/model/xml/interactions/MatchAssessmentItemBuilder.java
index 4f74399f85147fb0120843ce532165c3f242daec..68929a6ee802feb3e1129f86f2081a30f0a9dcbc 100644
--- a/src/main/java/org/olat/ims/qti21/model/xml/interactions/MatchAssessmentItemBuilder.java
+++ b/src/main/java/org/olat/ims/qti21/model/xml/interactions/MatchAssessmentItemBuilder.java
@@ -23,6 +23,7 @@ import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendAssociati
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendDefaultItemBody;
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendDefaultOutcomeDeclarations;
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendMatchInteraction;
+import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendMatchInteractionTrueFalse;
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendSetOutcomeFeedbackCorrect;
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendSetOutcomeFeedbackIncorrect;
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendSetOutcomeScoreMapResponse;
@@ -30,6 +31,7 @@ import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.appendSetOutcom
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.createMatchResponseDeclaration;
 import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.createResponseProcessing;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -38,6 +40,8 @@ import java.util.Map;
 import javax.xml.transform.stream.StreamResult;
 
 import org.olat.core.gui.render.StringOutput;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
 import org.olat.ims.qti21.QTI21Constants;
 import org.olat.ims.qti21.model.QTI21QuestionType;
@@ -80,6 +84,8 @@ import uk.ac.ed.ph.jqtiplus.value.SingleValue;
  *
  */
 public class MatchAssessmentItemBuilder extends AssessmentItemBuilder {
+	
+	private static final OLog log = Tracing.createLoggerFor(MatchAssessmentItemBuilder.class);
 
 	private String question;
 	private boolean shuffle;
@@ -92,14 +98,19 @@ public class MatchAssessmentItemBuilder extends AssessmentItemBuilder {
 	 
 	
 	public MatchAssessmentItemBuilder(String title, String matchCssClass, QtiSerializer qtiSerializer) {
-		super(createAssessmentItem(title, matchCssClass), qtiSerializer);
+		super(createAssessmentItem(title, matchCssClass, null, null, null), qtiSerializer);
+	}
+	
+	public MatchAssessmentItemBuilder(String title, String matchCssClass,
+			String unanswered, String right, String wrong, QtiSerializer qtiSerializer) {
+		super(createAssessmentItem(title, matchCssClass, unanswered, right, wrong), qtiSerializer);
 	}
 	
 	public MatchAssessmentItemBuilder(AssessmentItem assessmentItem, QtiSerializer qtiSerializer) {
 		super(assessmentItem, qtiSerializer);
 	}
 	
-	private static AssessmentItem createAssessmentItem(String title, String matchCssClass) {
+	private static AssessmentItem createAssessmentItem(String title, String matchCssClass, String unanswered, String right, String wrong) {
 		AssessmentItem assessmentItem = AssessmentItemFactory.createAssessmentItem(QTI21QuestionType.match, title);
 		
 		NodeGroupList nodeGroups = assessmentItem.getNodeGroups();
@@ -107,20 +118,33 @@ public class MatchAssessmentItemBuilder extends AssessmentItemBuilder {
 		double maxScore = 1.0d;
 		Identifier responseDeclarationId = Identifier.assumedLegal("RESPONSE_1");
 		//define correct answer
-		ResponseDeclaration responseDeclaration = createMatchResponseDeclaration(assessmentItem, responseDeclarationId, new HashMap<>(), maxScore);
+		ResponseDeclaration responseDeclaration = createMatchResponseDeclaration(assessmentItem, responseDeclarationId, new HashMap<>());
 		nodeGroups.getResponseDeclarationGroup().getResponseDeclarations().add(responseDeclaration);
-		
 		appendDefaultOutcomeDeclarations(assessmentItem, maxScore);
 
 		//the single choice interaction
 		ItemBody itemBody = appendDefaultItemBody(assessmentItem);
-		MatchInteraction interaction = appendMatchInteraction(itemBody, responseDeclarationId);
+		Map<Identifier, List<Identifier>> associations = new HashMap<>();
+		MatchInteraction interaction;
+		if(QTI21Constants.CSS_MATCH_TRUE_FALSE.equals(matchCssClass)) {
+			interaction = appendMatchInteractionTrueFalse(itemBody, unanswered, right, wrong, responseDeclarationId);
+			
+			//default correct answers set to "right"
+			SimpleAssociableChoice rightChoice = interaction.getSimpleMatchSets().get(1).getSimpleAssociableChoices().get(1);
+			List<SimpleAssociableChoice> sourceChoices = interaction.getSimpleMatchSets().get(0).getSimpleAssociableChoices();
+			for(SimpleAssociableChoice sourceChoice:sourceChoices) {
+				List<Identifier> targetIdentifiers = new ArrayList<>();
+				targetIdentifiers.add(rightChoice.getIdentifier());
+				associations.put(sourceChoice.getIdentifier(), targetIdentifiers);
+			}
+		} else {
+			interaction = appendMatchInteraction(itemBody, responseDeclarationId);
+		}
 		List<String> cssClasses = new ArrayList<>();
 		cssClasses.add(matchCssClass);
 		interaction.setClassAttr(cssClasses);
 		
-		Map<Identifier, List<Identifier>> associations = new HashMap<>();
-		appendAssociationMatchResponseDeclaration(responseDeclaration, associations, 1.0);
+		appendAssociationMatchResponseDeclaration(responseDeclaration, associations);
 		
 		//response processing
 		ResponseProcessing responseProcessing = createResponseProcessing(assessmentItem, responseDeclarationId);
@@ -199,20 +223,22 @@ public class MatchAssessmentItemBuilder extends AssessmentItemBuilder {
 	}
 	
 	private void extractMatchInteraction() {
-		StringOutput sb = new StringOutput();
-		List<Block> blocks = assessmentItem.getItemBody().getBlocks();
-		for(Block block:blocks) {
-			if(block instanceof MatchInteraction) {
-				matchInteraction = (MatchInteraction)block;
-				responseIdentifier = matchInteraction.getResponseIdentifier();
-				shuffle = matchInteraction.getShuffle();
-				break;
-			} else {
-				qtiSerializer.serializeJqtiObject(block, new StreamResult(sb));
+		try(StringOutput sb = new StringOutput()) {
+			List<Block> blocks = assessmentItem.getItemBody().getBlocks();
+			for(Block block:blocks) {
+				if(block instanceof MatchInteraction) {
+					matchInteraction = (MatchInteraction)block;
+					responseIdentifier = matchInteraction.getResponseIdentifier();
+					shuffle = matchInteraction.getShuffle();
+					break;
+				} else {
+					qtiSerializer.serializeJqtiObject(block, new StreamResult(sb));
+				}
 			}
+			question = sb.toString();
+		} catch(IOException e) {
+			log.error("", e);
 		}
-
-		question = sb.toString();
 	}
 	
 	private void extractScoreEvaluationMode() {
@@ -244,8 +270,12 @@ public class MatchAssessmentItemBuilder extends AssessmentItemBuilder {
 	public QTI21QuestionType getQuestionType() {
 		if(matchInteraction != null) {
 			List<?> cssClassses = matchInteraction.getClassAttr();
-			if(cssClassses != null && cssClassses.contains(QTI21Constants.CSS_MATCH_DRAG_AND_DROP)) {
-				return QTI21QuestionType.matchdraganddrop;
+			if(cssClassses != null) {
+				if(cssClassses.contains(QTI21Constants.CSS_MATCH_DRAG_AND_DROP)) {
+					return QTI21QuestionType.matchdraganddrop;
+				} else if(cssClassses.contains(QTI21Constants.CSS_MATCH_TRUE_FALSE)) {
+					return QTI21QuestionType.matchtruefalse;
+				}
 			}
 		}
 		return QTI21QuestionType.match;
@@ -410,17 +440,13 @@ public class MatchAssessmentItemBuilder extends AssessmentItemBuilder {
 
 	@Override
 	protected void buildResponseAndOutcomeDeclarations() {
-		//need min. and max. score
-		double maxScore = getMaxScoreBuilder().getScore();
-		
 		//refresh correct response
 		ResponseDeclaration responseDeclaration;
 		if(assessmentItem.getResponseDeclaration(responseIdentifier) != null) {
 			responseDeclaration = assessmentItem.getResponseDeclaration(responseIdentifier);
-			appendAssociationMatchResponseDeclaration(responseDeclaration, associations, maxScore);
+			appendAssociationMatchResponseDeclaration(responseDeclaration, associations);
 		} else {
-			responseDeclaration =
-					createMatchResponseDeclaration(assessmentItem, responseIdentifier, associations, maxScore);
+			responseDeclaration = createMatchResponseDeclaration(assessmentItem, responseIdentifier, associations);
 			assessmentItem.getResponseDeclarations().add(responseDeclaration);
 		}
 		
diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI21AssessmentItemFactory.java b/src/main/java/org/olat/ims/qti21/pool/QTI21AssessmentItemFactory.java
index 788594a9baf431121753f40bb5891594ad760529..ee2c61dac26679f8b7fdfc68b7f5d86a215b2748 100644
--- a/src/main/java/org/olat/ims/qti21/pool/QTI21AssessmentItemFactory.java
+++ b/src/main/java/org/olat/ims/qti21/pool/QTI21AssessmentItemFactory.java
@@ -53,6 +53,7 @@ public class QTI21AssessmentItemFactory implements QItemFactory {
 			case kprim: return "QTI 2.1 " + trans.translate("new.kprim");
 			case match: return "QTI 2.1 " + trans.translate("new.match");
 			case matchdraganddrop: return "QTI 2.1 " + trans.translate("new.matchdraganddrop");
+			case matchtruefalse: return "QTI 2.1 " + trans.translate("new.matchtruefalse");
 			case fib: return "QTI 2.1 " + trans.translate("new.fib");
 			case numerical: return "QTI 2.1 " + trans.translate("new.fib.numerical");
 			case essay: return "QTI 2.1 " + trans.translate("new.essay");
diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java b/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java
index 877380a91464a28a5ccedb50aa57a36986c95169..6e84ffd1ec6b9dd9c6c2c547b348cd6cd390ae7d 100644
--- a/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java
+++ b/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java
@@ -350,6 +350,8 @@ public class QTI21QPoolServiceProvider implements QPoolSPI {
 			case kprim: itemBuilder = new KPrimAssessmentItemBuilder(translator.translate("new.kprim"), translator.translate("new.answer"), qtiService.qtiSerializer()); break;
 			case match: itemBuilder = new MatchAssessmentItemBuilder(translator.translate("new.match"), QTI21Constants.CSS_MATCH_MATRIX, qtiService.qtiSerializer()); break;
 			case matchdraganddrop: itemBuilder = new MatchAssessmentItemBuilder(translator.translate("new.match"), QTI21Constants.CSS_MATCH_DRAG_AND_DROP, qtiService.qtiSerializer()); break;
+			case matchtruefalse: itemBuilder = new MatchAssessmentItemBuilder(translator.translate("new.match"), QTI21Constants.CSS_MATCH_TRUE_FALSE,
+					translator.translate("match.unanswered"), translator.translate("match.true"), translator.translate("match.false"), qtiService.qtiSerializer()); break;
 			case fib: itemBuilder = new FIBAssessmentItemBuilder(translator.translate("new.fib"), EntryType.text, qtiService.qtiSerializer()); break;
 			case numerical: itemBuilder = new FIBAssessmentItemBuilder(translator.translate("new.fib.numerical"), EntryType.numerical, qtiService.qtiSerializer()); break;
 			case essay: itemBuilder = new EssayAssessmentItemBuilder(translator.translate("new.essay"), qtiService.qtiSerializer()); break;
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java b/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
index de330b3e0c657dcf78411028d4dc5e6b831dd698..6c85414970833aa3f646b17454860755d793a160 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
+++ b/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
@@ -22,10 +22,13 @@ package org.olat.ims.qti21.questionimport;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
+import org.olat.core.gui.translator.Translator;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.Util;
 import org.olat.ims.qti21.QTI21Constants;
 import org.olat.ims.qti21.model.xml.AssessmentItemBuilder;
 import org.olat.ims.qti21.model.xml.AssessmentItemFactory;
@@ -39,6 +42,7 @@ import org.olat.ims.qti21.model.xml.interactions.MultipleChoiceAssessmentItemBui
 import org.olat.ims.qti21.model.xml.interactions.SimpleChoiceAssessmentItemBuilder;
 import org.olat.ims.qti21.model.xml.interactions.SimpleChoiceAssessmentItemBuilder.ScoreEvaluation;
 import org.olat.ims.qti21.model.xml.interactions.SingleChoiceAssessmentItemBuilder;
+import org.olat.ims.qti21.ui.editor.AssessmentItemEditorController;
 
 import uk.ac.ed.ph.jqtiplus.node.content.xhtml.text.P;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.ChoiceInteraction;
@@ -61,11 +65,13 @@ public class CSVToAssessmentItemConverter {
 	private int currentLine;
 	private int kprimPosition = 0;
 	private ImportOptions options;
+	private final Locale locale;
 	private final QtiSerializer qtiSerializer;
 	private AssessmentItemAndMetadata currentItem;
 	private final List<AssessmentItemAndMetadata> items = new ArrayList<>();
 	
-	public CSVToAssessmentItemConverter(ImportOptions options, QtiSerializer qtiSerializer) {
+	public CSVToAssessmentItemConverter(ImportOptions options, Locale locale, QtiSerializer qtiSerializer) {
+		this.locale = locale;
 		this.options = options;
 		this.qtiSerializer = qtiSerializer;
 	}
@@ -376,6 +382,13 @@ public class CSVToAssessmentItemConverter {
 					itemBuilder = initMatchAssessmentItemBuilder(matchBuilder);
 					break;
 				}
+				case "truefalse": {
+					Translator trans = Util.createPackageTranslator(AssessmentItemEditorController.class, locale);
+					MatchAssessmentItemBuilder matchBuilder = new MatchAssessmentItemBuilder("Matrix", QTI21Constants.CSS_MATCH_TRUE_FALSE,
+							trans.translate("match.unanswered"), trans.translate("match.true"), trans.translate("match.false"), qtiSerializer);
+					itemBuilder = initMatchAssessmentItemBuilderForTrueFalse(matchBuilder);
+					break;
+				}
 				default: {
 					itemBuilder = null;
 				}
@@ -428,6 +441,19 @@ public class CSVToAssessmentItemConverter {
 		return matchBuilder;
 	}
 	
+	private MatchAssessmentItemBuilder initMatchAssessmentItemBuilderForTrueFalse(MatchAssessmentItemBuilder matchBuilder) {
+		//reset
+		matchBuilder.setQuestion("");
+		matchBuilder.clearAssociations();
+		matchBuilder.clearMapping();
+		matchBuilder.getSourceChoices().clear();
+		//set default options
+		matchBuilder.setShuffle(false);
+		matchBuilder.setMultipleChoice(false);
+		matchBuilder.setScoreEvaluationMode(ScoreEvaluation.perAnswer);
+		return matchBuilder;
+	}
+	
 	private void build() {
 		if(currentItem != null) {
 			try {
@@ -513,6 +539,9 @@ public class CSVToAssessmentItemConverter {
 		} else if(itemBuilder instanceof KPrimAssessmentItemBuilder) {
 			itemBuilder.setMinScore(0.0d);
 			itemBuilder.setMaxScore(points);
+		} else if(itemBuilder instanceof MatchAssessmentItemBuilder) {
+			itemBuilder.setMinScore(0.0d);
+			itemBuilder.setMaxScore(points);
 		}
 	}
 	
@@ -567,18 +596,20 @@ public class CSVToAssessmentItemConverter {
 			}
 		} else {
 			String answer = parts[0];
-			SimpleAssociableChoice sourceChoice = AssessmentItemFactory
-					.createSimpleAssociableChoice(answer, matchBuilder.getSourceMatchSet());
-			matchBuilder.getSourceChoices().add(sourceChoice);
-			
-			//correct answer and points
-			for(int i=1; i<parts.length && i<(targetChoices.size() + 1); i++) {
-				double point = parseFloat(parts[i], 0.0f);
-				SimpleAssociableChoice targetChoice = targetChoices.get(i - 1);
-				DirectedPairValue directedPair = new DirectedPairValue(sourceChoice.getIdentifier(), targetChoice.getIdentifier());
-				matchBuilder.addScore(directedPair, Double.valueOf(point));
-				if(point > 0.0) {
-					matchBuilder.addAssociation(sourceChoice.getIdentifier(), targetChoice.getIdentifier());
+			if(StringHelper.containsNonWhitespace(answer)) {
+				SimpleAssociableChoice sourceChoice = AssessmentItemFactory
+						.createSimpleAssociableChoice(answer, matchBuilder.getSourceMatchSet());
+				matchBuilder.getSourceChoices().add(sourceChoice);
+				
+				//correct answer and points
+				for(int i=1; i<parts.length && i<(targetChoices.size() + 1); i++) {
+					double point = parseFloat(parts[i], 0.0f);
+					SimpleAssociableChoice targetChoice = targetChoices.get(i - 1);
+					DirectedPairValue directedPair = new DirectedPairValue(sourceChoice.getIdentifier(), targetChoice.getIdentifier());
+					matchBuilder.addScore(directedPair, Double.valueOf(point));
+					if(point > 0.0) {
+						matchBuilder.addAssociation(sourceChoice.getIdentifier(), targetChoice.getIdentifier());
+					}
 				}
 			}
 		}
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/OverviewQuestionController.java b/src/main/java/org/olat/ims/qti21/questionimport/OverviewQuestionController.java
index 31e777fddc3cd43ff00f974fa510a8ce658b9fc4..806f102bb936f00d90d7a2b09b53a12e5c29a748 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/OverviewQuestionController.java
+++ b/src/main/java/org/olat/ims/qti21/questionimport/OverviewQuestionController.java
@@ -127,6 +127,7 @@ public class OverviewQuestionController extends StepFormBasicController {
 				case essay: return translate("item.type.essay");
 				case match: return translate("item.type.match");
 				case matchdraganddrop: return translate("item.type.matchdraganddrop");
+				case matchtruefalse: return translate("item.type.matchtruefalse");
 				default: return "??";
 			}
 		}
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/TextInputController.java b/src/main/java/org/olat/ims/qti21/questionimport/TextInputController.java
index dacc1635e3c96e8e8d5b2c7ff0a09e4fb8339e87..cc8dde4c5766a0fc973d11c13fd564689107d189 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/TextInputController.java
+++ b/src/main/java/org/olat/ims/qti21/questionimport/TextInputController.java
@@ -91,7 +91,7 @@ public class TextInputController extends StepFormBasicController {
 		
 		String inp = inputElement.getValue();
 		if(validatedInp == null || !validatedInp.equals(inp)) {
-			CSVToAssessmentItemConverter converter = new CSVToAssessmentItemConverter(options, qtiService.qtiSerializer());
+			CSVToAssessmentItemConverter converter = new CSVToAssessmentItemConverter(options, getLocale(), qtiService.qtiSerializer());
 			try {
 				converter.parse(inputElement.getValue());
 				List<AssessmentItemAndMetadata> items = converter.getItems();
@@ -110,7 +110,7 @@ public class TextInputController extends StepFormBasicController {
 
 	@Override
 	protected void formOK(UserRequest ureq) {
-		CSVToAssessmentItemConverter converter = new CSVToAssessmentItemConverter(options, qtiService.qtiSerializer());
+		CSVToAssessmentItemConverter converter = new CSVToAssessmentItemConverter(options, getLocale(), qtiService.qtiSerializer());
 		converter.parse(inputElement.getValue());
 		importedItems.setItems(converter.getItems());
 		fireEvent(ureq, StepsEvent.ACTIVATE_NEXT);
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_de.properties
index a0e0ae54b23ccd7009d16d875bd24bb97dc920cf..253c520b2b27b905436cd504b67a8d43b057090c 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_de.properties
@@ -17,4 +17,5 @@ item.type.sc=$org.olat.ims.qti.editor\:item.type.sc
 item.type.essay=$org.olat.ims.qti21.ui.editor\:new.essay
 item.type.match=$org.olat.ims.qti21.ui.editor\:new.match
 item.type.matchdraganddrop=$org.olat.ims.qti21.ui.editor\:new.matchdraganddrop
+item.type.matchtruefalse=$org.olat.ims.qti21.ui.editor\:new.matchtruefalse
 error.at.line=Problem auf Zeile {0}
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_en.properties
index 3368a089f36e01e8e670d77c0e1ab01489b0197c..e5a25ae8a1bbb276f8cb2e61bd21a1ef89e994a8 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_en.properties
@@ -17,4 +17,5 @@ item.type.sc=$org.olat.ims.qti.editor\:item.type.sc
 item.type.essay=$org.olat.ims.qti21.ui.editor\:new.essay
 item.type.match=$org.olat.ims.qti21.ui.editor\:new.match
 item.type.matchdraganddrop=$org.olat.ims.qti21.ui.editor\:new.matchdraganddrop
+item.type.matchtruefalse=$org.olat.ims.qti21.ui.editor\:new.matchtruefalse
 error.at.line=Issue with line {0}
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_fr.properties
index 7d7701b21f484eac3a91c0a98557238fbfad8309..da4ab8cbd1b446afc58c19c1c7b7d4852182bdcf 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/ims/qti21/questionimport/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Tue Aug 15 17:19:04 CEST 2017
+#Thu Feb 01 18:22:50 CET 2018
 download.example=$org.olat.ims.qti.questionimport\:download.example
 error.at.line=Erreur ligne {0}
 form.importdata=$org.olat.ims.qti.questionimport\:form.importdata
@@ -6,6 +6,8 @@ input.title=$org.olat.ims.qti.questionimport\:input.title
 item.type.essay=$org.olat.ims.qti.editor\:item.type.essay
 item.type.fib=$org.olat.ims.qti.editor\:item.type.fib
 item.type.kprim=$org.olat.ims.qti.editor\:item.type.kprim
+item.type.match=$org.olat.ims.qti21.ui.editor\:new.match
+item.type.matchdraganddrop=$org.olat.ims.qti21.ui.editor\:new.matchdraganddrop
 item.type.mc=$org.olat.ims.qti.editor\:item.type.mc
 item.type.sc=$org.olat.ims.qti.editor\:item.type.sc
 table.header.points=$org.olat.ims.qti.questionimport\:table.header.points
diff --git a/src/main/java/org/olat/ims/qti21/ui/AssessmentEntryOutcomesListener.java b/src/main/java/org/olat/ims/qti21/ui/AssessmentEntryOutcomesListener.java
index a8077ea5be0e9d226c2500b1099159311c14914d..f9c3c3bfc4d2ff3b81f77cde717a17ff3c4bf1a4 100644
--- a/src/main/java/org/olat/ims/qti21/ui/AssessmentEntryOutcomesListener.java
+++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentEntryOutcomesListener.java
@@ -26,6 +26,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.translator.Translator;
+import org.olat.core.id.Identity;
+import org.olat.core.id.UserConstants;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.Formatter;
 import org.olat.core.util.Util;
@@ -80,7 +82,8 @@ public class AssessmentEntryOutcomesListener implements OutcomesListener {
 			DigitalSignatureOptions options, Date timestamp, Locale locale) {
 		MailBundle bundle = new MailBundle();
 		bundle.setToId(candidateSession.getIdentity());
-		String fullname = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(candidateSession.getIdentity());
+		Identity assessedIdentity = candidateSession.getIdentity();
+		String fullname = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(assessedIdentity);
 		Date assessedDate = candidateSession.getFinishTime() == null ? timestamp : candidateSession.getFinishTime();
 
 		
@@ -93,7 +96,12 @@ public class AssessmentEntryOutcomesListener implements OutcomesListener {
 				testEntry.getDisplayname(),	// {4}
 				fullname,					// {5}
 				Formatter.getInstance(locale)
-					.formatDateAndTime(assessedDate) // {6}
+					.formatDateAndTime(assessedDate), 								// {6}
+				assessedIdentity.getName(),											// {7}
+				assessedIdentity.getUser()
+					.getProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, locale),	// {8}
+				assessedIdentity.getUser()
+					.getProperty(UserConstants.INSTITUTIONALNAME, locale),			// {9}
 		};
 
 		String subject = translator.translate("digital.signature.mail.subject", args);
diff --git a/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java b/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java
index 1239e173bd47b83d24acf5423b91ce88d95750ff..acd2dbfcf0106d216809042de7cab92ba05ca8ec 100644
--- a/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java
@@ -746,7 +746,9 @@ public class AssessmentResultController extends FormBasicController {
 		}
 		
 		public String getScorePercent() {
-			if(maxScore == null) return null;
+			if(maxScore == null) {
+				return null;
+			}
 			if(score == null) return "0";
 			
 			double percent = (score / maxScore) * 100.0d;
diff --git a/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html b/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html
index 1b7dbb6a20458f62093176a2df5eff8a7f0d27e8..42163a3ec170c478633c9732e9b7bf0e33c9dfc4 100644
--- a/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html
+++ b/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html
@@ -80,16 +80,15 @@
 			<td>
 				<div>
 				#if ($testResults.hasMaxScore())
-		    		#if ($testResults.maxScore == "-1.0")
+					#if ($testResults.maxScore == "-1.0")
 		  				$testResults.score $r.translate("results.points") ($r.translate("question.progress.noMaxScore"))
-		    		#else
+					#else
 		  				<span title="$r.translateInAttribute("results.score.yourscore")" class="o_sel_assessmenttest_score">$testResults.score</span> 
-		  				$r.translate("results.of") <span title="$r.translateInAttribute("score.max")" class="o_sel_assessmenttest_maxscore">$testResults.maxScore</span> $r.translate("results.of.points")
+		  				$r.translate("results.of") <span title="$r.translateInAttribute("score.max")" class="o_sel_assessmenttest_maxscore">$testResults.maxScore</span> $r.translate("results.of.points") (${testResults.scorePercent}%)
 		  			#end
 				#else
 					$testResults.score
 				#end
-				(${testResults.scorePercent}%)
 				</div>
 			</td>
 		</tr>
@@ -153,7 +152,7 @@
 	</div>	
 	</div> ## END left column / o_qti_metainfo_listing
 		
-	#if(${testResults.hasScore()})			
+	#if(${testResults.hasScore()} && ${testResults.hasMaxScore()})			
 	<div class="o_qti_metainfo_visual col-xs-12 col-sm-5 col-md-4 col-lg-3"> ## START right column
 	<div class="o_block_centered_wrapper"><div class="o_block_centered_content">
 		<div class="radial-progress radial-progress-lg #if(${testResults.hasPass()}) #if(${testResults.getPass().booleanValue()}) radial-progress-success #elseif(!${testResults.getPass().booleanValue()}) radial-progress-danger #end #end " id="o_performance_summary_visual" data-progress="0">
@@ -398,6 +397,7 @@
 							/ <span title="$r.translateInAttribute("score.max")" class="o_sel_assessmentitem_maxscore">$itemResult.maxScore</span>
 						#end
 					</div>
+					#if(${itemResult.hasMaxScore()})
 					<div class="col-xs-6 col-md-8">
 						<div class="progress" style="width:100%;">
 							<div class="progress-bar" role="progressbar" aria-valuenow="$itemResult.score" aria-valuemin="0" aria-valuemax="$itemResult.maxScore" style="width:${itemResult.scorePercent}%;">
@@ -406,6 +406,7 @@
 						</div>
 					</div>
 					<div class="col-xs-1">${itemResult.scorePercent}%</div>
+					#end
 				</td> 
 			</tr>
 			#elseif(${itemResult.hasMaxScore()})
diff --git a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_fr.properties
index bd7144f56e387f9d9019b6027356a3bda611264b..667b869142061934241807f861b99832be7e8023 100644
--- a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Nov 30 09:44:19 CET 2017
+#Thu Feb 01 18:23:01 CET 2018
 actualPoints=$org.olat.modules.iq\:actualPoints
 admin.12.title=Configuration QTI 1.2
 admin.menu.title=QTI 2.1
@@ -112,6 +112,7 @@ error.integer=Format de nombre inad\u00E9quat. Exemple\: 15, 5, 1
 error.mimetype=$org.olat.core.commons.modules.bc\:WrongMimeType
 error.reload.question=Une erreur inattendue s'est produite. Veuillez v\u00E9rifiez la r\u00E9ponse que vous avez donn\u00E9 \u00E0 la question et sauvez-la \u00E0 nouveau.
 error.required.format=Votre entr\u00E9e ne correspond pas au format requis.
+error.test.closed=Le test est termin\u00E9
 error.textEntry.invalid=Votre entr\u00E9e doit \u00EAtre un {0} valide.
 error.textEntry.invalid.float=Votre entr\u00E9e doit \u00EAtre un nombre {0} valide avec une virgule ou un point comme s\u00E9parateur d\u00E9cimal.
 error.textEntry.invalid.record=Votre entr\u00E9e doit un nombre valide.
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java
index e5b8d647bd2b05dba5eb0775a77db4f42bd98bbe..15a9b960758dbbabc8b410563e5d2fa3280fe49b 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java
@@ -51,6 +51,7 @@ import static org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.renderR
 import static org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.renderSingleCardinalityValue;
 import static org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.valueContains;
 
+import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
 import java.net.URI;
@@ -1026,6 +1027,8 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent
 					interactionName += "_kprim";
 				} else if(hasClass(matchInteraction, QTI21Constants.CSS_MATCH_DRAG_AND_DROP)) {
 					interactionName += "_dnd";
+				} else if(hasClass(matchInteraction, QTI21Constants.CSS_MATCH_TRUE_FALSE)) {
+					interactionName += "_truefalse";
 				} else if(hasClass(matchInteraction, QTI21Constants.CSS_MATCH_KPRIM)) {
 					interactionName += "_kprim";
 				}
@@ -1375,14 +1378,17 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent
 			ResolvedAssessmentItem resolvedAssessmentItem, ItemSessionState itemSessionState, Math math) {
 		
 		renderer.setMathXsltDisabled(true);
-		StringOutput mathOutput = StringOutputPool.allocStringBuilder(2048);
-		mathOutput.append("<math xmlns=\"http://www.w3.org/1998/Math/MathML\">");
-		math.getContent().forEach((foreignElement)
-				-> renderMath(renderer, mathOutput, component, resolvedAssessmentItem, itemSessionState, foreignElement));
-		mathOutput.append("</math>");
-		String enrichedMathML = StringOutputPool.freePop(mathOutput);
-		renderer.setMathXsltDisabled(false);
-		transformMathmlAsString(sb, enrichedMathML);
+		try(StringOutput mathOutput = StringOutputPool.allocStringBuilder(2048)) {
+			mathOutput.append("<math xmlns=\"http://www.w3.org/1998/Math/MathML\">");
+			math.getContent().forEach((foreignElement)
+					-> renderMath(renderer, mathOutput, component, resolvedAssessmentItem, itemSessionState, foreignElement));
+			mathOutput.append("</math>");
+			String enrichedMathML = StringOutputPool.freePop(mathOutput);
+			renderer.setMathXsltDisabled(false);
+			transformMathmlAsString(sb, enrichedMathML);
+		} catch(IOException e) {
+			log.error("", e);
+		}
 	}
 	
 	protected void renderMath(AssessmentRenderer renderer, StringOutput out, AssessmentObjectComponent component,
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java
index 15dc7a694e8bbd32bf44a8ee121ad11190c936ae..0883fb38f8137c62451187e2b92be0a4b9a85899 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java
@@ -554,6 +554,10 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
 		return AssessmentRenderFunctions.valueContains(value, string);
 	}
 	
+	public boolean trueFalseDefault(Value response, String targetIdentifier, MatchInteraction interaction) {
+		return AssessmentRenderFunctions.trueFalseDefault(response, targetIdentifier, interaction);
+	}
+	
 	public ResponseData getResponseInput(Identifier identifier) {
 		return AssessmentRenderFunctions.getResponseInput(itemSessionState, identifier);
 	}
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java
index 3199e9125f4724a47fdee75f31f8b38994036eb3..955cc299589a5c64caaaa81b96b64fe08c51e841 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java
@@ -46,7 +46,9 @@ import uk.ac.ed.ph.jqtiplus.node.QtiNode;
 import uk.ac.ed.ph.jqtiplus.node.content.basic.TextRun;
 import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
 import uk.ac.ed.ph.jqtiplus.node.item.CorrectResponse;
+import uk.ac.ed.ph.jqtiplus.node.item.interaction.MatchInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.Choice;
+import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.SimpleAssociableChoice;
 import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
 import uk.ac.ed.ph.jqtiplus.node.item.template.declaration.TemplateDeclaration;
 import uk.ac.ed.ph.jqtiplus.node.test.TestFeedback;
@@ -525,14 +527,20 @@ public class AssessmentRenderFunctions {
 	//value-contains
 	public static final boolean valueContains(Value value, Identifier identifier) {
 		if(value != null && !value.isNull()) {
-			//TODO mimic the XSLT
-			return value.toQtiString().contains(identifier.toString());
-			/*
 			if(value.hasBaseType(BaseType.IDENTIFIER)) {
-				IdentifierValue identifierValue = (IdentifierValue)value;
-				return identifierValue.identifierValue().equals(identifier);
+				if(value.getCardinality().isSingle()) {
+					IdentifierValue identifierValue = (IdentifierValue)value;
+					return identifierValue.identifierValue().equals(identifier);
+				} else if(value.getCardinality().isList()) {
+					boolean contains = false;
+					for(IdentifierValue identifierValue : ((ListValue) value).values(IdentifierValue.class)) {
+						if(identifierValue.identifierValue().equals(identifier)) {
+							contains = true;
+						}
+					}
+					return contains;
+				}
 			}
-			*/
 		}
 		return false;
 	}
@@ -540,9 +548,21 @@ public class AssessmentRenderFunctions {
 	public static boolean valueContains(Value value, String string) {
 		if(value == null || value.isNull() || value instanceof NullValue) {
 			return false;
-		} else {
-			return value.toQtiString().contains(string);//TODO qti perhaps must match closer for MultipleValue
 		}
+		return value.toQtiString().contains(string);//TODO qti perhaps must match closer for MultipleValue
+	}
+	
+	/**
+	 * Return true if the answer is not answered
+	 * @param response
+	 * @param string
+	 * @return
+	 */
+	public static boolean trueFalseDefault(Value response, String targetIdentifier, MatchInteraction interaction) {
+		//first target is "unanswered"
+		SimpleAssociableChoice unansweredChoice = interaction.getSimpleMatchSets().get(1).getSimpleAssociableChoices().get(0);
+		return (targetIdentifier.equals(unansweredChoice.getIdentifier().toString())
+				&& (response == null || response.isNull() || response instanceof NullValue));
 	}
 	
 	/**
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/_content/associateInteraction.html b/src/main/java/org/olat/ims/qti21/ui/components/_content/associateInteraction.html
index faca66cbce70bc5a85fbfa666e33c406d7c68635..dd546cb1210d9bfb76a111f0148e9965d9c65294 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/_content/associateInteraction.html
+++ b/src/main/java/org/olat/ims/qti21/ui/components/_content/associateInteraction.html
@@ -13,7 +13,7 @@
 	<div class="o_error badResponse">$r.translate("error.as.directed")</div>
 	#end
 	<div id="${containerId}">
-		<div id="${containerId}_items" class="clearfix" style="padding:15px;">
+		<div id="${containerId}_items" class="o_associate_items clearfix" style="padding:15px;">
         	#foreach($choice in $choices)
             	<div data-qti-id="${choice.identifier}" data-qti-match-max="${choice.matchMax}" class="o_associate_item" style="width: 100px; float:left;">
               		$r.renderFlowStatics($choice.getFlowStatics())
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/_content/matchInteraction_truefalse.html b/src/main/java/org/olat/ims/qti21/ui/components/_content/matchInteraction_truefalse.html
new file mode 100644
index 0000000000000000000000000000000000000000..ab59a131b2bf3b19ec45f67bba7aede1e02d99a0
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/components/_content/matchInteraction_truefalse.html
@@ -0,0 +1,54 @@
+#set($responseIdentifier = $r.responseUniqueId($interaction))
+#set($orderedSet1 = $r.getVisibleOrderedChoices($interaction,0))
+#set($orderedSet2 = $r.getVisibleOrderedChoices($interaction,1))
+
+<input name="qtiworks_presented_${responseIdentifier}" type="hidden" value="1"/>
+<div class="$localName match_true_false">
+	#if($interaction.getPrompt())
+	<div class="prompt">$r.renderPrompt($interaction.getPrompt())</div>
+	#end
+	
+	#if($r.isInvalidResponse($interaction.responseIdentifier))
+	<div class="o_error badResponse">$r.translate("error.as.directed")</div>
+	#end
+	<table id="qti_container_${responseIdentifier}" class="table">
+		<thead>
+			<tr>
+            	#foreach($choice2 in $orderedSet2)
+				<th class="#if($foreach.index == 0) o_match_true_false_unanswered #elseif($foreach.index == 1) o_match_true_false_right #else o_match_true_false_wrong #end">$r.renderFlowStatics($choice2.getFlowStatics())</th>
+			#end
+				<th class="o_match_true_false_answer"> </th>
+			</tr>
+        </thead>
+		<tbody>
+		#foreach($choice1 in $orderedSet1)
+			#set($set1Identifier = $r.toString($choice1.identifier))
+            <tr>
+				#foreach($choice2 in $orderedSet2)
+					#set($set2Identifier = $r.toString($choice2.identifier))
+					#set($responseValue = $set1Identifier + " " + $set2Identifier)
+					#set($responseChecked = $r.getResponseValue($interaction.responseIdentifier))
+                	<td class="#if($foreach.index == 0) o_match_true_false_unanswered #elseif($foreach.index == 1) o_match_true_false_right #else o_match_true_false_wrong #end">
+                  	<input id="oo_${set1Identifier}_${set2Identifier}" type="checkbox" name="qtiworks_response_${responseIdentifier}" value="${responseValue}" #if($r.valueContains($responseChecked, $responseValue) || $r.trueFalseDefault($responseChecked, $set2Identifier, $interaction)) checked #end #if($r.isItemSessionEnded()) disabled #end/>
+                		$r.appendFlexiFormDirtyForCheckbox("oo_${set1Identifier}_${set2Identifier}")
+                	</td>
+				#end
+				<td class="o_match_true_false_answer">$r.renderFlowStatics($choice1.getFlowStatics())</td>
+            </tr>
+		#end
+		</tbody>
+	</table>
+	#if($r.isItemSessionOpen())
+        <script type='text/javascript'>
+		jQuery(function() {
+			jQuery('#qti_container_${responseIdentifier}').matchInteraction({
+				responseIdentifier: '$responseIdentifier',
+				formDispatchFieldId: '$r.formDispatchFieldId',
+				maxAssociations: $interaction.maxAssociations,
+				leftData: {#foreach($choice1 in $orderedSet1) #if($foreach.count > 1),#end $choice1.identifier:$choice1.matchMax #end},
+				rightData: {#foreach($choice2 in $orderedSet2) #if($foreach.count > 1),#end $choice2.identifier:$choice2.matchMax #end}
+			});
+		});
+        </script>
+	#end
+</div>
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
index c416c02bc87f21efb03583547fe90c8ed7185834..37a6514d99a3916b87b66ecce1691c8602a65315 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
@@ -64,6 +64,7 @@ import org.olat.ims.qti21.ui.editor.interactions.MatchEditorController;
 import org.olat.ims.qti21.ui.editor.interactions.MatchScoreController;
 import org.olat.ims.qti21.ui.editor.interactions.MultipleChoiceEditorController;
 import org.olat.ims.qti21.ui.editor.interactions.SingleChoiceEditorController;
+import org.olat.ims.qti21.ui.editor.interactions.TrueFalseEditorController;
 import org.olat.ims.qti21.ui.editor.interactions.UploadEditorController;
 import org.olat.modules.assessment.AssessmentEntry;
 import org.olat.modules.assessment.AssessmentService;
@@ -258,6 +259,7 @@ public class AssessmentItemEditorController extends BasicController {
 			case kprim: itemBuilder = initKPrimChoiceEditors(ureq, item); break;
 			case match: itemBuilder = initMatchChoiceEditors(ureq, item); break;
 			case matchdraganddrop: itemBuilder = initMatchDragAndDropEditors(ureq, item); break;
+			case matchtruefalse: itemBuilder = initMatchTrueFalseEditors(ureq, item); break;
 			case hotspot: itemBuilder = initHotspotEditors(ureq, item); break;
 			case essay: itemBuilder = initEssayEditors(ureq, item); break;
 			case upload: itemBuilder = initUploadEditors(ureq, item); break;
@@ -336,7 +338,7 @@ public class AssessmentItemEditorController extends BasicController {
 		itemEditor = new MatchEditorController(ureq, getWindowControl(), matchItemBuilder,
 				rootDirectory, rootContainer, itemFile, restrictedEdit, readOnly);
 		listenTo(itemEditor);
-		scoreEditor = new MatchScoreController(ureq, getWindowControl(), matchItemBuilder, itemRef, itemFile,
+		scoreEditor = new MatchScoreController(ureq, getWindowControl(), matchItemBuilder, itemRef, itemFile, true,
 				restrictedEdit, readOnly);
 		listenTo(scoreEditor);
 		feedbackEditor = new FeedbacksEditorController(ureq, getWindowControl(), matchItemBuilder,
@@ -355,7 +357,26 @@ public class AssessmentItemEditorController extends BasicController {
 		itemEditor = new MatchEditorController(ureq, getWindowControl(), matchItemBuilder,
 				rootDirectory, rootContainer, itemFile, restrictedEdit, readOnly);
 		listenTo(itemEditor);
-		scoreEditor = new MatchScoreController(ureq, getWindowControl(), matchItemBuilder, itemRef, itemFile,
+		scoreEditor = new MatchScoreController(ureq, getWindowControl(), matchItemBuilder, itemRef, itemFile, true,
+				restrictedEdit, readOnly);
+		listenTo(scoreEditor);
+		feedbackEditor = new FeedbacksEditorController(ureq, getWindowControl(), matchItemBuilder,
+				rootDirectory, rootContainer, itemFile, FeedbacksEnabler.standardFeedbacks(),
+				restrictedEdit, readOnly);
+		listenTo(feedbackEditor);
+		
+		tabbedPane.addTab(translate("form.match"), itemEditor);
+		tabbedPane.addTab(translate("form.score"), scoreEditor);
+		tabbedPane.addTab(translate("form.feedback"), feedbackEditor);
+		return matchItemBuilder;
+	}
+	
+	private AssessmentItemBuilder initMatchTrueFalseEditors(UserRequest ureq, AssessmentItem item) {
+		MatchAssessmentItemBuilder matchItemBuilder = new MatchAssessmentItemBuilder(item, qtiService.qtiSerializer());
+		itemEditor = new TrueFalseEditorController(ureq, getWindowControl(), matchItemBuilder,
+				rootDirectory, rootContainer, itemFile, restrictedEdit, readOnly);
+		listenTo(itemEditor);
+		scoreEditor = new MatchScoreController(ureq, getWindowControl(), matchItemBuilder, itemRef, itemFile, false,
 				restrictedEdit, readOnly);
 		listenTo(scoreEditor);
 		feedbackEditor = new FeedbacksEditorController(ureq, getWindowControl(), matchItemBuilder,
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
index a96e2720a569a6973359aa90838f68d41ae16d8a..ec845e72046d7d15d296b903cb0f40c69335b2c4 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
@@ -154,7 +154,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 	private MenuTree menuTree;
 	private Dropdown exportItemTools, addItemTools, changeItemTools;
 	private Link newTestPartLink, newSectionLink, newSingleChoiceLink, newMultipleChoiceLink,
-			newKPrimLink, newMatchLink, newMatchDragAndDropLink,
+			newKPrimLink, newMatchLink, newMatchDragAndDropLink, newMatchTrueFalseLink,
 			newFIBLink, newNumericalLink, newHotspotLink, newHottextLink,
 			newEssayLink, newUploadLink, newDrawingLink;
 	private Link importFromPoolLink, importFromTableLink, exportToPoolLink, exportToDocxLink;
@@ -278,7 +278,10 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 		newMatchDragAndDropLink = LinkFactory.createToolLink("new.matchdraganddrop", translate("new.matchdraganddrop"), this, "o_mi_qtimatch_draganddrop");
 		newMatchDragAndDropLink.setDomReplacementWrapperRequired(false);
 		addItemTools.addComponent(newMatchDragAndDropLink);
-		
+		newMatchTrueFalseLink = LinkFactory.createToolLink("new.matchtruefalse", translate("new.matchtruefalse"), this, "o_mi_qtimatch_truefalse");
+		newMatchTrueFalseLink.setDomReplacementWrapperRequired(false);
+		addItemTools.addComponent(newMatchTrueFalseLink);
+
 		newFIBLink = LinkFactory.createToolLink("new.fib", translate("new.fib"), this, "o_mi_qtifib");
 		newFIBLink.setDomReplacementWrapperRequired(false);
 		addItemTools.addComponent(newFIBLink);
@@ -514,6 +517,9 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 			doNewAssessmentItem(ureq, menuTree.getSelectedNode(), new MatchAssessmentItemBuilder(translate("new.match"), QTI21Constants.CSS_MATCH_MATRIX, qtiService.qtiSerializer()));
 		} else if(newMatchDragAndDropLink == source) {
 			doNewAssessmentItem(ureq, menuTree.getSelectedNode(), new MatchAssessmentItemBuilder(translate("new.matchdraganddrop"), QTI21Constants.CSS_MATCH_DRAG_AND_DROP, qtiService.qtiSerializer()));
+		} else if(newMatchTrueFalseLink == source) {
+			doNewAssessmentItem(ureq, menuTree.getSelectedNode(), new MatchAssessmentItemBuilder(translate("new.matchtruefalse"), QTI21Constants.CSS_MATCH_TRUE_FALSE,
+					translate("match.unanswered"), translate("match.true"), translate("match.false"), qtiService.qtiSerializer()));
 		} else if(newFIBLink == source) {
 			doNewAssessmentItem(ureq, menuTree.getSelectedNode(), new FIBAssessmentItemBuilder(translate("new.fib"), EntryType.text, qtiService.qtiSerializer()));
 		} else if(newNumericalLink == source) {
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
index 0ec4d2493e67627be447cdd18121ea08b77c00c1..0d6ca44f4e226f3ce17d7962b24a55a33c29df91 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
@@ -181,6 +181,9 @@ item.session.control.attempts.hint=Diese Einschr\u00E4nkung der L\u00F6sungsvers
 item.session.control.show.solution=L\u00F6sung anzeigen
 item.session.control.show.solution.hint=Beim R\u00FCckblick werden auch L\u00F6sungen angezeigt.
 lifecycle.version=$org.olat.modules.qpool.ui\:lifecycle.version
+match.unanswered=Unbeantwortet
+match.true=Richtig
+match.false=Falsch
 math.operator.bigger=>
 math.operator.biggerEquals=>\=
 math.operator.equals=\=
@@ -208,6 +211,7 @@ new.hottext.text=Hottext
 new.kprim=Kprim
 new.match=Matrix
 new.matchdraganddrop=Drag and Drop
+new.matchtruefalse=True/false
 new.mc=Multiple Choice
 new.rectangle=Viereck
 new.sc=Single Choice
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
index 2bd777a1782d5996bb80f50130d6053be14899a8..b468c8a82483a8f75570af4e70d9bc270a4f76ba 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
@@ -180,6 +180,9 @@ item.session.control.attempts.hint=This limitation of the attempts is only valid
 item.session.control.show.solution=Show solution
 item.session.control.show.solution.hint=Solution is shown in review as well.
 lifecycle.version=$org.olat.modules.qpool.ui\:lifecycle.version
+match.unanswered=Unanswered
+match.true=Right
+match.false=Wrong
 math.operator.bigger=>
 math.operator.biggerEquals=>\=
 math.operator.equals=\=
@@ -208,6 +211,7 @@ new.hottext.text=text
 new.kprim=Kprim
 new.match=Match
 new.matchdraganddrop=Drag and Drop
+new.matchtruefalse=True/false
 new.mc=Multiple choice
 new.rectangle=Rectangle
 new.sc=Single choice
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties
index 0be95da7d656e79c917232bf68229a8427aec79b..47a723b540a062aaf477298c6e84507d370558c7 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Nov 16 19:02:40 CET 2017
+#Thu Feb 01 18:25:17 CET 2018
 Diff\u00E9rentes=alternatives
 MULTIPLE=Choix multiple
 SINGLE=Choix simple
@@ -18,6 +18,8 @@ change.elements=Edition
 convert=Convertir
 convert.alien=Convertir
 convert.to=Transformer en\:
+copy.at=Copi\u00E9 le
+copy.qpool.question=Faire une copie et l'\u00E9diter
 correct.answers=Correct
 cut.value=Nombre de points n\u00E9cessaire pour "r\u00E9ussi"
 delete=Effacer
@@ -135,6 +137,7 @@ form.match=Match
 form.metadata=M\u00E9tadonn\u00E9es
 form.metadata.description=Description
 form.metadata.title=Titre
+form.pool=Banque de questions
 form.score=Score
 form.score.answer.correct=Correct
 form.score.answer.points=Points
@@ -157,6 +160,8 @@ form.testPart.navigationMode.linear=Lin\u00E9aire
 form.testPart.navigationMode.nonlinear=Non lin\u00E9aire
 form.unkown=Inconnu
 form.upload=T\u00E9l\u00E9verser un fichier
+general.identifier=$org.olat.modules.qpool.ui\:general.identifier
+general.master.identifier=$org.olat.modules.qpool.ui\:general.master.identifier
 hotspot.layout=Couleur des hotpsots
 hotspot.layout.green=Vert
 hotspot.layout.inverted=Invers\u00E9
@@ -176,6 +181,7 @@ item.session.control.attempts=Tentatives
 item.session.control.attempts.hint=Cette limitation du nombre d'essai est seulement valide pour les parties de test et non pour le test entier. Le nombre d'essai pour le test entier peut \u00EAtre limit\u00E9 dans "Options".
 item.session.control.show.solution=Afficher la solution
 item.session.control.show.solution.hint=Lors de la revue, les solutions sont \u00E9galement pr\u00E9sent\u00E9es.
+lifecycle.version=$org.olat.modules.qpool.ui\:lifecycle.version
 math.operator.bigger=>
 math.operator.biggerEquals=>\=
 math.operator.equals=\=
@@ -203,6 +209,7 @@ new.hottext.text=texte
 new.kprim=Kprim
 new.match=Match
 new.matchdraganddrop=Drag and Drop
+new.matchtruefalse=True/false
 new.mc=Choix multiples
 new.rectangle=Rectangle
 new.sc=Choix simple
@@ -212,6 +219,7 @@ new.testpart=Partie de test
 new.upload=T\u00E9l\u00E9verser un fichier
 preview=Aper\u00E7u
 preview.solution=Aper\u00E7u de la solution
+rights.owners=$org.olat.modules.qpool.ui\:rights.owners
 time.limit.max=Limite de temps (minute)
 title.add=$org.olat.ims.qti.editor\:title.add
 tools.change.copy=$org.olat.ims.qti.editor\:tools.change.copy
@@ -233,6 +241,7 @@ warning.atleastone=Choisir au moins un \u00E9l\u00E9ment s'il vous pla\u00EEt.
 warning.atleastonesection=La section ne peut pas \u00EAtre supprim\u00E9e. Un test ou un "test part" doit contenir au moins une section.
 warning.conversion.list=Des incompatibilit\u00E9s avec l'\u00E9diteur ont \u00E9t\u00E9 d\u00E9tect\u00E9es\:
 warning.conversion.standard=Il existe un risque que des donn\u00E9es soient perdues bien qu'aucune incompatibilit\u00E9 n'ait \u00E9t\u00E9 d\u00E9tect\u00E9e.
+warning.copy.from.pool=La question a \u00E9t\u00E9 copi\u00E9e depuis la banque de questions. Vous pouvez retrouver l'originale avec l'ID master.
 warning.custom.operator=Une extension non-standard a \u00E9t\u00E9 trouv\u00E9e que cette \u00E9diteur ne la supporte pas.
 warning.feedback.cutvalue=Le feedback est bas\u00E9 sur la valeur "Points n\u00E9cessaire pour 'R\u00E9ussi'" et cell-ci doit \u00EAtre d'abord d\u00E9finie.
 warning.in.use=La ressource est d\u00E9j\u00E0 utilis\u00E9e pour au moins une \u00E9valuation. L'\u00E9dition en est limit\u00E9e.
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchScoreController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchScoreController.java
index 4c5385eda1170bc3a048642e3b8c8386e98deabd..c91e91438dae43843b9d12bd36dbed57ad3ab020 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchScoreController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/MatchScoreController.java
@@ -80,16 +80,18 @@ public class MatchScoreController extends AssessmentItemRefEditorController impl
 	private int count = 0;
 	private final String mapperUri;
 	private final File itemFileRef;
+	private final boolean sourceLeft;
 	private List<MatchWrapper> sourceWrappers = new ArrayList<>();
 	private List<MatchWrapper> targetWrappers = new ArrayList<>();
 	private Map<DirectedPairValue, MatchScoreWrapper> scoreWrappers = new HashMap<>();
 	
 	public MatchScoreController(UserRequest ureq, WindowControl wControl, MatchAssessmentItemBuilder itemBuilder,
-			AssessmentItemRef itemRef, File itemFileRef, boolean restrictedEdit, boolean readOnly) {
+			AssessmentItemRef itemRef, File itemFileRef, boolean sourceLeft, boolean restrictedEdit, boolean readOnly) {
 		super(ureq, wControl, itemRef, restrictedEdit, readOnly);
 		setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale()));
 		this.itemBuilder = itemBuilder;
 		this.itemFileRef = itemFileRef;
+		this.sourceLeft = sourceLeft;
 		
 		URI assessmentObjectUri = itemFileRef.toURI();
 		mapperUri = registerCacheableMapper(null, "MatchScoreController::" + CodeHelper.getRAMUniqueID(),
@@ -133,6 +135,7 @@ public class MatchScoreController extends AssessmentItemRefEditorController impl
 		formLayout.add(scoreCont);
 		scoreCont.setLabel(null, null);
 		scoreCont.setVisible(assessmentModeEl.isSelected(1));
+		scoreCont.contextPut("sourceLeft", Boolean.valueOf(sourceLeft));
 		
 		for(SimpleAssociableChoice choice:itemBuilder.getSourceMatchSet().getSimpleAssociableChoices()) {
 			sourceWrappers.add(createMatchWrapper(choice));
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/TrueFalseEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/TrueFalseEditorController.java
new file mode 100644
index 0000000000000000000000000000000000000000..0dc283e50758d4c6b9c68a61b30e5921671317c1
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/TrueFalseEditorController.java
@@ -0,0 +1,364 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.ims.qti21.ui.editor.interactions;
+
+import static org.olat.ims.qti21.model.xml.AssessmentItemFactory.createSimpleAssociableChoice;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.components.htmlheader.jscss.JSAndCSSFormItem;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.util.Util;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.ims.qti21.model.QTI21QuestionType;
+import org.olat.ims.qti21.model.xml.interactions.MatchAssessmentItemBuilder;
+import org.olat.ims.qti21.ui.editor.AssessmentTestEditorController;
+import org.olat.ims.qti21.ui.editor.events.AssessmentItemEvent;
+
+import uk.ac.ed.ph.jqtiplus.node.item.interaction.MatchInteraction;
+import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.SimpleAssociableChoice;
+import uk.ac.ed.ph.jqtiplus.types.Identifier;
+
+/**
+ * 
+ * Initial date: 31 janv. 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class TrueFalseEditorController extends FormBasicController {
+
+	private TextElement titleEl;
+	private FormLink addRowButton;
+	private RichTextElement textEl;
+	private FormLayoutContainer answersCont;
+	
+	private int count = 0;
+	private VFSContainer itemContainer;
+	
+	private final boolean restrictedEdit, readOnly;
+	private MatchAssessmentItemBuilder itemBuilder;
+	private final List<SourceWrapper> sourceWrappers = new ArrayList<>();
+	private final Map<String,List<String>> temporaryAssociations = new HashMap<>();
+	
+	/**
+	 * 
+	 * @param ureq The user request
+	 * @param wControl The parent window control
+	 * @param itemBuilder The assessment item builder for match (matrix or drag and drop)
+	 * @param rootDirectory	The directory for images...
+	 * @param rootContainer The directory for images...
+	 * @param itemFile The assessment item file
+	 * @param matrix
+	 * @param restrictedEdit
+	 */
+	public TrueFalseEditorController(UserRequest ureq, WindowControl wControl, MatchAssessmentItemBuilder itemBuilder,
+			File rootDirectory, VFSContainer rootContainer, File itemFile, boolean restrictedEdit, boolean readOnly) {
+		super(ureq, wControl, "simple_choices_editor");
+		setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale()));
+		this.itemBuilder = itemBuilder;
+		this.readOnly = readOnly;
+		this.restrictedEdit = restrictedEdit;
+		
+		String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
+		itemContainer = (VFSContainer)rootContainer.resolve(relativePath);
+		
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		FormLayoutContainer metadata = FormLayoutContainer.createDefaultFormLayout("metadata", getTranslator());
+		if (itemBuilder.getQuestionType() == QTI21QuestionType.matchdraganddrop) {
+			metadata.setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_fragetypen_draganddrop");
+		} else {
+			metadata.setFormContextHelp("Test editor QTI 2.1 in detail#details_testeditor_fragetypen_match");
+		}
+		metadata.setRootForm(mainForm);
+		formLayout.add(metadata);
+		formLayout.add("metadata", metadata);
+		
+		titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
+		titleEl.setElementCssClass("o_sel_assessment_item_title");
+		titleEl.setMandatory(true);
+		titleEl.setEnabled(!readOnly);
+
+		String description = itemBuilder.getQuestion();
+		textEl = uifactory.addRichTextElementForQTI21("desc", "form.imd.descr", description, 8, -1, itemContainer,
+				metadata, ureq.getUserSession(), getWindowControl());
+		textEl.setEnabled(!readOnly);
+
+		//responses
+		String page = velocity_root + "/match_truefalse.html";
+		answersCont = FormLayoutContainer.createCustomFormLayout("answers", getTranslator(), page);
+		answersCont.setRootForm(mainForm);
+		answersCont.contextPut("showHeaders", (itemBuilder.getQuestionType() == QTI21QuestionType.matchdraganddrop));
+		formLayout.add(answersCont);
+		formLayout.add("answers", answersCont);
+
+		MatchInteraction interaction = itemBuilder.getMatchInteraction();
+		if(interaction != null) {
+			List<SimpleAssociableChoice> sourceChoices = itemBuilder.getSourceChoices();
+			for(SimpleAssociableChoice sourceChoice:sourceChoices) {
+				wrapSource(ureq, sourceChoice, sourceWrappers);
+			}
+			List<TargetWrapper> targetChoices = itemBuilder.getTargetChoices()
+					.stream().map(c -> new TargetWrapper(c)).collect(Collectors.toList());
+			answersCont.contextPut("targetChoices", targetChoices);
+		}
+		answersCont.contextPut("sourceChoices", sourceWrappers);
+		answersCont.contextPut("restrictedEdit", restrictedEdit || readOnly);
+		answersCont.contextPut("responseIdentifier", itemBuilder.getResponseIdentifier());
+		int maxAssociations = itemBuilder.getMatchInteraction().getMaxAssociations();
+		answersCont.contextPut("interactionMaxAssociations", maxAssociations);
+
+		JSAndCSSFormItem js = new JSAndCSSFormItem("js", new String[] { "js/jquery/qti/jquery.match.js" });
+		formLayout.add(js);
+		
+		if(!readOnly) {
+			uifactory.addFormSubmitButton("submit", answersCont);
+		}
+		if(!restrictedEdit && !readOnly) {
+			addRowButton = uifactory.addFormLink("add.match.row", answersCont, Link.BUTTON);
+			addRowButton.setElementCssClass("o_sel_match_add_row");
+			addRowButton.setIconLeftCSS("o_icon o_icon_add");
+		}
+	}
+	
+	private void wrapSource(UserRequest ureq, SimpleAssociableChoice choice, List<SourceWrapper> wrappers) {
+		String choiceContent =  itemBuilder.getHtmlHelper().flowStaticString(choice.getFlowStatics());
+		String choiceId = "answer" + count++;
+		RichTextElement choiceEl = uifactory.addRichTextElementForQTI21Match(choiceId, "form.imd.answer", choiceContent, 4, -1, itemContainer,
+				answersCont, ureq.getUserSession(), getWindowControl());
+		choiceEl.setUserObject(choice);
+		choiceEl.setEnabled(!readOnly);
+		answersCont.add("choiceId", choiceEl);
+		
+		FormLink deleteButton = uifactory.addFormLink("del_" + (count++), "delete", "delete", null, answersCont, Link.NONTRANSLATED);
+		deleteButton.setIconLeftCSS("o_icon o_icon_delete_item");
+		deleteButton.setVisible(!restrictedEdit && !readOnly);
+		deleteButton.setI18nKey("");
+		
+		SourceWrapper wrapper = new SourceWrapper(choice, choiceEl, deleteButton);
+		deleteButton.setUserObject(wrapper);
+		wrappers.add(wrapper);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = super.validateFormLogic(ureq);
+
+		commitTemporaryAssociations(ureq);
+		for(SourceWrapper sourceWrapper:sourceWrappers) {
+			sourceWrapper.setErrorSingleChoice(false);
+			List<String> answers = temporaryAssociations.get(sourceWrapper.getIdentifierString());
+			sourceWrapper.setErrorSingleChoice(answers == null || answers.size() != 1);
+		}
+
+		return allOk;
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(addRowButton == source) {
+			commitTemporaryAssociations(ureq);
+			doAddSourceRow(ureq);
+		} else if(source instanceof FormLink) {
+			FormLink button = (FormLink)source;
+			if("delete".equals(button.getCmd())) {
+				commitTemporaryAssociations(ureq);
+				SourceWrapper associationWrapper = (SourceWrapper)button.getUserObject();
+				doDeleteAssociableChoice(associationWrapper);
+			}
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		if(readOnly) return;
+		//title
+		itemBuilder.setTitle(titleEl.getValue());
+		//question
+		String questionText = textEl.getRawValue();
+		itemBuilder.setQuestion(questionText);
+		
+		if(!restrictedEdit) {
+			itemBuilder.setMultipleChoice(false);
+			itemBuilder.setShuffle(false);
+		}
+		
+		//update 
+		for(SourceWrapper sourceWrapper:sourceWrappers) {
+			SimpleAssociableChoice choice = sourceWrapper.getSimpleChoice();
+			String answer = sourceWrapper.getText().getRawValue();
+			itemBuilder.getHtmlHelper().appendHtml(choice, answer);
+		}
+
+		//correct answers
+		commitAssociations(ureq);
+
+		fireEvent(ureq, new AssessmentItemEvent(AssessmentItemEvent.ASSESSMENT_ITEM_CHANGED, itemBuilder.getAssessmentItem(), QTI21QuestionType.match));
+	}
+	
+	private void commitTemporaryAssociations(UserRequest ureq) {
+		temporaryAssociations.clear();
+		
+		for(SourceWrapper sourceWrapper:sourceWrappers) {
+			String[] targetParamIds = ureq.getHttpReq().getParameterValues(sourceWrapper.getIdentifierString());
+			if(targetParamIds != null && targetParamIds.length == 1) {
+				String sourceId = sourceWrapper.getIdentifierString();
+				String targetId = targetParamIds[0];
+				
+				List<String> targetIds = temporaryAssociations.computeIfAbsent(sourceId, s -> new ArrayList<>());
+				targetIds.add(targetId);
+				temporaryAssociations.put(sourceId, targetIds);
+			}
+		}
+	}
+	
+	private void commitAssociations(UserRequest ureq) {
+		if(restrictedEdit) return;
+		
+		temporaryAssociations.clear();
+		itemBuilder.clearAssociations();
+		for(SourceWrapper sourceWrapper:sourceWrappers) {
+			String[] targetParamIds = ureq.getHttpReq().getParameterValues(sourceWrapper.getIdentifierString());
+			if(targetParamIds != null && targetParamIds.length == 1) {
+				Identifier sourceChoiceId = sourceWrapper.getIdentifier();
+				Identifier targetChoiceId = Identifier.assumedLegal(targetParamIds[0]);
+				itemBuilder.addAssociation(sourceChoiceId, targetChoiceId);
+			}
+		}
+	}
+	
+	private void doAddSourceRow(UserRequest ureq) {
+		SimpleAssociableChoice newChoice = createSimpleAssociableChoice("Text", itemBuilder.getSourceMatchSet());
+		itemBuilder.getSourceMatchSet().getSimpleAssociableChoices().add(newChoice);
+		wrapSource(ureq, newChoice, sourceWrappers);
+		answersCont.setDirty(true);
+	}
+	
+	private void doDeleteAssociableChoice(SourceWrapper associationWrapper) {
+		if(sourceWrappers.remove(associationWrapper)) {
+			itemBuilder.removeSimpleAssociableChoice(associationWrapper.getSimpleChoice());
+		}
+		answersCont.setDirty(true);
+	}
+	
+	public class TargetWrapper {
+
+		private final Identifier choiceIdentifier;
+		private final String choiceText;
+		
+		public TargetWrapper(SimpleAssociableChoice choice) {
+			choiceText = itemBuilder.getHtmlHelper().flowStaticString(choice.getFlowStatics());
+			choiceIdentifier = choice.getIdentifier();
+		}
+		
+		public Identifier getIdentifier() {
+			return choiceIdentifier;
+		}
+
+		public String getIdentifierString() {
+			return choiceIdentifier.toString();
+		}
+
+		public String getChoiceText() {
+			return choiceText;
+		}
+	}
+
+	public class SourceWrapper {
+		
+		private FormLink deleteButton;
+		private RichTextElement choiceTextEl;
+		private final Identifier choiceIdentifier;
+		private final SimpleAssociableChoice choice;
+		
+		private boolean errorSingleChoice;
+		
+		public SourceWrapper(SimpleAssociableChoice choice, RichTextElement choiceTextEl, FormLink deleteButton) {
+			this.choice = choice;
+			this.choiceTextEl = choiceTextEl;
+			this.choiceIdentifier = choice.getIdentifier();
+			this.deleteButton = deleteButton;
+		}
+		
+		public Identifier getIdentifier() {
+			return choiceIdentifier;
+		}
+		
+		public String getIdentifierString() {
+			return choiceIdentifier.toString();
+		}
+		
+		public SimpleAssociableChoice getSimpleChoice() {
+			return choice;
+		}
+		
+		public FormLink getDeleteButton() {
+			return deleteButton;
+		}
+		
+		public RichTextElement getText() {
+			return choiceTextEl;
+		}
+		
+		public boolean isCorrect(Identifier targetChoiceId) {
+			String sourceId = choice.getIdentifier().toString();
+			String targetId = targetChoiceId.toString();
+			if(temporaryAssociations.containsKey(sourceId)) {
+				if(temporaryAssociations.get(sourceId).contains(targetId)) {
+					return true;
+				}
+			}
+			return itemBuilder.isCorrect(choiceIdentifier, targetChoiceId);
+		}
+
+		public boolean isErrorSingleChoice() {
+			return errorSingleChoice;
+		}
+
+		public void setErrorSingleChoice(boolean errorSingleChoice) {
+			this.errorSingleChoice = errorSingleChoice;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/match_score.html b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/match_score.html
index 56689877bf6d96efe3a93fae9931356fe4db25be..04bfa726f3d8a6504599d61086247f4de8c1767a 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/match_score.html
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/match_score.html
@@ -1,16 +1,19 @@
 <table class="table matchInteraction score">
 	<thead>
 		<tr>
-			<th></th>
+			#if($r.isTrue($sourceLeft)) <th></th> #end
 			#foreach($targetChoice in $targetChoices)
 				<th>${r.render($targetChoice.getSummaryEl())}
 			#end
+			#if($r.isFalse($sourceLeft)) <th></th> #end
 		</tr>
 	</thead>
 	<tbody>
 	#foreach($sourceChoice in $sourceChoices)
 		<tr>
-			<th>${r.render($sourceChoice.getSummaryEl())}</th>
+			#if($r.isTrue($sourceLeft)) 
+				<th>${r.render($sourceChoice.getSummaryEl())}</th>
+			#end
 			#set($sourceIndex = ${foreach.index})
 			#foreach($targetChoice in $targetChoices)
 				<td class="o_sel_match_${sourceIndex}_${foreach.index}">
@@ -24,6 +27,9 @@
 				#end
 				</td>
 			#end
+			#if($r.isFalse($sourceLeft)) 
+				<td>${r.render($sourceChoice.getSummaryEl())}</td>
+			#end
 		</tr>
 	#end
 	</tbody>
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/match_truefalse.html b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/match_truefalse.html
new file mode 100644
index 0000000000000000000000000000000000000000..41e288c947447485f191f922707bb8f10acf2791
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/_content/match_truefalse.html
@@ -0,0 +1,49 @@
+<fieldset class="o_form form-horizontal">
+
+<table id="qti_container_${responseIdentifier}" class="table match_true_false o_match_true_false_edit">
+	<thead>
+		<tr>
+			#foreach($targetChoice in $targetChoices)
+				<th class="o_sel_match_target_${foreach.index}" style="border-top: none;">${targetChoice.getChoiceText()}</th>
+			#end
+			<th style="border-top: none;"> </th>
+		</tr>
+	</thead>
+	<tbody>
+	#foreach($sourceChoice in $sourceChoices)
+		#set($set1Identifier = $sourceChoice.getIdentifierString())
+		<tr>
+			#set($sourceIndex = ${foreach.index})
+			#foreach($targetChoice in $targetChoices)
+				#set($set2Identifier = $targetChoice.getIdentifierString())
+				#set($responseValue = $set1Identifier + " " + $set2Identifier)
+				<td class="o_sel_match_${sourceIndex}_${foreach.index}">
+					<input id="oo_${set1Identifier}_${set2Identifier}" type="radio" name="${set1Identifier}" value="${set2Identifier}" #if(${sourceChoice.isCorrect(${targetChoice.getIdentifier()})}) checked #end #if($restrictedEdit) disabled #end/>
+					$f.appendFlexiFormDirtyForCheckbox("oo_${set1Identifier}_${set2Identifier}")
+					#if(${sourceChoice.isErrorSingleChoice()})
+						<div class="o_error">$r.translate("error.singlechoice")</div>
+					#end
+				</td>
+			#end
+			<th class="o_sel_match_source_${foreach.index}">$r.render(${sourceChoice.getText()})
+				#if($f.hasError($item))
+				<span class="o_icon o_icon_error form-control-feedback"></span>
+				#end
+				#if(!$restrictedEdit) <div class="pull-right">$r.render(${sourceChoice.getDeleteButton()})</div> #end
+			</th>
+		</tr>
+	#end
+	</tbody>
+</table>
+
+#if($r.available("add.match.row") || $r.available("submit"))
+<div class="o_button_group o_sel_match_save">
+	#if($r.available("submit"))
+		$r.render("submit")
+	#end
+	#if($r.available("add.match.row"))
+		$r.render("add.match.row")
+	#end
+</div>
+#end
+</fieldset>
\ No newline at end of file
diff --git a/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties
index 38cdabc634c102ca754601eb9395fa1371aef2bb..86857ece73128768d35b43ae4db17242a04f7494 100644
--- a/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Tue Aug 15 17:29:04 CEST 2017
+#Thu Feb 01 18:37:13 CET 2018
 about.copyright=Copyright et participations
 about.custom=
 about.custom.title=
@@ -116,6 +116,7 @@ timeout.message=Votre session a expir\u00E9 ou le serveur a \u00E9t\u00E9 red\u0
 timeout.title=Expiration de la session
 topnav.help=Aide
 topnav.help.alt=D\u00E9marrer l'aide de OpenOLAT
+warning.old.browser=La version de votre butineur n'est plus support\u00E9e. Veuillez mettre \u00E0 jour votre butineur pour qu'OpenOLAT fonctionne sans accroc. Vous trouverez plus d'information dans le manual\: <a href\="{0}" target\="_blank">Manuel d'utilisation</a>.
 wayf.homesite=Institution
 wayf.intro=Veuillez choisir votre institution.<br>Vous allez \u00EAtre redirig\u00E9(e) pour l'authentification.
 wayf.pleasechoose=Veuillez choisir votre institution...
diff --git a/src/main/java/org/olat/modules/assessment/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/assessment/ui/_i18n/LocalStrings_fr.properties
index 37a549f67104fb6026b0c5c01131f75143b4266e..5d8f134f0fa4b0d423ccd1d204cf9e824343f64f 100644
--- a/src/main/java/org/olat/modules/assessment/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/modules/assessment/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Fri Sep 23 11:41:35 CEST 2016
+#Thu Feb 01 18:26:00 CET 2018
 assessment.status.done=Evalu\u00E9
 assessment.status.inProgress=D\u00E9marr\u00E9
 assessment.status.inReview=A passer en revue
@@ -24,9 +24,11 @@ filter.passed=R\u00E9ussi
 index.introduction=Evaluez les participants de ce test avec l'outil d'\u00E9valuation. Il vous permettra d'acc\u00E9der aux r\u00E9sultats des tests et de les modifier.
 reopen=R\u00E9ouvrir
 review=Passer en revue
+run.ended=Termin\u00E9
 save.done=Sauver comme compl\u00E9t\u00E9
 statistics.small.overview=Aper\u00E7u statistiques
 table.header.assessmentStatus=Status
+table.header.completion=Progression
 table.header.elements.toReview=Passer en revue
 table.header.name=Nom d'utilisateur
 table.header.numOfAssessedIdentities=\# participants
diff --git a/src/main/java/org/olat/modules/docpool/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/docpool/ui/_i18n/LocalStrings_fr.properties
index ec400f245119e08d37e8f233e871f32d0f4a9e6c..d9200144f9c125a764bbc80baff7a862127fdbad 100644
--- a/src/main/java/org/olat/modules/docpool/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/modules/docpool/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Fri Nov 17 11:56:26 CET 2017
+#Thu Feb 01 18:27:02 CET 2018
 admin.description=La banque de documents propose une biblioth\u00E8que de documents structur\u00E9 automatiquement sur la base d'une taxonomie et des comp\u00E9tences.
 admin.menu.title=Banque de documents
 admin.menu.title.alt=Banque de documents
@@ -34,3 +34,4 @@ teach.can.read.parent.levels.explain.1=Autoriser l'acc\u00E8s en lecture des
 teach.can.read.parent.levels.explain.2=niveaux au-dessus
 teach.can.write=Autoriser l'acc\u00E8s en \u00E9criture
 teach.competence=Comp\u00E9tence enseignement
+warning.taxonomy.index.emtpy=La page d'informations de la banque de documents n'a pas \u00E9t\u00E9 configur\u00E9e. Demandez, s'il-vous-pla\u00EEt, \u00E0 l'administrateur syst\u00E8me d'en mettre une \u00E0 disposition des utilisateurs.
diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
index 42132939fed00610aec8f96bddc2433f81b0795d..ec5dab3a51662acf675106af88219f1fe05da27a 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Fri Aug 18 10:31:35 CEST 2017
+#Tue Feb 06 08:30:51 CET 2018
 access=Access
 access.binder=The people below have access to the portfolio binder\:
 access.rights=Add access rights
@@ -92,6 +92,8 @@ comment.several={0} comments
 comment.title=Comments
 comment.zero=Still no comments
 compare.evaluations=Evaluation
+confirm.close.page=Do you really want to close this entry? The entry will be marked as closed for the trainee.
+confirm.close.page.other.coaches=The following persons also have access to this entry\:
 confirmation=Confirmation
 create.binder=Create binder
 create.empty.binder=New empty binder
@@ -347,9 +349,9 @@ status.inRevision=$\:status.in.revision
 status.not.started=not started
 status.published=published
 status.submitted=submitted
-status.user.incoming=New
-status.user.inProcess=In process
 status.user.done=Done
+status.user.inProcess=In process
+status.user.incoming=New
 summary=Summary
 summary.close=Hide summary
 summary.open=Open summary
@@ -358,7 +360,6 @@ table.grading.failed.points=<span class\="o_state o_failed"><i class\="o_icon o_
 table.grading.no=no grading yet
 table.grading.passed.points=<span class\="o_state o_passed"><i class\="o_icon o_icon_passed"> </i> {0} Point(s), passed</span>
 table.grading.points={0} Point(s)
-table.header.mark=<i class\="o_icon o_icon_bookmark_header o_icon-lg" title\="Bookmark"> </i>
 table.header.categories=Categories
 table.header.change.status=Status
 table.header.closed=Closed
@@ -372,6 +373,7 @@ table.header.grading=Grading
 table.header.inRevision=$\:status.in.revision
 table.header.key=ID
 table.header.lastUpdate=Last update
+table.header.mark=<i class\="o_icon o_icon_bookmark_header o_icon-lg" title\="Bookmark"> </i>
 table.header.new=New
 table.header.numpages=\# Entries
 table.header.open=Start
diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_fr.properties
index 392425b122ae5250c3c7293cfea6f3824eacfcc9..b37c747c8fa0420003e1f32f3de883c472d5da29 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Nov 16 16:51:38 CET 2017
+#Thu Feb 01 21:29:46 CET 2018
 access=Acc\u00E8s
 access.binder=Les personnes suivantes ont acc\u00E8s au classeur\:
 access.rights=Ajouter un droit d'acc\u00E8s
@@ -72,6 +72,7 @@ binder.num.sections.pages={0} sections avec un total de {1} entr\u00E9es
 binder.status=Status
 binder.title=Portfolio {0}
 binders=Classeurs
+bookmark=Favori
 categories=Cat\u00E9gories
 categories.add=Ajouter des cat\u00E9gories
 categories.hint=Entrer le texte de la cat\u00E9gorie et passer "Entrez" pour cr\u00E9er la cat\u00E9gorie d\u00E9sir\u00E9e.
@@ -91,6 +92,8 @@ comment.several={0} commentaires
 comment.title=Commentaires
 comment.zero=Pas encore de commentaires
 compare.evaluations=Evaluation
+confirm.close.page=Voulez-vous clore cette contribution? Cette contribution sera clos pour l'apprenant.
+confirm.close.page.other.coaches=Les personnes suivantes ont acc\u00E8s \u00E0 la contribution\:
 confirmation=Confirmation
 create.binder=Cr\u00E9er un classeur
 create.empty.binder=Nouveau classeur vide
@@ -162,6 +165,7 @@ export.page=Exporter la page
 export.page.onepage=En une page
 export.page.pdf=Exporter la page au format PDF
 fileupload=Image du titre
+filter.sections.empty=Pas de sections ouvertes
 filter.show.all=Tout affichez
 firstName=Pr\u00E9nom
 go.to.trash=Aller \u00E0 la poubelle
@@ -189,6 +193,8 @@ invitation.mail.success=Les personnes invit\u00E9es ont \u00E9t\u00E9 inform\u00
 issue=Edition
 language=Langue
 lastName=Nom de famille
+leave=Enlever
+leave.explain=Voulez-vous enlever le classeur? Vous n'y aurez plus acc\u00E8s. Pour obtenir \u00E0 nouveau un acc\u00E8s, le propri\u00E9taire du classeur devra vous en accorder l'acc\u00E8s \u00E0 nouveau.
 mail=Courriel
 mail.body=Message
 mail.subject=Sujet
@@ -326,6 +332,9 @@ section.up=Vers le haut
 select.form=S\u00E9lectionner un questionnaire
 select.mymap=$org.olat.course.nodes.portfolio\:select.mymap
 series=S\u00E9ries
+shared.binders=Classeurs
+shared.bookmarks=Favoris
+shared.entries=Contributions / \u00E0 faire
 shared.with.me=Partag\u00E9 avec moi
 shared.with.me.text=Une liste de classeurs que d'autres personnes partagent avec vous.
 show.help.binder=Aide
@@ -339,6 +348,9 @@ status.inRevision=$\:status.in.revision
 status.not.started=pas commenc\u00E9
 status.published=publi\u00E9
 status.submitted=soumis
+status.user.done=Fait
+status.user.inProcess=En cours
+status.user.incoming=Nouveau
 summary=R\u00E9sum\u00E9
 summary.placeholder=Court r\u00E9sum\u00E9 du contenu de la contribution
 table.grading.failed.points=<span class\="o_state o_failed"><i class\="o_icon o_icon_failed"> </i> {0} Point(s)</span>
@@ -347,14 +359,19 @@ table.grading.passed.points=<span class\="o_state o_passed"><i class\="o_icon o_
 table.grading.points={0} point(s)
 table.header.categories=Cat\u00E9gories
 table.header.change.status=Status
+table.header.closed=Clos
 table.header.collection.date=Collect\u00E9 le
 table.header.course=Cours
 table.header.course.node=El\u00E9ment de cours
 table.header.date=Date
 table.header.down=<i class\='o_icon o_icon o_icon-lg o_icon_move_down'> </i>
+table.header.draft=$\:status.draft
 table.header.grading=Evaluation
+table.header.inRevision=$\:status.in.revision
 table.header.key=ID
 table.header.lastUpdate=Derni\u00E8re mise-\u00E0-jour
+table.header.mark=<i class\="o_icon o_icon_bookmark_header o_icon-lg" title\="Favori"> </i>
+table.header.new=Nouveau
 table.header.numpages=\# Contributions
 table.header.open=D\u00E9marrer
 table.header.open.sections=Ouvrir
diff --git a/src/main/java/org/olat/modules/qpool/QuestionType.java b/src/main/java/org/olat/modules/qpool/QuestionType.java
index 24ed4ad3b84b160b31c287391b702a0face9e377..2116a82b3fe593a16d66ea7dfe78d8ef7b153753 100644
--- a/src/main/java/org/olat/modules/qpool/QuestionType.java
+++ b/src/main/java/org/olat/modules/qpool/QuestionType.java
@@ -38,6 +38,7 @@ public enum QuestionType {
 	DRAWING,
 	MATCH,
 	MATCHDRAGANDDROP,
+	MATCHTRUEFALSE,
 	HOTTEXT,
 	UNKOWN
 
diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties
index a36cc397dc3c2589a22f8ac10c6c5a6dd392430a..687c3952b98f12752ab0c3462511275f80342e36 100644
--- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties
@@ -216,7 +216,7 @@ process.rating.description=Bewerten Sie bitte die Frage. Jede Frage kann genau e
 process.rating.title=Beurteilung
 process.rating=Bewertung
 process.start.review.button=$\:process.activate.start.review
-process.start.review.description=Nach dem Start des Beurteilungsprozesses werden alle Bewertungen der Frage gel\u00F6scht und die Frage kann nicht mehr bearbeitet werden. Wollen Sie den Beurteilungsprozess f\u00FCr die Frage "{0}" wriklich starten?
+process.start.review.description=Nach dem Start des Beurteilungsprozesses werden alle Bewertungen der Frage gel\u00F6scht und die Frage kann nicht mehr bearbeitet werden. Wollen Sie den Beurteilungsprozess f\u00FCr die Frage "{0}" wirklich starten?
 process.start.review.taxonomy.level=$\:general.taxonomy.level
 process.start.review.title=$\:process.activate.start.review
 question=Itemanalyse
diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties
index d5643ce491d4520c5c8e21b42a60da9f114cdd32..d10e9999b6c762a9d6a8a61e2754f1763a469bbb 100644
--- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Tue Apr 15 11:12:45 CEST 2014
+#Tue Feb 06 08:32:16 CET 2018
 add=+
 add.to.list=Add to list
 admin.menu.title=Question bank
@@ -11,9 +11,9 @@ classification.taxonomic.path=Subject path
 classification.taxonomic.path.incl=Subjects
 classification.taxonomy.level=Subject
 classification.taxonomy.parents=Path
+collection.add.to.source=Add questions to list "{0}"
 collection.creationDate=Created at
 collection.name=Name
-collection.add.to.source=Add questions to list "{0}"
 commands=Question
 confirm.copy.button=Copy
 confirm.copy.editable=Allow other users to edit the question
@@ -23,17 +23,18 @@ confirm.copy.title=Copy
 confirm.delete.button=Delete
 confirm.delete.confirmation=Delete all questions
 confirm.delete.confirmation.error=Please confirm
+confirm.delete.message=Do you really want to permanently delete these questions? They can not be recovered.
 confirm.delete.questions=Questions
+confirm.delete.source=Do you really want to delete this list?
 confirm.delete.title=Delete
-confirm.delete.message=Do you really want to permanently delete these questions? They can not be recovered.
 confirm.unshare=Do your really want to remove this question "{0}"?
 convert.editable=Allow other users to edit the question
+convert.format=Format
 convert.item=Convert
-convert.item.not.possible=You haven't selected any question you can convert.
 convert.item.msg=Do you want to convert the {0} question(s) in the following format?
+convert.item.not.possible=You haven't selected any question you can convert.
 convert.item.successful={0} question(s) successfully converted.
 convert.item.warning={0} was not converted.
-convert.format=Format
 convert.qti21.hint=You will find information about the conversion from QTI 1.2 to QTI 2.1 in the manual
 convert.questions=Questions
 copy=Copy
@@ -177,14 +178,16 @@ menu.pools.main=Catalog
 menu.pools.main.alt=Catalog
 menu.queries=Questions
 menu.queries.all=All questions
-menu.queries.whithout.taxonomy.level=Without subject
 menu.queries.whithout.author=Without author
+menu.queries.whithout.taxonomy.level=Without subject
+menu.queries.without.author=Without author
+menu.queries.without.taxonomy.level=Without subject
 menu.ratings=Ratings
 menu.review=Review
 menu.share=Public shares
-metadatas=Metadata
-metadata.show=Metadata
 metadata.hide=Metadata
+metadata.show=Metadata
+metadatas=Metadata
 my.competences=My subjects
 my.list=My lists
 my.share=My shares
@@ -197,19 +200,23 @@ pool.name=Name
 pool.owners=Owners
 pool.public=Public
 presentation.title=Question bank
-process.activate.not.reviewable.description=It is not possible to review questions in the format 'QTI 1.2'. Please previously convert the question to the format 'QTI 2.1'.
+previous=Previous
 process.activate.locked=The question is opened by '{0}'. Therefore, you are not able to start the review process.
+process.activate.not.reviewable.description=It is not possible to review questions in the format 'QTI 1.2'. Please previously convert the question to the format 'QTI 2.1'.
 process.activate.review=Review question
 process.activate.review.description=The question is in the status 'Review'. Please review the question carefully to technical correctness and with regards to content. Subsequently you have to push the button below to rate the question. 
 process.activate.start.review=Start review process
 process.activate.start.review.description=You can now create and revise the question, until it has a sufficient quality. If the question is completely created, you have to start the review process by pushing the button below. Afterwards the question can not be edited anymore.
 process.comment=Comment
 process.confirm.endOfLife=If a question is end of life, the question can not be used anymore. Do you really want to set the end of life for the question "{0}"?
-process.review=Review
+process.endOfLife=End of life
+process.final=Final
+process.rating=Rating
 process.rating.button=Rate
 process.rating.description=Please rate the question. You are only once able to rate a question. After the rating the question is not in the list of the review questions anymore.
 process.rating.title=Review
-process.rating=Rating
+process.review=Review
+process.revision=Revision
 process.start.review.button=$\:process.activate.start.review
 process.start.review.description=After the start of the review process all ratings are deleted and the question can not be edited anymore. Do you really want to start the review process for the question "{0}"?
 process.start.review.taxonomy.level=$\:general.taxonomy.level
@@ -254,14 +261,14 @@ share.item.pools=Share with pools
 share.options=Do you want to allow other users to edit the imported question(s)? 
 share.pool=Share with pool
 shared=Shared
+sharing.pools.empty.table=This question is not shared in any pool.
 sharing.shares=Groups
 sharing.shares.empty.table=This question is not shared with any group.
-sharing.pools.empty.table=This question is not shared in any pool.
 source.status.draft=$\:lifecycle.status.draft ({0})
+source.status.endOfLife=$\:lifecycle.status.endOfLife ({0})
+source.status.finalVersion=$\:lifecycle.status.finalVersion ({0})
 source.status.review=$\:lifecycle.status.review ({0})
 source.status.revised=$\:lifecycle.status.revised ({0})
-source.status.finalVersion=$\:lifecycle.status.finalVersion ({0})
-source.status.endOfLife=$\:lifecycle.status.endOfLife ({0})
 technical=Technical
 technical.creation=Created
 technical.editor=Editor
diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_fr.properties
index a37ada097f268361a8b6c779a054f7f6a886706b..6d1ad037b5f96c8dd3d8e6ebec7e78012810ce20 100644
--- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Nov 16 19:06:10 CET 2017
+#Fri Feb 02 08:26:04 CET 2018
 add=+
 add.to.list=Ajouter \u00E0 la liste
 admin.menu.title=Banque de questions
@@ -11,10 +11,24 @@ classification.taxonomic.path=Sujet chemin
 classification.taxonomic.path.incl=Sujets
 classification.taxonomy.level=Sujet
 classification.taxonomy.parents=Chemin
+collection.add.to.source=Ajouter des questions \u00E0 la liste "{0}"
 collection.creationDate=Cr\u00E9er le
 collection.name=Nom
+commands=Questions
+confirm.copy.button=Copier
+confirm.copy.editable=D'autres utilisateurs ont le droit d'\u00E9diter la question.
+confirm.copy.message=Voulez-vous copier la question?
+confirm.copy.questions=Questions
+confirm.copy.title=Copier
+confirm.delete.button=Effacer
+confirm.delete.confirmation=Effacer toutes les questions
+confirm.delete.confirmation.error=Confirmez s'il-vous-pla\u00EEt.
+confirm.delete.message=Voulez-vous vraiment effacer ces questions? Elles ne pourront plus \u00EAtre restaur\u00E9es.
+confirm.delete.questions=Questions
 confirm.delete.source=Voulez-vous vraiment effacer cette liste?
+confirm.delete.title=Effacer
 confirm.unshare=Voulez-vous vraiment enlever cette question de "{0}"?
+convert.editable=D'autres utilisateurs peuvent \u00E9diter la question.
 convert.format=Format
 convert.item=Convertir
 convert.item.msg=D\u00E9sirez-vous convertir la ou les questions "{0}" au format suivant?
@@ -22,12 +36,16 @@ convert.item.not.possible=Vous n'avez pas s\u00E9lectionn\u00E9 de questions qui
 convert.item.successful={0} question(s) ont \u00E9t\u00E9 converties avec succ\u00E8s.
 convert.item.warning={0} question(s) n'ont pas \u00E9t\u00E9 converties.
 convert.qti21.hint=Vous trouverez plus d'informations sur la conversion QTI 1.2 vers QTI 2.1 dans le manuel d'utilisation
+convert.questions=Questions
 copy=Copier
 create.collection.description=Donnez le nom de votre liste.
 create.list=Cr\u00E9er une liste
 create.pool=Cr\u00E9er un pool
 create.success=1 question a \u00E9t\u00E9 cr\u00E9er avec succ\u00E8s.
 create.test=Cr\u00E9er un test
+create.test.format.qti12=QTI 1.2
+create.test.format.qti21=QTI 2.1
+create.test.no.formats=Les questions s\u00E9lectionn\u00E9es sont dans un format qui ne permet pas de cr\u00E9er un test.
 delete.collection=Effacer la liste
 delete.item=Effacer
 delete.pool=Effacer un pool
@@ -43,8 +61,41 @@ educational.learningTime.minute=m
 educational.learningTime.second=s
 error.input.toolong=Le texte que vous avez entr\u00E9 est trop long ({1} caract\u00E8res). Limitez-vous s'il vous pla\u00EEt \u00E0 {1} caract\u00E8res.
 error.select.one=Vous devez s\u00E9lectionner au moins une question.
+error.select.one.author=Vous devez s\u00E9lectionner au moins une question qu'auteur peut \u00E9diter.
+error.select.one.convert=Vous devez s\u00E9lectionner au moins une question qui puisse \u00EAtre convertie dans un autre format.
+error.select.one.copy=Vous devez s\u00E9lectionner au moins une question que vous puissiez copier.
+error.select.one.create.test=Vous devez s\u00E9lectionner au moins une question que vous puissiez utiliser dans un test.
+error.select.one.delete=Vous devez s\u00E9lectionner au moins une question que vous puissiez effacer.
+error.select.one.export=Vous devez s\u00E9lectionner au moins une question que vous puissiez exporter.
+error.select.one.metadata=Vous devez s\u00E9lectionner au moins une question dont vous puissiez changer les m\u00E9ta-donn\u00E9es.
+error.select.one.remove=Vous devez s\u00E9lectionner au moins une question \u00E0 enlever.
 error.wrongFloat=Format num\u00E9rique inad\u00E9quat. Exemple\: 1.0, 0.5, 0.2
 export.item=Exporter
+export.log=Fichier log
+export.log.header.additional.informations=$\:general.additional.informations
+export.log.header.assessment.type=$\:question.assessmentType
+export.log.header.context=$\:educational.context
+export.log.header.copyright=$\:rights.copyright
+export.log.header.coverage=$\:general.coverage
+export.log.header.creator=$\:rights.creator
+export.log.header.differentiation=$\:question.differentiation
+export.log.header.difficulty=$\:question.difficulty
+export.log.header.item.type=$\:question.type
+export.log.header.keywords=$\:general.keywords
+export.log.header.language=$\:general.language
+export.log.header.learningTime=$\:educational.learningTime
+export.log.header.log.action=Action
+export.log.header.log.author=Chang\u00E9 par
+export.log.header.log.date=Date
+export.log.header.numOfAnswerAlternatives=$\:question.numOfAnswerAlternatives
+export.log.header.status=$\:lifecycle.status
+export.log.header.stdevDifficulty=$\:question.stdevDifficulty
+export.log.header.taxonomic.path=$\:classification.taxonomic.path
+export.log.header.title=$\:general.title
+export.log.header.topic=$\:general.topic
+export.log.header.usage=$\:question.usage
+export.log.header.version=$\:lifecycle.version
+export.overview.accept=Pris en compte
 general=G\u00E9n\u00E9ral
 general.additional.informations=Informations additionnelles
 general.additional.informations.long=$\:general.additional.informations
@@ -55,6 +106,9 @@ general.key=Cl\u00E9 DB
 general.keywords=Mots cl\u00E9s
 general.language=Langue
 general.master.identifier=ID master
+general.taxonomy.level=Sujet
+general.taxonomy.path={0}
+general.title=Titre
 general.topic=Th\u00E8me
 import.excellike.12=Importer QTI 1.2 un fichier Excel par copier coller
 import.excellike.21=Importer QTI 2.1 un fichier Excel par copier coller
@@ -69,6 +123,7 @@ item.collectioned=La question {0} a \u00E9t\u00E9 ajout\u00E9e \u00E0 la liste.
 item.copied={0} question(s) ont \u00E9t\u00E9 copi\u00E9es.
 item.deleted=La question a \u00E9t\u00E9 effac\u00E9e.
 item.level=Niveau
+item.numbers.of={0} / {1}
 item.pooled=La question {0} a \u00E9t\u00E9 ajout\u00E9e au pool.
 item.shared=La question {0} a \u00E9t\u00E9 partag\u00E9e.
 item.type.drawing=Dessin
@@ -86,13 +141,18 @@ item.type.unkown=Inconnu
 item.type.upload=T\u00E9l\u00E9verser un fichier
 lifecycle.status=Statut
 lifecycle.status.draft=Ebauche
+lifecycle.status.endOfLife=End of life
 lifecycle.status.finalVersion=Final
+lifecycle.status.last.modified=Dernier changement de statut
 lifecycle.status.review=En cours d'examen
 lifecycle.status.revised=R\u00E9vis\u00E9
 lifecycle.status.unavailable=Indisponible
 lifecycle.version=Version
 list=Listes
+locked.readonly=La question est momentan\u00E9ment ouverte par "{0}". C'est pourquoi vous ne pouvez pas l'\u00E9diter pour l'instant.
+manage.owners=Editer
 mark=<i class\="o_icon o_icon_bookmark_header o_icon-lg" title\="Favoris"> </i>
+mark.add.to.source=Ajouter les questions aux favoris.
 menu.admin=Administration
 menu.admin.alt=Administration
 menu.admin.levels=Niveau
@@ -100,30 +160,65 @@ menu.admin.levels.alt=Niveau
 menu.admin.licenses=Licenses
 menu.admin.licenses.alt=Administrer les licenses
 menu.admin.pools=Gestion des pools
+menu.admin.review.process=Processus d'\u00E9valuation
 menu.admin.studyfields=Sujet
 menu.admin.studyfields.alt=Sujet
 menu.admin.types=Type de questions
 menu.admin.types.alt=Administrer les types de questions
+menu.database=Ma banque de questions
+menu.database.alt=Ma banque de questions
 menu.database.favorit=Mes favoris
 menu.database.favorit.alt=Mes favoris
 menu.database.my=Mes questions
 menu.database.my.alt=Mes questions
+menu.final=Final
 menu.pools=Pool
 menu.pools.alt=Pool
 menu.pools.main=Catalogue
 menu.pools.main.alt=Catalogue
+menu.queries=Questions
+menu.queries.all=Toutes les questions
+menu.queries.without.author=Sans auteur
+menu.queries.without.taxonomy.level=Sans sujet
+menu.ratings=Evaluations
+menu.review=Evaluation
 menu.share=Partag\u00E9
+metadata.hide=M\u00E9ta-donn\u00E9es
+metadata.show=M\u00E9ta-donn\u00E9es
 metadatas=M\u00E9tadonn\u00E9es
+my.competences=Mes sujets
 my.list=Mes listes
 my.share=Partag\u00E9s
 new.item=Cr\u00E9er une question
 next=Suivant
+numberOfRatings=Nombre d'\u00E9valuations
+pool.add.to.source=Ajouter les questions au pool "{0}".
 pool.key=ID
 pool.name=Nom
 pool.owners=Propri\u00E9taires
 pool.public=Public
 presentation.title=Banque de questions
 previous=Pr\u00E9c\u00E9dent
+process.activate.locked=La question est momentan\u00E9ment ouverte par "{0}". Le processus d'\u00E9valuation ne peut par cons\u00E9quent pas \u00EAtre d\u00E9marrer pour l'instant.
+process.activate.not.reviewable.description=Les questions au format QTI 1.2 ne peuvent pas \u00EAtre \u00E9valu\u00E9es. Convertissez-les d'abord au format QTI 2.1.
+process.activate.review=Evaluer la question
+process.activate.review.description=La question est pass\u00E9e en revue. V\u00E9rifier attentivement , s'il vous pla\u00EEt, l'exactitude technique et la justesse de la question avant de soumettre votre \u00E9valuation avec le bouton ci-dessous.
+process.activate.start.review=D\u00E9marrer le processus d'\u00E9valuation
+process.activate.start.review.description=Vous pouvez cr\u00E9er ici une question et l'am\u00E9liorer jusqu'\u00E0 ce qu'elle soit de qualit\u00E9 suffisante. Lorsque la question est termin\u00E9e, vous pouvez commencer le processus d'\u00E9valuation. La question ne peut plus \u00EAtre modifi\u00E9e par la suite.
+process.comment=Commentaire
+process.confirm.endOfLife=Une question avec le  "$\:lifecycle.status.endOfLife" ne heut plus \u00EAtre utilis\u00E9e. Voulez-vous mettre le statut "$\:lifecycle.status.endOfLife" \u00E0 la question "{0}"?
+process.endOfLife=End of life
+process.final=Final
+process.rating=Evaluation
+process.rating.button=Evaluer
+process.rating.description=Evaluez la question s'il-vous-pla\u00EEt. Chaque question peut \u00EAtre \u00E9valuer exactement une fois. Apr\u00E8s \u00E9valuation, la question n'appara\u00EEtra plus dans la liste des questions \u00E0 \u00E9valuer.
+process.rating.title=Evaluation
+process.review=Evaluation
+process.revision=R\u00E9vision
+process.start.review.button=$\:process.activate.start.review
+process.start.review.description=Apr\u00E8s le d\u00E9but du processus d'\u00E9valuation, toutes les \u00E9valuations de la question seront effac\u00E9es et la question ne pourra plus \u00EAtre \u00E9dit\u00E9e. Voulez-vous commencer l'\u00E9valuation de la question "{0}"?
+process.start.review.taxonomy.level=$\:general.taxonomy.level
+process.start.review.title=$\:process.activate.start.review
 question=Analyse \u00E9l\u00E9ment
 question.assessmentType=Type de test
 question.assessmentType.both=Tous les deux
@@ -140,31 +235,48 @@ question.type=Type
 question.usage=Utilisation dans des tests
 quickview=<i class\='o_icon o_icon_quickview'> </i>
 rating=Evaluation
+rating.creation.date=Date
+rating.empty.table=Cette question n'a pas encore \u00E9t\u00E9 \u00E9valu\u00E9e.
 remove=-
 rename.collection=Renommer la liste
 rights=Droits
 rights.copyright=Copyright
 rights.creator=Propri\u00E9taires
 rights.description=License
+rights.owners=Auteurs
 root.taxonomyLevel=Sujets
 select.group=Partag\u00E9
 select.item=$\:details
 select.pool=Partagez dans un pool
+share.add.to.source=Ajouter les questions au groupe "{0}".
 share.editable=Editer
 share.group=Partagez avec un groupe
 share.item=Partagez
+share.item.group=Partagez par le groupe "{0}"
+share.item.groups=Partage par groupes
+share.item.pool=Partage par le pool "{0}"
+share.item.pools=Partage par pools
 share.options=Voulez-vous permettre \u00E0 une autre personne d'\u00E9diter cette/ces question(s)?
 share.pool=Partagez dans un pool
 shared=Partag\u00E9
+sharing.pools.empty.table=Cette question n'est partag\u00E9 par aucun pool.
 sharing.shares=Groupes
+sharing.shares.empty.table=Cette question n'est partag\u00E9 par aucun groupe.
+source.status.draft=$\:lifecycle.status.draft ({0})
+source.status.endOfLife=$\:lifecycle.status.endOfLife ({0})
+source.status.finalVersion=$\:lifecycle.status.finalVersion ({0})
+source.status.review=$\:lifecycle.status.review ({0})
+source.status.revised=$\:lifecycle.status.revised ({0})
 technical=Technique
 technical.creation=Cr\u00E9ation
 technical.editor=Editeur
 technical.editorVersion=Version de l'\u00E9diteur
 technical.format=Format
 technical.lastModified=Modifi\u00E9
+technical.statusLastModified=Dernier changement de statut
 technics=Technique
 topnav.qpool=Banque de questions
 topnav.qpool.alt=Banque de questions et partage
 unshare.item=Enlever
 used=Utilis\u00E9
+warning.qpool.index.emtpy=La page d'informations de la banque de documents n'a pas \u00E9t\u00E9 configur\u00E9e. Demandez \u00E0 l'administrateur syst\u00E8me d'ajouter une page d'informations dans <strong>Administration de la banque de questions</strong>.
diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java b/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java
index 0134f440b376542105d78631063340b296501ca0..92014e037b5bcbaf2a28ab992e92c28a4768bf75 100644
--- a/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java
@@ -52,7 +52,6 @@ import org.olat.core.util.Util;
 import org.olat.core.util.i18n.ui.SingleKeyTranslatorController;
 import org.olat.modules.qpool.QPoolService;
 import org.olat.modules.qpool.model.QEducationalContext;
-import org.olat.modules.qpool.ui.QuestionPoolMainEditorController;
 import org.olat.modules.qpool.ui.QuestionsController;
 
 /**
@@ -173,7 +172,7 @@ public class QEducationalContextsAdminController extends FormBasicController {
 
 		String[] keys2Translate = { key2Translate };
 		singleKeyTrnsCtrl = new SingleKeyTranslatorController(ureq, getWindowControl(), keys2Translate,
-				QuestionPoolMainEditorController.class);
+				QuestionsController.class);
 		listenTo(singleKeyTrnsCtrl);
 
 		removeAsListenerAndDispose(cmc);
@@ -293,8 +292,8 @@ public class QEducationalContextsAdminController extends FormBasicController {
 				case levelI18n: {
 					String i18nKey = "item.level." + level.getLevel().toLowerCase();
 					String translation = getTranslator().translate(i18nKey);
-					if(translation.length() > 256) {
-						return getTranslator().translate("translation.missing");
+					if(i18nKey.equals(translation) || translation.length() > 256) {
+						return level.getLevel();
 					}
 					return translation;
 				}
diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java b/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java
index eb056481e26b02c566acff7e23fa01bb3a0a6412..d24399a5699aa3ffcca3ea79a03b822642670373 100644
--- a/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java
@@ -52,7 +52,6 @@ import org.olat.core.util.Util;
 import org.olat.core.util.i18n.ui.SingleKeyTranslatorController;
 import org.olat.modules.qpool.QPoolService;
 import org.olat.modules.qpool.model.QItemType;
-import org.olat.modules.qpool.ui.QuestionPoolMainEditorController;
 import org.olat.modules.qpool.ui.QuestionsController;
 
 /**
@@ -173,7 +172,7 @@ public class QItemTypesAdminController extends FormBasicController {
 
 		String[] keys2Translate = { key2Translate };
 		singleKeyTrnsCtrl = new SingleKeyTranslatorController(ureq, getWindowControl(), keys2Translate,
-				QuestionPoolMainEditorController.class);
+				QuestionsController.class);
 		listenTo(singleKeyTrnsCtrl);
 
 		removeAsListenerAndDispose(cmc);
diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties
index 5d5b06e917acb0fc6a2cccf58425e4694401fa06..d765bb2bf5618e9b88bfdb43b8f1692885df3e14 100644
--- a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties
@@ -78,7 +78,6 @@ taxonomy.selectable=Ausw\u00E4lbare Fachbereiche
 taxonomyLevel.deleted=Fachbereich wurde erfolgreich gel\u00F6scht
 taxonomyLevel.notdeleted=Fachbereich konnte nicht gel\u00F6scht werden, eventuell wird er bereits verwendet.
 translation=\u00dcbersetzung
-translation.missing=Keine \u00dcbersetzung
 type.key=ID
 type.translation=\u00DCbersetzung
 type.type=Typ
diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties
index bdd72fd6e98ee67a126d2e728b11582cdabfe187..103546671ff4ea8434c63041edc9cdd28eb0fa3f 100644
--- a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Wed Aug 28 17:36:55 CEST 2013
+#Tue Feb 06 08:32:43 CET 2018
 admin.configuration.title=Question bank
 admin.levels.intro=Create those levels that apply to your organisations educational level. Examples for levels in an academic context could be elementary school, middle school, high school, bachelor, master. Within a corporation context, levels could be the following\: without apprenticeship, with vocational training, administration, middle management, CO
 admin.licenses.intro=You can create more license types if the default license types are not sufficient. Please note that the default licenses cannot be deleted.
@@ -8,6 +8,7 @@ admin.review.process.decision.type=Decision method
 admin.review.process.title=Review process
 admin.studyfields.intro=Subjects allow for technical indexing the question items. It's organized as a hierarchical structure for modelling the potential degree programs. Select the "$org.olat.modules.taxonomy.ui\:add.taxonomy.level" in order to create a new subject, or select an existing one for editing purposes.
 admin.types.intro=Create more question types if the existing default types aren't sufficient. Please note that the default question types can not be deleted.
+average.rating.for.final=Average rating for status "final"
 collections.enabled=Lists
 create.infos.page=Create infos page
 create.level=Create level
@@ -15,12 +16,12 @@ create.license=Create license
 create.type=Create type
 delete.level=Delete
 delete.level.confirm=Do you really want to delete this level?
-delete.taxonomyLevel=Delete
-delete.taxonomyLevel.confirm=Do you really want to delete this subject "{0}"?
-delete.qustions.without.author=Delete questions when author deleted
-delete.qustions.without.author.info=When a user is deleted, he is removed as author from his question items. If this option is enabled and the user is the only author of the question item, the question item is deleted as well.
 delete.license=Delete
 delete.license.confirm=Do you really want to delete this license?
+delete.qustions.without.author=Delete questions when author deleted
+delete.qustions.without.author.info=When a user is deleted, he is removed as author from his question items. If this option is enabled and the user is the only author of the question item, the question item is deleted as well.
+delete.taxonomyLevel=Delete
+delete.taxonomyLevel.confirm=Do you really want to delete this subject "{0}"?
 delete.type=Delete
 delete.type.confirm=Do you really want to delete this type?
 edit.info.page=Edit infos page
@@ -32,36 +33,35 @@ error.item.type.unique=A question type with this name already exists.
 final.visibility=Visibility of final questions
 final.visibility.manager=Manager
 final.visibility.manager.teacher=Manager, Teacher
+import.create.subject=Create subject when importing
 item.license.deleted=License has been successfully deleted.
 item.license.notdeleted=License cannot be deleted, it is probably in use.
 item.type.deleted=Type has been successfully deleted.
 item.type.notdeleted=Type cannot be deleted, it is probably in use.
-import.create.subject=Create subject when importing
 level.key=ID
 level.level=Level
 level.translation=Translation
 license.id=ID
 license.key=License
+lower.limit=Lower limit for positive decision
 lower.limit.desc=The decision method "Lower limit" changes the status of a question to "$org.olat.modules.qpool.ui\:lifecycle.status.finalVersion", if the minimum number of ratings is reached and if all ratings are equal or higher then the lower limit. If a rating is lower then the lower limit, the question status this immediately changed to "$org.olat.modules.qpool.ui\:lifecycle.status.revised", even if the minimum number of ratings is not reached yet.
 lower.limit.provider.name=Lower limit
-lower.limit=Lower limit for positive decision
 number.of.ratings=Number of ratings per question
 pool.manager.allowed=The pool manager is allowed to
 pool.manager.edit.matadata=see all questions and edit the metadata
 pool.manager.edit.status=change the status of a question
-pool.manager.educational.context=edit the settings "$:\segment.educational.context"
-pool.manager.licenses=edit the settings "$:\segment.licenses"
-pool.manager.item.types=edit the settings "$:\segment.item.types"
-pool.manager.pools=edit the settings "$:\segment.pools"
-pool.manager.review.process=edit the settings "$:\segment.review.process"
-pool.manager.taxonomy=edit the settings "$:\segment.taxonomy"
+pool.manager.educational.context=edit the settings "$\:segment.educational.context"
+pool.manager.item.types=edit the settings "$\:segment.item.types"
+pool.manager.licenses=edit the settings "$\:segment.licenses"
+pool.manager.pools=edit the settings "$\:segment.pools"
+pool.manager.review.process=edit the settings "$\:segment.review.process"
+pool.manager.taxonomy=edit the settings "$\:segment.taxonomy"
 pools.enabled=Pools
 reset.status=Reset all questions to state "draft".
 review.process.confirm.enable.button=Enable
-review.process.confirm.enable.description=It is recommended to reset all questions the the question bank to the status "draft" to create a clean starting position for the introduction of the review process.<br\><br\>The resetting of the question states can not be undone!
+review.process.confirm.enable.description=It is recommended to reset all questions the the question bank to the status "draft" to create a clean starting position for the introduction of the review process.<br><br>The resetting of the question states can not be undone\!
 review.process.confirm.enable.title=Enable review process
 review.process.enabled=Review process
-shares.enabled=Groups
 segment.configuration=Question bank
 segment.educational.context=Levels
 segment.info.page=Infos page
@@ -71,13 +71,13 @@ segment.pools=Pools
 segment.review.process=Review process
 segment.taxonomy=Subjects
 selected.taxonomy.tree=Taxonomy
+shares.enabled=Groups
 taxonomy.all=All subjects
 taxonomy.competences=Subjects with competence "teach" or "manage"
 taxonomy.selectable=Selectable subjects
 taxonomyLevel.deleted=Subject has been successfully deleted.
 taxonomyLevel.notdeleted=The subject cannot be deleted, it is probably in use.
 translation=Translation
-translation.missing=Translation missing
 type.key=ID
 type.translation=Translation
 type.type=Type
diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_fr.properties
index bf7585fea641527d9921ac377ee4480cb12dff3e..80488125de013ecd44189a9bb0503127be59f158 100644
--- a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_fr.properties
@@ -1,27 +1,39 @@
-#Sat Nov 02 16:23:20 CET 2013
+#Fri Feb 02 08:33:46 CET 2018
 admin.configuration.title=Banque de questions
 admin.levels.intro=Cr\u00E9er les niveaux qui s'appliquent aux niveaux d'\u00E9ducation de votre organisation. Exemples de niveaux dans un contexte acad\u00E9mique pourrait \u00EAtre l'\u00E9cole primaire, coll\u00E8ge, lyc\u00E9e, bachelor, master. Dans le contexte d'une soci\u00E9t\u00E9, les niveaux pourraient \u00EAtre les suivantes\: sans apprentissage, formation professionnelle, administration...
 admin.licenses.intro=Vous pouvez cr\u00E9er plusieurs types de licence si ceux par d\u00E9faut ne sont pas suffisants. Veuillez noter que les licences par d\u00E9faut ne peuvent pas \u00EAtre supprim\u00E9es.
+admin.pool.manager.title=Permissions des administrateurs de la banque de questions
 admin.pools.intro=Cr\u00E9ez un ou plusieurs pools de questions. Un pool est une banque de questions qui permet \u00E0 tous les utilisateurs avec droits d'auteur d'\u00E9changer des \u00E9l\u00E9ments - questions (si en acc\u00E8s public). Vous pouvez \u00E9galement opter pour un pool partag\u00E9 par seulement quelques auteurs, par exemple le personnel d'un d\u00E9partement (en acc\u00E8s priv\u00E9).
+admin.review.process.decision.type=M\u00E9thode d'\u00E9valuation
+admin.review.process.title=Processus d'\u00E9valuation
 admin.studyfields.intro=Les sujets permettent une indexation technique des questions. Elle est organis\u00E9e comme une structure hi\u00E9rarchique pour mod\u00E9liser les \u00E9ventuels programmes d'\u00E9tudes. S\u00E9lectionner le r\u00E9pertoire "$org.olat.modules.taxonomy.ui\:add.taxonomy.level" afin de cr\u00E9er un nouveau sujet, ou s\u00E9lectionnez un existant pour l'\u00E9diter.
 admin.types.intro=Cr\u00E9er davantage de types de questions si les types par d\u00E9faut ne sont pas suffisants. Veuillez noter que les types de questions par d\u00E9faut ne peuvent pas \u00EAtre supprim\u00E9s.
+average.rating.for.final=Evaluation moyenne pour obtenir le statut "final"
+collections.enabled=Listes
 create.infos.page=Cr\u00E9er une page d'information
 create.level=Cr\u00E9er un niveau
 create.license=Cr\u00E9er une license
 create.type=Cr\u00E9er un type
 delete.level=Effacer
 delete.level.confirm=Voulez-vous vraiment effacer ce niveau?
-delete.taxonomyLevel=Effacer
-delete.taxonomyLevel.confirm=Voulez-vous vraiment effacer le sujet suivant "{0}"?
 delete.license=Effacer
 delete.license.confirm=Voulez-vous vraiment effacer cette license?
+delete.qustions.without.author=Effacer les questions si l'auteur est effac\u00E9
+delete.qustions.without.author.info=Apr\u00E8s l'effacement d'un utilisateur, celui-ci sera enlever de la liste des auteurs de toutes les questions de la banque. Si l'option en a \u00E9t\u00E9 activ\u00E9e, et que cette personne est l'unique auteur d'une question, la question sera \u00E9galement effac\u00E9e.
+delete.taxonomyLevel=Effacer
+delete.taxonomyLevel.confirm=Voulez-vous vraiment effacer le sujet suivant "{0}"?
 delete.type=Effacer
 delete.type.confirm=Voulez-vous vraiment effacer ce type?
 edit.info.page=Editer la page d'informations
 edit.taxonomyLevel=Editer le sujet
 educational.context.deleted=Le sujet a \u00E9t\u00E9 effac\u00E9 avec succ\u00E8s.
 educational.context.notdeleted=Le sujet n'a pas pu \u00EAtre effac\u00E9, il est probablement utilis\u00E9.
-error.item.type.unique=Un type de question avec ce nom existe d\u00e9j\u00e0.
+error.integer.positive=L'entr\u00E9e doit \u00EAtre un nombre positif.
+error.item.type.unique=Un type de question avec ce nom existe d\u00E9j\u00E0.
+final.visibility=Visibilit\u00E9 des questions "final"
+final.visibility.manager=Administrateur
+final.visibility.manager.teacher=Administrateur, enseignant
+import.create.subject=Cr\u00E9er les sujets \u00E0 l'importation
 item.license.deleted=Le license a \u00E9t\u00E9 effac\u00E9 avec succ\u00E8s.
 item.license.notdeleted=Le license n'a pas pu \u00EAtre effac\u00E9 avec succ\u00E8s, il est probablement encore utilis\u00E9.
 item.type.deleted=Le type a \u00E9t\u00E9 effac\u00E9 avec succ\u00E8s.
@@ -31,10 +43,41 @@ level.level=Niveau
 level.translation=Traduction
 license.id=ID
 license.key=License
+lower.limit=Limite inf\u00E9rieure des \u00E9valuations positives
+lower.limit.desc=Avec la m\u00E9thode d'\u00E9valuation "Limite inf\u00E9rieure", une question obtiendra le status "$org.olat.modules.qpool.ui\:lifecycle.status.finalVersion" si le nombre minimum d'\u00E9valuation a \u00E9t\u00E9 atteint et que toutes les \u00E9valuations sont sup\u00E9rieures ou \u00E9gales \u00E0 cette limite. Si une \u00E9valuation se situe sous la limite, la question passe imm\u00E9diatement au status "$org.olat.modules.qpool.ui\:lifecycle.status.revised" avant m\u00EAme que le nombre minimal d'\u00E9valuations ne soit atteint.
+lower.limit.provider.name=Limite inf\u00E9rieure
+number.of.ratings=Nombre d'\u00E9valuation par question
+pool.manager.allowed=L'administrateur de la banque de donn\u00E9es peut
+pool.manager.edit.matadata=voir toutes les questions et \u00E9diter les m\u00E9ta-donn\u00E9es
+pool.manager.edit.status=changer le status de toutes les questions
+pool.manager.educational.context=\u00E9diter les param\u00E8tres "$\:segment.educational.context"
+pool.manager.item.types=\u00E9diter les param\u00E8tres "$\:segment.item.types"
+pool.manager.licenses=\u00E9diter les param\u00E8tres "$\:segment.licenses"
+pool.manager.pools=\u00E9diter les param\u00E8tres "$\:segment.pools"
+pool.manager.review.process=\u00E9diter les param\u00E8tres "$\:segment.review.process"
+pool.manager.taxonomy=\u00E9diter les param\u00E8tres "$\:segment.taxonomy"
+pools.enabled=Pools
+reset.status=Remettre le status "Brouillon" \u00E0 toutes questions
+review.process.confirm.enable.button=activ\u00E9
+review.process.confirm.enable.description=Il est recommand\u00E9 de r\u00E9initialis\u00E9 tous les status des questions de la banque pour avoir une base uniforme pour d\u00E9buter avec le nouveau processus d'\u00E9valuation.<br><br>Une fois les status r\u00E9initialis\u00E9s, les status pr\u00E9c\u00E9dents ne pourront pas \u00EAtre r\u00E9activ\u00E9s.
+review.process.confirm.enable.title=Activer le processus d'\u00E9valuation
+review.process.enabled=Processus d'\u00E9valuation
+segment.configuration=Banque de questions
+segment.educational.context=Niveaux
 segment.info.page=Page d'informations
+segment.item.types=Type de questions
+segment.licenses=Licenses
+segment.pools=Administration pool
+segment.review.process=Processus d'\u00E9valuation
+segment.taxonomy=Sujets
 selected.taxonomy.tree=Taxonomie
+shares.enabled=Groupes
+taxonomy.all=Tous les sujets
+taxonomy.competences=Sujets avec la comp\u00E9tence "Enseigner" ou "G\u00E9rer"
+taxonomy.selectable=Sujets s\u00E9lectionnables
 taxonomyLevel.deleted=Le sujet a \u00E9t\u00E9 effac\u00E9 avec succ\u00E8s.
 taxonomyLevel.notdeleted=Le sujet n'a pas pu \u00EAtre effac\u00E9 avec succ\u00E8s, il est probablement encore utilis\u00E9.
+translation=Traductions
 type.key=ID
 type.translation=Traduction
 type.type=Type
diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/MetaUIFactory.java b/src/main/java/org/olat/modules/qpool/ui/metadata/MetaUIFactory.java
index f9bf1726ed97ca682fc703f3ed4d6030c9e0c582..cff1d26f16ac0f21eb18af9ad8e0418fe19cab58 100644
--- a/src/main/java/org/olat/modules/qpool/ui/metadata/MetaUIFactory.java
+++ b/src/main/java/org/olat/modules/qpool/ui/metadata/MetaUIFactory.java
@@ -78,8 +78,9 @@ public class MetaUIFactory {
 		int count = 0;
 		for(QEducationalContext level:levels) {
 			contextKeys[count] = level.getLevel();
-			String translation = translator.translate("item.level." + level.getLevel().toLowerCase());
-			if(translation.length() > 128) {
+			String i18nKey = "item.level." + level.getLevel().toLowerCase();
+			String translation = translator.translate(i18nKey);
+			if(i18nKey.equals(translation) || translation.length() > 256) {
 				translation = level.getLevel();
 			}
 			contextValues[count++] = translation;
diff --git a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyDAO.java b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyDAO.java
index 8b53c14013cb58ff02fef0bb4208679fe7103b49..52c8e88be75762e6d0a15ecdc5927824e4b0e50e 100644
--- a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyDAO.java
+++ b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyDAO.java
@@ -136,8 +136,7 @@ public class TaxonomyDAO implements InitializingBean{
 		File directory = new File(storage, type);
 		directory.mkdirs();
 		Path relativePath = rootDirectory.toPath().relativize(directory.toPath());
-		String relativePathString = relativePath.toString();
-		return relativePathString;
+		return relativePath.toString();
 	}
 	
 	public VFSContainer getDocumentsLibrary(Taxonomy taxonomy) {
diff --git a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java
index 624cd9be6da723f14294c7e5ccfe9b1d81ba44e1..ec293aed0ac7ffbac2e882dbf374bb6ecbe60ae1 100644
--- a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java
+++ b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java
@@ -21,11 +21,13 @@ package org.olat.modules.taxonomy.manager;
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 
 import org.olat.basesecurity.IdentityRef;
 import org.olat.core.id.Identity;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSItem;
 import org.olat.core.util.vfs.VFSManager;
 import org.olat.modules.taxonomy.Taxonomy;
 import org.olat.modules.taxonomy.TaxonomyCompetence;
@@ -160,12 +162,23 @@ public class TaxonomyServiceImpl implements TaxonomyService {
 			merge(reloadedTaxonomyLevel, reloadedMergeTo);
 		} else {
 			VFSContainer library = taxonomyLevelDao.getDocumentsLibrary(reloadedTaxonomyLevel);
-			Taxonomy taxonomy = reloadedTaxonomyLevel.getTaxonomy();
-			VFSContainer lostAndFound = taxonomyDao.getLostAndFoundDirectoryLibrary(taxonomy);
-			String dir = StringHelper.transformDisplayNameToFileSystemName(reloadedTaxonomyLevel.getIdentifier());
-			dir += "_" + taxonomyLevel.getKey();
-			VFSContainer lastStorage = lostAndFound.createChildContainer(dir);
-			VFSManager.copyContent(library, lastStorage);
+			if(library != null) {
+				Taxonomy taxonomy = reloadedTaxonomyLevel.getTaxonomy();
+				VFSContainer lostAndFound = taxonomyDao.getLostAndFoundDirectoryLibrary(taxonomy);
+				String dir = StringHelper.transformDisplayNameToFileSystemName(reloadedTaxonomyLevel.getIdentifier());
+				dir += "_" + taxonomyLevel.getKey();
+				VFSContainer lastStorage = lostAndFound.createChildContainer(dir);
+				if(lastStorage == null) {
+					VFSItem storageItem = lostAndFound.resolve(dir);
+					if(storageItem instanceof VFSContainer) {
+						lastStorage = (VFSContainer)storageItem;
+					} else {
+						lastStorage = lostAndFound.createChildContainer(UUID.randomUUID().toString());
+					}
+				}
+				
+				VFSManager.copyContent(library, lastStorage);
+			}
 			//delete the competences
 			taxonomyCompetenceDao.deleteCompetences(taxonomyLevel);
 			//questions
diff --git a/src/main/java/org/olat/modules/taxonomy/ui/TaxonomyLevelOverviewController.java b/src/main/java/org/olat/modules/taxonomy/ui/TaxonomyLevelOverviewController.java
index 2abbda811b173d599a3fd9b753c4109427958ebe..65b98b210d8c0abe8ec8555faecd983452887995 100644
--- a/src/main/java/org/olat/modules/taxonomy/ui/TaxonomyLevelOverviewController.java
+++ b/src/main/java/org/olat/modules/taxonomy/ui/TaxonomyLevelOverviewController.java
@@ -213,13 +213,15 @@ public class TaxonomyLevelOverviewController extends BasicController implements
 			showWarning("warning.atleastone.level");
 			return;
 		}
-		
+
+		taxonomyLevel = taxonomyService.getTaxonomyLevel(taxonomyLevel);
 		Taxonomy taxonomy = taxonomyLevel.getTaxonomy();
-		confirmDeleteCtrl = new DeleteTaxonomyLevelController(ureq, getWindowControl(), null, taxonomy);
+		List<TaxonomyLevel> levelToDelete = Collections.singletonList(taxonomyLevel);
+		confirmDeleteCtrl = new DeleteTaxonomyLevelController(ureq, getWindowControl(), levelToDelete, taxonomy);
 		listenTo(confirmDeleteCtrl);
 
 		String title = translate("confirmation.delete.level.title");
-		cmc = new CloseableModalController(getWindowControl(), "close", moveLevelCtrl.getInitialComponent(), true, title);
+		cmc = new CloseableModalController(getWindowControl(), "close", confirmDeleteCtrl.getInitialComponent(), true, title);
 		listenTo(cmc);
 		cmc.activate();
 	}
diff --git a/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_en.properties
index e48fce6efaa5801c924d074d236b3e1317694b27..deb3aa8c70663f382ee6479de397328e59e4dd2d 100644
--- a/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Fri Dec 08 12:28:56 CET 2017
+#Tue Feb 06 08:32:56 CET 2018
 QuestionItemImpl=Question
 actions=Actions
 add.competence.have=Add "$\:have"
@@ -18,12 +18,12 @@ assign.type=Assign
 atleast.one.competence=You must select at least one competence you can edit.
 confirm.delete.level.type.sucessfull=The level type "{0}" was successfully deleted.
 confirm.deleted.level=The level "{0}" was successfully  deleted.
+confirm.merge.level=The level(s) "{0}" was sucessfully merged.
 confirm.removed.competence=The competence(s) was successfully removed.
 confirmation.delete.level=Do you really want to delete the level "{0}"?
 confirmation.delete.level.title=Delete level
 confirmation.delete.type=Do you really want to delete this level type "{0}"?
 confirmation.delete.type.title=Delete level type "{0}"
-confirm.merge.level=The level(s) "{0}" was sucessfully merged.
 confirmation.remove.competence=Do you really want to remove the competence "{0}" for the level {1}?
 confirmation.remove.competence.title=Remove competence
 create.taxonomy=Create new taxonomy
@@ -33,10 +33,10 @@ details.delete=Delete
 edit.competence.title=Edit competence "{1}" of "{0}"
 edit.competences=Edit competences
 edit.level.types=Edit types
-error.delete.num=These taxonomy levels contains the following elements:
-error.delete.num.relations=<strong>{0}</strong> references to learn objects
-error.delete.num.competences=<strong>{0}</strong> competence relations
+error.delete.num=These taxonomy levels contains the following elements\:
 error.delete.num.child.levels=<strong>{0}</strong> children taxonomy levels
+error.delete.num.competences=<strong>{0}</strong> competence relations
+error.delete.num.relations=<strong>{0}</strong> references to learn objects
 error.discontinuous.selection=Discontinous selection of taxonomy levels is not supported.
 error.found.no.allowed.sub.types=No level type was found which is compatible with the selection and the level types configuration.
 error.select.target.level=You must select a taxonomy level.
@@ -101,6 +101,7 @@ table.taxonomy.level.type.empty=There isn't any level type available. If you wan
 target=Target
 target.can.read="$\:target" allowed to read
 taxonomy.admin.enabled=Enable taxonomy
+taxonomy.competence.expiration=Expiration date
 taxonomy.competence.fullName=Name
 taxonomy.competence.type=Competence
 taxonomy.description=Description
diff --git a/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_fr.properties
index 7ff112f86edd9f511a48c72222dbe354ab720917..c6034489631af23770bda176ae84e4adc5d38a75 100644
--- a/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/modules/taxonomy/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Fri Nov 17 12:09:10 CET 2017
+#Fri Feb 02 08:47:45 CET 2018
 QuestionItemImpl=Question
 actions=Actions
 add.competence.have=Ajouter "$\:have"
@@ -14,9 +14,11 @@ admin.configuration.title=Configuration taxonomie
 admin.menu.title=Taxonomie
 admin.menu.title.alt=Taxonomie
 admin.taxonomy.trees=Taxonomie
+assign.type=Attribuer
 atleast.one.competence=Vous devez choisir au moins une comp\u00E9tence que vous pouvez \u00E9diter.
 confirm.delete.level.type.sucessfull=Le type de niveau "{0}" a \u00E9t\u00E9 effac\u00E9.
 confirm.deleted.level=Le niveau "{0}" de la taxonomie a \u00E9t\u00E9 effac\u00E9.
+confirm.merge.level=Les niveaux "{0}" ont \u00E9t\u00E9 fusionn\u00E9s avec succ\u00E8s.
 confirm.removed.competence=La ou les comp\u00E9tences ont \u00E9t\u00E9 effac\u00E9es.
 confirmation.delete.level=Voulez-vous vraiment effacer le niveau "{0}" de la taxonomie?
 confirmation.delete.level.title=Effacer un niveau de la taxonomie
@@ -31,10 +33,20 @@ details.delete=Effacer
 edit.competence.title=Editer la comp\u00E9tence "{1}" de "{0}"
 edit.competences=Editer la comp\u00E9tence
 edit.level.types=Editer le type
+error.delete.num=Les niveaux de la taxonomie contiennent les \u00E9l\u00E9ments suivants\:
+error.delete.num.child.levels=<strong>{0}</strong> sous-niveaux
+error.delete.num.competences=<strong>{0}</strong> relations vers des comp\u00E9tences
+error.delete.num.relations=<strong>{0}</strong> r\u00E9f\u00E9rences \u00E0 des objets didactiques
+error.discontinuous.selection=La s\u00E9lection discontinue de niveaux de la taxonomie n'est pas support\u00E9 pour l'instant.
+error.found.no.allowed.sub.types=Il n'y a aucun type de niveaux dont la configuration est compatible avec la s\u00E9lection.
+error.select.target.level=Vous devez s\u00E9lectionner au moins un niveau de la taxonomie.
 error.sort.order.integer=Num\u00E9ro de tri doit \u00EAtre un chiffre entier.
+error.target.no.parent=Ce niveau de la taxonomie ne peut pas \u00EAtre d\u00E9placer l\u00E0.
+error.target.not.allowed=Ce niveau de la taxonomie ne peut pas \u00EAtre d\u00E9plac\u00E9 l\u00E0 car le type du niveau parent est incompatible avec celui-ci.
 filter.no.level.type=Sans type de niveau
 have=Acquis
 info.copy.level.type.sucessfull=Le type de niveau "{0}" a \u00E9t\u00E9 copi\u00E9.
+info.delete.merge.to=Ces \u00E9l\u00E9ments peuvent \u00EAtre fusionn\u00E9s avec un autre niveau de la taxonomie.
 insert.taxonomy.levels=Ajouter un type de niveau
 level.description=Description
 level.directory.path=Chemin technique
@@ -46,9 +58,14 @@ level.type=Type
 level.type.allowed.sub.types=Sous-types
 level.type.cssClass=Class CSS
 level.type.docs.enabled=Activer le dossier documents
+level.types.to.assign=Types de niveaux
 level.visible=Visible
 manage=G\u00E9rer
+merge.taxonomy.level=Fusionner
+merge.to=Fusionner
 move.taxonomy.level=D\u00E9placer
+move.taxonomy.level.title=D\u00E9placer "{0}"
+move.taxonomy.levels.title=D\u00E9placer
 my.taxonomies=Ma taxonomie
 not.configured=Pas encore configur\u00E9e\! Configurer d'abord une taxonomie dans la partie administration.
 not.implemented=Not implemented
@@ -56,6 +73,7 @@ open.taxonomy=montrer / \u00E9diter
 remove=Enlever
 selected.taxonomy.qpool=Taxonomie pour la banque de questions
 selected.taxonomy.tree=Taxonomie pour la banque de documents
+show.all=Tout montrer
 table.competence.empty=Il n'y a pas encore de comp\u00E9tences attribu\u00E9es pour ce niveau de la taxonomie
 table.header.actions=<i class\='o_icon o_icon_actions o_icon-lg'> </i>
 table.header.competence.achievement=Accomplissement
@@ -72,15 +90,18 @@ table.header.taxonomy.level.displayName=Nom
 table.header.taxonomy.level.externalId=R\u00E9f. ext. niveau
 table.header.taxonomy.level.identifier=Identifiant
 table.header.taxonomy.level.num.children=Nombre
+table.header.taxonomy.level.type=Type de niveau
 table.header.taxonomy.level.type.identifier=Type du niveau
 table.header.type.displayName=Nom
 table.header.type.identifier=Identifiant
 table.relations.empty=Il n'y a pas encore de relations \u00E0 ce niveau de la taxonomie.
 table.taxonomy.empty=Il n'existe pas encore de taxonomie. Pour utiliser la banque de documents, la banque de questions ou les comp\u00E9tences, vous devez d'abord cr\u00E9er une taxonomie.
+table.taxonomy.level.empty=Il n'y a pas de niveau disponible.
 table.taxonomy.level.type.empty=Il n'y pas encore de type de niveaux de la taxonomie. Pour utiliser la banque de documents ou la banque de questions, vous devez d\u00E9finir des types \u00E0 attribuer aux niveaux de la taxonomie.
 target=A atteindre
 target.can.read="$\:target" autoriser en lecture
 taxonomy.admin.enabled=Activer taxonomie
+taxonomy.competence.expiration=Expiration
 taxonomy.competence.fullName=Nom
 taxonomy.competence.type=Comp\u00E9tence
 taxonomy.description=Description
@@ -107,5 +128,8 @@ taxonomy.metadata=M\u00E9tadonn\u00E9es
 taxonomy.types=Types de niveaux
 teach=Enseigner
 tools=$\:table.header.actions
+type.taxonomy.level=Attribuer un type de niveau
+warning.atleastone.level=Vous devez s\u00E9lectionner au moins un niveau que vous pouvez \u00E9diter.
+warning.atleastone.level.competence=Vous devez s\u00E9lectionner au moins un niveau.
 warning.delete.level=Ce niveau de la taxonomie ne peut pas \u00EAtre effac\u00E9 car il est encore utilis\u00E9.
 warning.delete.level.type=Le niveau de la taxonomie n'a pas \u00E9t\u00E9 effac\u00E9 car il est encore utilis\u00E9.
diff --git a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_fr.properties
index 3e5abeb9b306c434a481fbcfaebb3e9555061873..7c740386991942bc2aabaf064fb24fcfcf4f0ebe 100644
--- a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Thu Mar 09 17:09:13 CET 2017
+#Thu Feb 01 18:30:54 CET 2018
 add.track=Ajouter sous-titre
 admin.config.enable=Activ\u00E9 la resource de type vid\u00E9o
 admin.config.hint=Voulez-vous vraiment d\u00E9sactiver le transcodage vid\u00E9o?
@@ -76,9 +76,9 @@ track.table.header.file=Fichier
 track.table.header.language=Langue
 track.table.label=Sous-titres
 track.upload=T\u00E9l\u00E9charger
+track.upload.error.filetype=Pour les sous-titres, seuls les fichiers au format WebVTT avec le suffixe .srt sont support\u00E9s.
 track.upload.error.nofile=Choisissez un fichier s'il vous pla\u00EEt.
 track.upload.error.nolang=Choisissez une langue de la liste
-track.upload.error.filetype=Pour les sous-titres, seuls les fichiers au format WebVTT avec le suffixe .srt sont support\u00E9s.
 transcoding.error=Master endommag\u00E9
 transcoding.inefficient=Qualit\u00E9 m\u00E9diocre
 transcoding.processing=En cours
@@ -121,3 +121,4 @@ video.not.replaced=Le fichier vid\u00E9o n'a pas pu \u00EAtre remplac\u00E9. Cho
 video.replace.desc=Veuillez choisir un fichier vid\u00E9o sur votre ordinateur et cliquer le bouton "Remplacer la vid\u00E9o" pour remplacer l'ancien.
 video.replace.upload=Fichier vid\u00E9o
 video.replaced=Le fichier vid\u00E9o a \u00E9t\u00E9 remplac\u00E9 et il sera transcod\u00E9 pour obtenir les diff\u00E9rentes r\u00E9solutions configur\u00E9es.
+warning.no.poster.proposals=Un aper\u00E7u n'a pas pu \u00EAtre g\u00E9n\u00E9r\u00E9.
diff --git a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
index 378cefc4063b2c12a3d2bd17f14a7fbda7e1dc68..ab014fb1defc4aa9c0ce92cc4e3bddd05014c2c7 100755
--- a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
+++ b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
@@ -175,7 +175,7 @@ public class EPStructureManager {
 	protected List<PortfolioStructure> getStructureElements(int firstResult, int maxResults, ElementType... types){
 		StringBuilder sb = new StringBuilder();
 		sb.append("select stEl from ").append(EPStructureElement.class.getName()).append(" stEl");
-		sb.append(" where stEl.class in (");
+		sb.append(" where type(stEl) in (");
 		boolean first = true;
 		for(ElementType type:types) {
 			if(first) first = false;
@@ -205,7 +205,7 @@ public class EPStructureManager {
 		  .append("    where baseGroup=membership.group and membership.identity.key=:identityKey and membership.role='").append(GroupRoles.owner.name()).append("'")
 		  .append(" )");
 		if(types != null && types.length > 0) {
-			sb.append(" and stEl.class in (");
+			sb.append(" and type(stEl) in (");
 			boolean first = true;
 			for(ElementType type:types) {
 				if(first) first = false;
@@ -336,7 +336,7 @@ public class EPStructureManager {
 			  .append(" )");
 		}
 		if (types != null && types.length > 0) {
-			sb.append(" and stEl.class in (");
+			sb.append(" and type(stEl) in (");
 			boolean first = true;
 			for (final ElementType type : types) {
 				if (first) {
@@ -397,7 +397,7 @@ public class EPStructureManager {
 			  .append(" )");
 		}
 		if(types != null && types.length > 0) {
-			sb.append(" and stEl.class in (");
+			sb.append(" and type(stEl) in (");
 			boolean first = true;
 			for(ElementType type:types) {
 				if(first) first = false;
diff --git a/src/main/java/org/olat/repository/RepositoryMailing.java b/src/main/java/org/olat/repository/RepositoryMailing.java
index 559fca1b8a049004efdb9f8927cada8607017e70..7c73d2bf7216e102b789380fb40b2cc4ee0e7936 100644
--- a/src/main/java/org/olat/repository/RepositoryMailing.java
+++ b/src/main/java/org/olat/repository/RepositoryMailing.java
@@ -74,6 +74,19 @@ public class RepositoryMailing {
 		return createMailTemplate(re, actor, subjectKey, bodyKey);
 	}
 	
+	/**
+	 * The mail template when adding users to a course.
+	 * 
+	 * @param re
+	 * @param actor
+	 * @return the generated MailTemplate
+	 */
+	public static MailTemplate createAddAutoParticipantMailTemplate(RepositoryEntry re, Identity actor) {
+		String subjectKey = "notification.mail.added.auto.subject";
+		String bodyKey = "notification.mail.added.auto.body";
+		return createMailTemplate(re, actor, subjectKey, bodyKey);
+	}
+	
 	/**
 	 * The mail template when adding tutors to a course.
 	 * 
@@ -119,6 +132,8 @@ public class RepositoryMailing {
 		switch(type) {
 			case addParticipant:
 				return createAddParticipantMailTemplate(re, ureqIdentity);
+			case addParticipantItself:
+				return createAddAutoParticipantMailTemplate(re, ureqIdentity);
 			case addTutor:
 				return createAddTutorMailTemplate(re, ureqIdentity);
 			case addOwner:
@@ -131,7 +146,7 @@ public class RepositoryMailing {
 		return null;
 	}
 
-	protected static void sendEmail(Identity ureqIdentity, Identity identity, RepositoryEntry re,
+	public static void sendEmail(Identity ureqIdentity, Identity identity, RepositoryEntry re,
 			Type type, MailPackage mailing) {
 		
 		if(mailing != null && !mailing.isSendEmail()) {
@@ -181,7 +196,8 @@ public class RepositoryMailing {
 		addTutor,
 		removeTutor,
 		addOwner,
-		removeOwner
+		removeOwner,
+		addParticipantItself
 	}
 	
 	private static MailTemplate createMailTemplate(RepositoryEntry re, Identity actor, String subjectKey, String bodyKey) {
diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
index f25e518daa8cd227e249de38041cdbf777c21266..b1a602c46540480aa1acedf7d791c599d88b4598 100644
--- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
@@ -384,6 +384,8 @@ no.lifecycle=Keine Einschr\u00E4nkung
 no.catalog.entries=Diese Resource wurde noch nicht im Katalog registriert. \r\n\r\n Verwenden Sie den "In Katalog einf\u00FCgen" Button in der Toolbar, um die Resource auf einer bestimmten Katalog-Ebenen hinzuzuf\u00FCgen. Der Katalog erlaubt es dem Benutzer je nach Zugriffskonfiguration nach bestimmten Eintr\u00E4gen zu suchen. Sie k\u00F6nnen die Resource auf mehreren Katalog-Ebenen hinzuf\u00FCgen.
 info.catalog.entries=Verwenden Sie den "In Katalog einf\u00FCgen" Button in der Toolbar, um die Resource auf einer bestimmten Katalog-Ebenen hinzuzuf\u00FCgen. Der Katalog erlaubt es dem Benutzer je nach Zugriffskonfiguration nach bestimmten Eintr\u00E4gen zu suchen. Sie k\u00F6nnen die Resource auf mehreren Katalog-Ebenen hinzuf\u00FCgen.
 nomembers=XXX No members
+notification.mail.added.auto.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie haben sich f\u00FCr den folgenden Kurs angemeldet\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\nZugang\: $courseurl
+notification.mail.added.auto.subject=$\:notification.mail.added.subject
 notification.mail.added.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie wurden von {0} {1} ({2}) in einen Kurs eingeladen\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\nZugang\: $courseurl\n\nBei Fragen kontaktieren Sie bitte {0} {1} ({2}).
 notification.mail.added.subject=Kurs $coursename 
 notification.mail.removed.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie wurden von {0} {1} ({2}) aus dem Kurs ausgetragen\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\n\nBei Fragen kontaktieren Sie bitte {0} {1} ({2}).
diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
index c2a87e54010a7bd99e288dc35f80d5ca08abefa4..19026de10963c68967c64893efb76b1de13bc14a 100644
--- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
@@ -381,6 +381,8 @@ no.lifecycle=No limitation
 no.catalog.entries=This resource has not been added to the catalog yet. \r\n\r\n Use the "Add to catalog" button in the toolbar above to add the resource to a specific level in the catalog. The catalog allows users to browse for available resources depending on th resource access configuration. You can add the resource to multiple catalog levels.
 info.catalog.entries=Use the "Add to catalog" button in the toolbar above to add the resource to a specific level in the catalog. The catalog allows users to browse for available resources depending on th resource access configuration. You can add the resource to multiple catalog levels. 
 nomembers=XXX No members
+notification.mail.added.auto.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou registered you to the following course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\nLink\: $courseurl
+notification.mail.added.auto.subject=$\:notification.mail.added.subject
 notification.mail.added.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou have been added by {0} {1} ({2}) to a course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\nLink\: $courseurl\n\nIf you have questions regarding this action, please contact {0} {1} ({2}).
 notification.mail.added.subject=Course $coursename
 notification.mail.removed.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou have been removed by {0} {1} ({2}) from a course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\r\n\r\nIf you have questions regarding this action, please contact {0} {1} ({2}).
diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_fr.properties
index 1d9de9f97f10c51cc6c1539ff5eaccf9c6ec10f2..087cc752e309f62400c50a4c1dfc7b2db7da1254 100644
--- a/src/main/java/org/olat/repository/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Tue Aug 15 17:30:54 CEST 2017
+#Thu Feb 01 18:37:37 CET 2018
 BinderTemplate=Mod\u00E8le de portfolio 2.0
 CourseModule=Cours
 EPStructuredMapTemplate=Mod\u00E8le de portfolio
@@ -140,6 +140,10 @@ cif.private.dates=Date
 cif.public.dates=Semestre
 cif.requirements=Exigences
 cif.resourcename=Nom de fichier
+cif.resources.status=Cours
+cif.resources.status.active=Actif
+cif.resources.status.all=Tous
+cif.resources.status.closed=Termin\u00E9
 cif.softkey=OpenOLAT-Soft-ID
 cif.type=Type
 cif.type.na=pas d'indication
diff --git a/src/main/java/org/olat/resource/accesscontrol/Offer.java b/src/main/java/org/olat/resource/accesscontrol/Offer.java
index 8c59b0b518b1ea78a3d40915764830ed9e54d53b..368f67cc4cdb6113ed033a424a9293dd16772682 100644
--- a/src/main/java/org/olat/resource/accesscontrol/Offer.java
+++ b/src/main/java/org/olat/resource/accesscontrol/Offer.java
@@ -68,5 +68,9 @@ public interface Offer extends Persistable {
 	public boolean isAutoBooking();
 	
 	public void setAutoBooking(boolean autoBooking);
+	
+	public boolean isConfirmationEmail();
+
+	public void setConfirmationEmail(boolean confirmationEmail);
 
 }
diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java
index a517ed0173b7f314ef63370b40f63b68eefa950e..d9a3a9e2393b3cc616ac99c95bdf40e84cdaa7d1 100644
--- a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java
+++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java
@@ -41,6 +41,7 @@ import org.olat.core.id.Roles;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.mail.MailPackage;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.manager.BusinessGroupDAO;
@@ -49,6 +50,7 @@ import org.olat.group.model.EnrollState;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryRef;
 import org.olat.repository.RepositoryEntryShort;
+import org.olat.repository.RepositoryMailing;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.RepositoryService;
 import org.olat.repository.manager.RepositoryEntryRelationDAO;
@@ -113,11 +115,11 @@ public class ACFrontendManager implements ACService {
 	@Autowired
 	private BusinessGroupDAO businessGroupDao;
 	@Autowired
+	private BusinessGroupService businessGroupService;
+	@Autowired
 	private BusinessGroupRelationDAO businessGroupRelationDao;
 	@Autowired
 	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
-	@Autowired
-	private BusinessGroupService businessGroupService;
 
 	/**
 	 * The rule to access the repository entry:<br/>
@@ -479,14 +481,19 @@ public class ACFrontendManager implements ACService {
 		if("BusinessGroup".equals(resourceType)) {
 			BusinessGroup group = businessGroupService.loadBusinessGroup(resource);
 			if(group != null) {
-				EnrollState result = businessGroupService.enroll(identity, null, identity, group, null);
-				return result.isFailed() ? Boolean.FALSE : Boolean.TRUE;
+				MailPackage mailing = new MailPackage(offer.isConfirmationEmail());
+				EnrollState result = businessGroupService.enroll(identity, null, identity, group, mailing);
+				return !result.isFailed();
 			}
 		} else {
-			RepositoryEntryRef entry = repositoryManager.lookupRepositoryEntry(resource, false);
+			RepositoryEntry entry = repositoryManager.lookupRepositoryEntry(resource, false);
 			if(entry != null) {
 				if(!repositoryEntryRelationDao.hasRole(identity, entry, GroupRoles.participant.name())) {
 					repositoryEntryRelationDao.addRole(identity, entry, GroupRoles.participant.name());
+					if(offer.isConfirmationEmail()) {
+						MailPackage mailing = new MailPackage(offer.isConfirmationEmail());
+						RepositoryMailing.sendEmail(identity, identity, entry, RepositoryMailing.Type.addParticipantItself, mailing);
+					}
 				}
 				return true;
 			}
diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACMethodDAO.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACMethodDAO.java
index 65e609bf5e9242da0a34d1584a2d3c631c531a05..dede289ce9f44f0128cbf5af9d5a853b85339a3b 100644
--- a/src/main/java/org/olat/resource/accesscontrol/manager/ACMethodDAO.java
+++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACMethodDAO.java
@@ -188,7 +188,7 @@ public class ACMethodDAO implements InitializingBean {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select method from ").append(AbstractAccessMethod.class.getName()).append(" method")
 			.append(" where method.valid=true")
-			.append(" and method.class=").append(type.getName());
+			.append(" and type(method) =").append(type.getName());
 
 		TypedQuery<AccessMethod> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), AccessMethod.class);
 		List<AccessMethod> methods = query.getResultList();
@@ -378,7 +378,7 @@ public class ACMethodDAO implements InitializingBean {
 	protected void activateFreeMethod(boolean enable) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select method from ").append(AbstractAccessMethod.class.getName())
-			.append(" method where method.class=").append(FreeAccessMethod.class.getName());
+			.append(" method where type(method) =").append(FreeAccessMethod.class.getName());
 
 		TypedQuery<AccessMethod> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), AccessMethod.class);
 		List<AccessMethod> methods = query.getResultList();
diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java
index 398013d122564e92ec00f6a1b2f11fe7ac74c60e..53442c6b3cb050b7523ad78f6833ecc86a3bc73c 100644
--- a/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java
+++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java
@@ -135,6 +135,7 @@ public class ACOfferDAO {
 		offer.setLastModified(now);
 		offer.setResource(resource);
 		offer.setValid(true);
+		offer.setConfirmationEmail(false);
 		if(resourceName != null && resourceName.length() > 255) {
 			resourceName = resourceName.substring(0, 250);
 		}
diff --git a/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java b/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java
index 5c4f6cb4223d33c17b82bd88aa7e2caad5be54d0..3aa9c4f7183d52ecea65b13f35409c82b14f0bbd 100644
--- a/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java
+++ b/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java
@@ -98,6 +98,8 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 	private String token;
 	@Column(name="autobooking", nullable=true, insertable=true, updatable=true)
 	private boolean autoBooking;
+	@Column(name="confirmation_email", nullable=true, insertable=true, updatable=true)
+	private boolean confirmationEmail;
 
 	@Column(name="resourceid", nullable=true, insertable=true, updatable=true)
 	private Long resourceId;
@@ -182,6 +184,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 		this.validTo = validTo;
 	}
 
+	@Override
 	public Long getResourceId() {
 		return resourceId;
 	}
@@ -190,6 +193,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 		this.resourceId = resourceId;
 	}
 
+	@Override
 	public String getResourceTypeName() {
 		return resourceTypeName;
 	}
@@ -198,6 +202,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 		this.resourceTypeName = resourceTypeName;
 	}
 
+	@Override
 	public String getResourceDisplayName() {
 		return resourceDisplayName;
 	}
@@ -215,15 +220,25 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 	public void setDescription(String description) {
 		this.description = description;
 	}
-	
+
+	@Override
 	public boolean isAutoBooking() {
 		return autoBooking;
 	}
-	
+
+	@Override
 	public void setAutoBooking(boolean autoBooking) {
 		this.autoBooking = autoBooking;
 	}
 
+	public boolean isConfirmationEmail() {
+		return confirmationEmail;
+	}
+
+	public void setConfirmationEmail(boolean confirmationEmail) {
+		this.confirmationEmail = confirmationEmail;
+	}
+
 	public String getToken() {
 		return token;
 	}
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java b/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java
index 67cc9d65aac158c16646d195abd6c884b152feea..3b9462286db794b5837cb2642eb5335cf8592760 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java
@@ -33,10 +33,6 @@ import org.olat.resource.accesscontrol.model.AccessMethod;
 
 /**
  * 
- * Description:<br>
- * TODO: srosse Class Description for AbstractConfigurationMethodController
- * 
- * <P>
  * Initial Date:  18 avr. 2011 <br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
@@ -73,6 +69,7 @@ public abstract class AbstractConfigurationMethodController extends FormBasicCon
 	
 	public abstract AccessMethod getMethod();
 
+	@Override
 	public FormItem getInitialFormItem() {
 		return flc;
 	}
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java
index 5f30e7fa5e75db21fa9bfb89c99f6bbee46b72dc..e95c3beeb16b3574b7af0c9bd30a7d729c909563 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java
@@ -24,14 +24,13 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
 
+import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
-import org.olat.core.gui.components.form.flexible.elements.DateChooser;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.impl.Form;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
@@ -64,8 +63,12 @@ import org.springframework.beans.factory.annotation.Autowired;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
 public class AccessConfigurationController extends FormBasicController {
+	
+	private static final String[] onKeys = new String[] { "on" };
 
-	private List<FormLink> addMethods = new ArrayList<FormLink>();
+	private MultipleSelectionElement confirmationEmailEl;
+	private final List<FormLink> addMethods = new ArrayList<>();
+	
 	private final String displayName;
 	private final OLATResource resource;
 
@@ -73,7 +76,7 @@ public class AccessConfigurationController extends FormBasicController {
 	private FormLayoutContainer confControllerContainer;
 	private AbstractConfigurationMethodController newMethodCtrl, editMethodCtrl;
 
-	private final List<AccessInfo> confControllers = new ArrayList<AccessInfo>();
+	private final List<AccessInfo> confControllers = new ArrayList<>();
 
 	private final boolean embbed;
 	private final boolean emptyConfigGrantsFullAccess;
@@ -82,6 +85,8 @@ public class AccessConfigurationController extends FormBasicController {
 
 	private final Formatter formatter;
 
+	@Autowired
+	private DB dbInstance;
 	@Autowired
 	private ACService acService;
 	@Autowired
@@ -144,6 +149,11 @@ public class AccessConfigurationController extends FormBasicController {
 			}
 			((FormLayoutContainer)formLayout).contextPut("methods", addMethods);
 		}
+		
+		String[] onValues = new String[] { "" };
+		confirmationEmailEl = uifactory.addCheckboxesHorizontal("confirmation.email", formLayout, onKeys, onValues);
+		confirmationEmailEl.addActionListener(FormEvent.ONCHANGE);
+		confirmationEmailEl.setVisible(false);
 
 		String confPage = velocity_root + "/configuration_list.html";
 		confControllerContainer = FormLayoutContainer.createCustomFormLayout("conf-controllers", getTranslator(), confPage);
@@ -154,6 +164,15 @@ public class AccessConfigurationController extends FormBasicController {
 
 		confControllerContainer.contextPut("confControllers", confControllers);
 
+		boolean confirmationEmail = false;
+		for(AccessInfo info:confControllers) {
+			Offer offer = info.getLink().getOffer();
+			confirmationEmail |= offer.isConfirmationEmail();
+		}
+		if(confirmationEmail) {
+			confirmationEmailEl.select(onKeys[0], true);
+		}
+
 		if(!embbed) {
 			setFormTitle("accesscontrol.title");
 
@@ -187,16 +206,6 @@ public class AccessConfigurationController extends FormBasicController {
 		//
 	}
 
-	@Override
-	public void event(UserRequest ureq, Component source, Event event) {
-		if(addMethods.contains(source)) {
-			AccessMethod method = (AccessMethod)((Link)source).getUserObject();
-			addMethod(ureq, method);
-		} else {
-			super.event(ureq, source, event);
-		}
-	}
-
 	@Override
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if(newMethodCtrl == source) {
@@ -243,39 +252,21 @@ public class AccessConfigurationController extends FormBasicController {
 			String cmd = button.getCmd();
 			if("delete".equals(cmd)) {
 				AccessInfo infos = (AccessInfo)source.getUserObject();
-				acService.deleteOffer(infos.getLink().getOffer());
-				confControllers.remove(infos);
+				removeMethod(infos);
 				fireEvent(ureq, Event.CHANGED_EVENT);
 			} else if("edit".equals(cmd)) {
 				AccessInfo infos = (AccessInfo)source.getUserObject();
 				editMethod(ureq, infos);
 			}
+		} else if(confirmationEmailEl == source) {
+			setConfirmationEmail(confirmationEmailEl.isAtLeastSelected(1));
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
 
 	@Override
 	public void formOK(UserRequest ureq) {
-		Map<String,FormItem> formItemMap = confControllerContainer.getFormComponents();
-
-		List<OfferAccess> links = new ArrayList<OfferAccess>();
-		for(AccessInfo info:confControllers) {
-			FormItem dateFrom = formItemMap.get("from_" + info.getLink().getKey());
-			if(dateFrom instanceof DateChooser) {
-				Date from = ((DateChooser)dateFrom).getDate();
-				info.getLink().setValidFrom(from);
-				info.getLink().getOffer().setValidFrom(from);
-			}
-
-			FormItem dateTo = formItemMap.get("to_" + info.getLink().getKey());
-			if(dateTo instanceof DateChooser) {
-				Date to = ((DateChooser)dateTo).getDate();
-				info.getLink().setValidTo(to);
-				info.getLink().getOffer().setValidTo(to);
-			}
-
-			links.add(info.getLink());
-		}
+		//
 	}
 
 	protected void loadConfigurations() {
@@ -320,6 +311,15 @@ public class AccessConfigurationController extends FormBasicController {
 			delLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item");
 			confControllerContainer.add(delLink.getName(), delLink);
 		}
+		
+		updateConfirmationEmail();
+	}
+	
+	private void updateConfirmationEmail() {
+		if(confirmationEmailEl.isVisible() != !confControllers.isEmpty()) {
+			confirmationEmailEl.setVisible(!confControllers.isEmpty());
+			flc.setDirty(true);
+		}
 	}
 
 	private void editMethod(UserRequest ureq, AccessInfo infos) {
@@ -342,7 +342,9 @@ public class AccessConfigurationController extends FormBasicController {
 	}
 
 	protected void addMethod(UserRequest ureq, AccessMethod method) {
+		boolean confirmationEmail = confirmationEmailEl.isVisible() && confirmationEmailEl.isAtLeastSelected(1);
 		Offer offer = acService.createOffer(resource, displayName);
+		offer.setConfirmationEmail(confirmationEmail);
 		OfferAccess link = acService.createOfferAccess(offer, method);
 
 		removeAsListenerAndDispose(newMethodCtrl);
@@ -362,6 +364,23 @@ public class AccessConfigurationController extends FormBasicController {
 			addConfiguration(newLink);
 		}
 	}
+	
+	private void removeMethod(AccessInfo infos) {
+		acService.deleteOffer(infos.getLink().getOffer());
+		confControllers.remove(infos);
+		updateConfirmationEmail();
+	}
+	
+	private void setConfirmationEmail(boolean confirmationEmail) {
+		for(AccessInfo info:confControllers) {
+			Offer offer = info.getLink().getOffer();
+			offer.setConfirmationEmail(confirmationEmail);
+			offer = acService.save(offer);
+		}
+		dbInstance.commit();//make sure all is on the dabatase
+		confControllers.clear();
+		loadConfigurations();
+	}
 
 	public class AccessInfo {
 		private String name;
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html b/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html
index 0047566062bd6fad59505d6ed0513823ae76a52a..e530afecc3a5027d9e48c322bb1a87186aaa6bae 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html
@@ -12,6 +12,12 @@
 		#if ($off_info) <div class="o_info">$off_info</div> #end
 	</div></div>
 #end
+	#if($r.visible("confirmation.email"))
+	<div class="form-group">
+		<label class="control-label col-sm-3">$r.translate("confirmation.email")</label>
+		<div class="col-sm-9">$r.render("confirmation.email")</div>
+	</div>
+	#end
 	<div class="form-group">
 		<label class="control-label col-sm-3">$r.translate("ac.methods.label") $r.render("acMethodsLabelHelp")</label>
 		<div class="col-sm-9">$r.render("conf-controllers")</div>
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties
index be5ad639800744c5ea0412081a581203497cc5c0..c7a441396c7f8356b0f6c62b076a9f2f370749fd 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties
@@ -38,6 +38,7 @@ admin.menu.title.alt=$\:admin.title
 admin.title=Verwaltung der Zugangskontrolle und Buchungsmethoden
 cmd.close=Schliessen
 cmd.title=Zugangskontrolle
+confirmation.email=Best\u00E4tigungsemail f\u00FCr selbst eingetragene Benutzer
 course.closed=$org.olat.course.run\:course.closed
 create=Erstellen
 from=Von\:
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties
index 701fa5425c9c805a9a16402e168a5b166581a2c7..a47f66b45d118e7e662482cd069e723c093b40f8 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties
@@ -61,6 +61,7 @@ admin.title=Access control and booking methods administration
 
 cmd.close=Close
 cmd.title=Access control
+confirmation.email=Confirmation email for self-registered users
 course.closed=$org.olat.course.run\:course.closed
 create=Create
 from=From\:
diff --git a/src/main/java/org/olat/search/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/search/ui/_i18n/LocalStrings_fr.properties
index 03386d72b123d275ba2d32268313469298f2d562..c288b25c7e2b728d4b892ded17015e7b7cf45450 100644
--- a/src/main/java/org/olat/search/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/search/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Fri Nov 17 12:07:55 CET 2017
+#Thu Feb 01 18:38:42 CET 2018
 DocumentPool=Banque de documents
 EPSite=Portfolio
 HomeSite=Home
@@ -6,6 +6,7 @@ LibrarySite=Biblioth\u00E8que
 Portfolio=Portfolio
 Taxonomy=Taxonomie
 TaxonomyLevel=Niveau de la taxonomie
+Templates=Mod\u00E8le
 all.search.result.title=tous les {0} r\u00E9sultats 
 area.blogs=Blogue/podcast
 area.courses=Cours
diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_12_3_0.java b/src/main/java/org/olat/upgrade/OLATUpgrade_12_3_0.java
index 2db559824a3fbf7df0ccb61a7e9eeaa0a2582170..a7ba6d015cd10d02c89ddecbe3d217d2866fb424 100644
--- a/src/main/java/org/olat/upgrade/OLATUpgrade_12_3_0.java
+++ b/src/main/java/org/olat/upgrade/OLATUpgrade_12_3_0.java
@@ -176,9 +176,9 @@ public class OLATUpgrade_12_3_0 extends OLATUpgrade {
 					log.error("Not able to migrate question title: " + item, e);
 				}
 			}
-			log.info(counter + " QPool items processed.");
 			counter += items.size();
 			dbInstance.commitAndCloseSession();
+			log.info(counter + " QPool items processed.");
 		} while(items.size() == BATCH_SIZE);
 	}
 
@@ -197,7 +197,7 @@ public class OLATUpgrade_12_3_0 extends OLATUpgrade {
 			item.setTitle(title);
 			dbInstance.getCurrentEntityManager().merge(item);
 		} else {
-			throw new RuntimeException("No title found for QPool item");
+			log.warn("Not able to migrate question title of QPool item (no title found). dir: " + item.getDirectory() + ", " + item);
 		}
 	}
 
@@ -211,26 +211,36 @@ public class OLATUpgrade_12_3_0 extends OLATUpgrade {
 				title = getTitleQTI12(item);
 				break;
 			default:
-				log.error("Not able to migrate question title. QPool item has no valid format: " + item);
+				log.warn("QPool item has no valid format for title migration: " + item.getFormat() + ", " + item);
 		}
 		return title;
 	}
 
 	private String getTitleQTI21(QuestionItemImpl item) {
-		File resourceDirectory = qpoolService.getRootDirectory(item);
-		File resourceFile = qpoolService.getRootFile(item);
-		URI assessmentItemUri = resourceFile.toURI();
-		
-		ResolvedAssessmentItem resolvedAssessmentItem = qtiService
-				.loadAndResolveAssessmentItem(assessmentItemUri, resourceDirectory);
-		
-		return resolvedAssessmentItem.getRootNodeLookup().getRootNodeHolder().getRootNode().getTitle();
+		try {
+			File resourceDirectory = qpoolService.getRootDirectory(item);
+			File resourceFile = qpoolService.getRootFile(item);
+			URI assessmentItemUri = resourceFile.toURI();
+			
+			ResolvedAssessmentItem resolvedAssessmentItem = qtiService
+					.loadAndResolveAssessmentItem(assessmentItemUri, resourceDirectory);
+			
+			return resolvedAssessmentItem.getRootNodeLookup().getRootNodeHolder().getRootNode().getTitle();
+		} catch (NullPointerException e) {
+			log.warn("Cannot read files from dir: " + item.getDirectory());
+		}
+		return null;
 	}
 
 	private String getTitleQTI12(QuestionItemImpl item) {
-		VFSLeaf leaf = qpoolService.getRootLeaf(item);
-		Item xmlItem = QTIEditHelper.readItemXml(leaf);
-		return xmlItem.getTitle();
+		try {
+			VFSLeaf leaf = qpoolService.getRootLeaf(item);
+			Item xmlItem = QTIEditHelper.readItemXml(leaf);
+			return xmlItem.getTitle();
+		} catch (NullPointerException e) {
+			log.warn("Cannot read files from dir: " + item.getDirectory());
+		}
+		return null;
 	}
 	
 	private boolean migrateDialogElements(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
diff --git a/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql
index 05bd7c7c22ed2c2201f62ee5e95fdc33d13e3f90..e9681a365487751c8371f7cfbae56a4b24490699 100644
--- a/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql
+++ b/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql
@@ -1,4 +1,7 @@
 
 -- Evaluation forms
 alter table o_eva_form_response drop column e_responsedatatype;
-alter table o_eva_form_response add column e_file_response_path varchar(4000);
\ No newline at end of file
+alter table o_eva_form_response add column e_file_response_path varchar(4000);
+
+-- access control
+alter table o_ac_offer add column confirmation_email bit default 0;
\ No newline at end of file
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index e0410fd1e005bd6804bcaa23f2d7a3cb3e0c6e15..90f5fcc7c152574f8d626a15413fed0ae2ea0bba 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -973,6 +973,7 @@ create table  if not exists o_ac_offer (
   resourcetypename varchar(255),
   resourcedisplayname varchar(255),
   autobooking boolean default 0,
+  confirmation_email bit default 0,
   token varchar(255),
   price_amount DECIMAL(12,4),
   price_currency_code VARCHAR(3),
diff --git a/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql
index 05bd7c7c22ed2c2201f62ee5e95fdc33d13e3f90..7a9d6391a40d6e8484f53f56b19a6872985ea6e6 100644
--- a/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql
+++ b/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql
@@ -1,4 +1,7 @@
 
 -- Evaluation forms
 alter table o_eva_form_response drop column e_responsedatatype;
-alter table o_eva_form_response add column e_file_response_path varchar(4000);
\ No newline at end of file
+alter table o_eva_form_response add column e_file_response_path varchar(4000);
+
+-- access control
+alter table o_ac_offer add confirmation_email number default 0;
\ No newline at end of file
diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql
index e277aed0d3ddbc0704e04d338a58ee7e304bb2a9..9835c84a5b3bdf81ba2e6ad09534709d6ede0575 100644
--- a/src/main/resources/database/oracle/setupDatabase.sql
+++ b/src/main/resources/database/oracle/setupDatabase.sql
@@ -889,6 +889,7 @@ create table o_ac_offer (
   resourcedisplayname varchar(255 char),
   token varchar(255 char),
   autobooking number default 0 not null,
+  confirmation_email number default 0,
   price_amount number(20,2),
   price_currency_code VARCHAR(3 char),
   offer_desc VARCHAR(2000 char),
diff --git a/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql
index 05bd7c7c22ed2c2201f62ee5e95fdc33d13e3f90..91679515c5d411fb52ab1a5032773215fb65f75e 100644
--- a/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql
+++ b/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql
@@ -1,4 +1,7 @@
 
 -- Evaluation forms
 alter table o_eva_form_response drop column e_responsedatatype;
-alter table o_eva_form_response add column e_file_response_path varchar(4000);
\ No newline at end of file
+alter table o_eva_form_response add column e_file_response_path varchar(4000);
+
+-- access control
+alter table o_ac_offer add column confirmation_email bool default false;
\ No newline at end of file
diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql
index 4012d0db76b43a7b4de0e5d435444ab5d67df453..45b02621327f35b47c3efbbfce4c6b72e7abe580 100644
--- a/src/main/resources/database/postgresql/setupDatabase.sql
+++ b/src/main/resources/database/postgresql/setupDatabase.sql
@@ -837,6 +837,7 @@ create table o_ac_offer (
   resourcetypename varchar(255),
   resourcedisplayname varchar(255),
   autobooking bool not null default false,
+  confirmation_email bool default false,
   token varchar(255),
   price_amount DECIMAL,
   price_currency_code VARCHAR(3),
diff --git a/src/main/resources/org/olat/ims/qti21/questionimport/qti-import-metadata.xlsx b/src/main/resources/org/olat/ims/qti21/questionimport/qti-import-metadata.xlsx
index f736582664caef023283487991abf40083432f63..337788a2369fb178b73ae6c206045fc0536fe2a8 100644
Binary files a/src/main/resources/org/olat/ims/qti21/questionimport/qti-import-metadata.xlsx and b/src/main/resources/org/olat/ims/qti21/questionimport/qti-import-metadata.xlsx differ
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index fbd8788bc5f57485015847966d3f5063afdbe2c5..3348f67dd672ce10b3df510633824703d01e3430 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -1156,8 +1156,8 @@ ldap.learningResourceManagerRoleValue=
 # Build properties
 #####
 application.name=OpenOLAT
-build.version=12.3a
-build.identifier=openolat123a-dev
+build.version=12.4a
+build.identifier=openolat124a-dev
 build.repo.revision=local-devel
 
 #####
diff --git a/src/main/webapp/static/js/jquery/qti/jquery.match.js b/src/main/webapp/static/js/jquery/qti/jquery.match.js
index 4f46a3789ad8cd067def4e582d0beb3dcea78244..0ebe74c7eeacf09c40394e7e0a23499562301561 100644
--- a/src/main/webapp/static/js/jquery/qti/jquery.match.js
+++ b/src/main/webapp/static/js/jquery/qti/jquery.match.js
@@ -1,36 +1,36 @@
 (function ($) {
-    $.fn.matchInteraction = function(options) {
-    	var settings = $.extend({
-    		responseIdentifier: null,
-    		formDispatchFieldId: null,
-    		maxAssociations: 1,
-    		leftData: {},
-    		rightData: {},
-    		leftMap: {},
-    		rightMap: {},
-    		matched: []
+	$.fn.matchInteraction = function(options) {
+		var settings = $.extend({
+			responseIdentifier: null,
+			formDispatchFieldId: null,
+			maxAssociations: 1,
+			leftData: {},
+			rightData: {},
+			leftMap: {},
+			rightMap: {},
+			matched: []
         }, options );
-    	
-        for(var key in settings.leftData){
-        	settings.leftMap[key] = {
-                matchMax: settings.leftData[key],
-                matchCount: 0
-            };
-        }
-        for(var key in settings.rightData){
-        	settings.rightMap[key] = {
-                matchMax: settings.rightData[key],
-                matchCount: 0
-            };
-        }
-    	
-    	try {
-    		match(this, settings);
-    	} catch(e) {
-    		if(window.console) console.log(e);
-    	}
-        return this;
-    };
+
+		for(var key in settings.leftData){
+			settings.leftMap[key] = {
+				matchMax: settings.leftData[key],
+				matchCount: 0
+			};
+		}
+		for(var key in settings.rightData){
+			settings.rightMap[key] = {
+				matchMax: settings.rightData[key],
+				matchCount: 0
+			};
+		}
+
+		try {
+			match(this, settings);
+		} catch(e) {
+			if(window.console) console.log(e);
+		}
+		return this;
+	};
     
     function match($obj, settings) {
         queryInputElements(settings.responseIdentifier).on('click', function() {
@@ -44,22 +44,26 @@
         return jQuery('input[name=qtiworks_response_' + responseIdentifier + ']');
     };
 
-    function withCheckbox(settings, inputElement, callback) {
-        var directedPair = inputElement.value;
-        var splitPair = directedPair.split(" ");
-        var left = settings.leftMap[splitPair[0]];
-        var right = settings.rightMap[splitPair[1]];
+	function withCheckbox(settings, inputElement, callback) {
+		var directedPair = inputElement.value;
+		var splitPair = directedPair.split(" ");
+		var left = settings.leftMap[splitPair[0]];
+		var right = settings.rightMap[splitPair[1]];
         callback(inputElement, directedPair, left, right);
     };
 
-    function recalculate(settings) {
-    	settings.matchCount = 0;
-        settings.matched = {};
-        for(var key in settings.leftMap) {
-        	settings.leftMap[key].matchCount = 0;
-        }
-        for(var key in settings.rightMap) {
-        	settings.rightMap[key].matchCount = 0;
+    /**
+     * Left -> source (set 0)
+     * Right -> target (set 1)
+     */
+	function recalculate(settings) {
+		settings.matchCount = 0;
+		settings.matched = {};
+		for(var key in settings.leftMap) {
+			settings.leftMap[key].matchCount = 0;
+		}
+		for(var key in settings.rightMap) {
+			settings.rightMap[key].matchCount = 0;
         }
 
         queryInputElements(settings.responseIdentifier).each(function() {
@@ -74,48 +78,76 @@
         });
     };
 
-    function updateDisabledStates(settings) {
-        queryInputElements(settings.responseIdentifier).each(function() {
-            withCheckbox(settings, this, function(inputElement, directedPair, left, right) {
-                if (inputElement.checked) {
-                    inputElement.disabled = false;
-                }
-                else if ((settings.maxAssociations!=0 && settings.matchCount >= settings.maxAssociations)
-                        || (left.matchMax!=0 && left.matchCount >= left.matchMax)
-                        || (right.matchMax!=0 && right.matchCount >= right.matchMax)) {
+    /**
+     * Left -> source (set 0)
+     * Right -> target (set 1)
+     */
+	function updateDisabledStates(settings) {
+		queryInputElements(settings.responseIdentifier).each(function() {
+			withCheckbox(settings, this, function(inputElement, directedPair, left, right) {
+				if (inputElement.checked) {
+					inputElement.disabled = false;
+				} else if (settings.maxAssociations != 0 && settings.matchCount >= settings.maxAssociations) {
                     inputElement.disabled = true;
-                }
-                else {
+				} else if (left.matchMax != 0 && left.matchCount >= left.matchMax) {
+                    if(left.matchMax != 1 && left.matchCount != 1) {
+                    		inputElement.disabled = true;
+                    } else {
+                        inputElement.disabled = false;
+                    }
+				} else if (right.matchMax != 0 && right.matchCount >= right.matchMax) {
+                    inputElement.disabled = true;
+				} else {
                     inputElement.disabled = false;
                 }
             });
         });
     };
 
-    function checkMatch(settings, inputElement) {
-        withCheckbox(settings, inputElement, function(inputElement, directedPair, left, right) {
-            if (inputElement.checked){
-                var incremented = false;
-                if (left.matchMax != 0 && left.matchMax <= left.matchCount) {
+	function checkMatch(settings, inputElement) {
+		withCheckbox(settings, inputElement, function(inputElement, directedPair, left, right) {
+			if(inputElement.checked){
+				var incremented = false;
+				// left -> target
+				if(left.matchMax == 1) {
+					// deselect the other check
+					var jInputElement = jQuery(inputElement);
+					var inputId = jInputElement.attr('id');
+					var inputRightId = jInputElement.attr('value').split(" ")[0];
+					queryInputElements(settings.responseIdentifier).each(function() {
+						withCheckbox(settings, this, function(element, directedPair, left, right) {
+							var jElement = jQuery(element);
+							if(inputId !== jElement.attr('id') && element.checked) {
+								var elementRightId = jElement.attr('value').split(" ")[0];
+								if(inputRightId === elementRightId) {
+									element.checked = false;
+									left.matchCount--;
+									settings.matchCount--;
+								}
+							}
+						});
+					});
+                	
+					left.matchCount++;
+					settings.matchCount++;
+					incremented = true;
+                } else if (left.matchMax != 0 && left.matchMax <= left.matchCount) {
                     inputElement.checked = false;
-                }
-                else {
+                } else {
                     left.matchCount++;
                     settings.matchCount++;
                     incremented = true;
                 }
-
+                // right -> source
                 if (right.matchMax != 0 && right.matchMax <= right.matchCount) {
                     inputElement.checked = false;
-                }
-                else {
+                } else {
                     right.matchCount++;
                     if (!incremented) {
                         settings.matchCount++;
                     }
                 }
-            }
-            else {
+            } else {
                 settings.matchCount--;
                 left.matchCount--;
                 right.matchCount--;
diff --git a/src/main/webapp/static/js/jquery/qti/jquery.order.js b/src/main/webapp/static/js/jquery/qti/jquery.order.js
index 8001bc90508a43b24a64600aa55c3efadb919c23..7aa33724c6fd7abec8e77a428ca679a9d7a9cea2 100644
--- a/src/main/webapp/static/js/jquery/qti/jquery.order.js
+++ b/src/main/webapp/static/js/jquery/qti/jquery.order.js
@@ -10,7 +10,6 @@
 		}, options );
 
 		try {
-			console.log(settings.responseValue);
 			if(typeof settings.responseValue != "undefined" && settings.responseValue.length > 0) {
 				recalculate(settings);
 			}
diff --git a/src/main/webapp/static/js/jquery/qti/jquery.qti.min.js b/src/main/webapp/static/js/jquery/qti/jquery.qti.min.js
index 8af3614bb3f30aa01604f1dbe2e59f9a7d48a3ca..45e0497c44285a2fda1bc002032f34ad1c6b740d 100644
--- a/src/main/webapp/static/js/jquery/qti/jquery.qti.min.js
+++ b/src/main/webapp/static/js/jquery/qti/jquery.qti.min.js
@@ -1 +1 @@
-(function(g){g.fn.associateInteraction=function(m){var n=g.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,opened:false,unrestricted:false},m);try{if(typeof n.responseValue!="undefined"&&n.responseValue.length>0){c(this,n)}if(n.opened){a(this,n)}}catch(o){if(window.console){console.log(o)}}return this};function c(m,q){var t=m.attr("id");var w=q.responseValue.split(",");var u=jQuery("#"+t+"_panel .association");for(var r=0;r<w.length;r++){var p=w[r].split(" ");var s=jQuery(u.get(r));if(s.size()==0){var v=d(t,q);s=jQuery("#"+v)}var o=jQuery("#"+t+"_items div[data-qti-id='"+p[0]+"']");if(e(o,t)){o=jQuery(o).clone()}var n=jQuery("#"+t+"_items div[data-qti-id='"+p[1]+"']");if(e(n,t)){n=jQuery(n).clone()}jQuery(o).addClass("oo-choosed");jQuery(n).addClass("oo-choosed");jQuery(s.find(".association_box.left")).addClass("oo-filled").append(o);jQuery(s.find(".association_box.right")).addClass("oo-filled").append(n)}l(t,q);if(q.unrestricted&&q.opened){i(t,q)}}function a(q,o){var m=q.attr("id");var n=jQuery("#"+m+" .o_associate_item");b(n,m,o);var p=jQuery("#"+m+"_panel .association_box");k(p,m,o)}function b(n,m,o){n.on("click",function(r,q){var p=jQuery(this);if(!p.hasClass("oo-choosed")&&!p.hasClass("oo-selected")){p.addClass("oo-selected")}}).draggable({containment:"#"+m,scroll:false,revert:"invalid",stop:function(p,q){jQuery(this).css({left:"0px",top:"0px"});jQuery(q.helper).removeClass("oo-drag")},helper:function(){var q=jQuery(this);var r=q.parent(".association_box").size()>0;if(!r&&e(this,m)){q.removeClass("oo-selected");var p=q.clone();jQuery(p).attr("id","n"+j()).data("qti-cloned","true").addClass("oo-drag");return p}q.addClass("oo-drag");return q}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function e(r,n){var q=jQuery(r);var p=q.data("qti-match-max");var m=q.data("qti-id");var o=jQuery("#"+n+"_panel div[data-qti-id='"+m+"']").size();return(p==0||o+1<p)}function k(n,m,o){n.on("click",function(r,p){var q=jQuery(this);var s=jQuery(".o_associate_item",this).size();if(s==1){jQuery(".o_associate_item",this).each(function(t,u){h(u,q,m)})}else{jQuery("#"+m+"_items .o_associate_item.oo-selected").each(function(t,v){var u=jQuery(v);if(e(v,m)){u.removeClass("oo-selected");f(u.clone(),q,m)}else{f(u,q,m)}})}l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}).droppable({drop:function(r,s){var q=jQuery(this);var t=jQuery(".o_associate_item",this).size();if(t>0){jQuery(".o_associate_item",this).each(function(u,v){h(v,q,m)})}var p;if(s.helper!=null&&jQuery(s.helper).data("qti-cloned")=="true"){var p=jQuery(s.draggable);p.removeClass("oo-selected").removeClass("oo-drag");p=p.clone();b(p,m,o);f(p,q,m)}else{var p=jQuery(s.draggable);p.removeClass("oo-selected").removeClass("oo-drag");f(p,q,m)}l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function f(o,n,m){o.removeClass("oo-selected").css({left:"0px",top:"0px"}).addClass("oo-choosed").appendTo(n);n.addClass("oo-filled")}function h(r,q,n){q.removeClass("oo-filled");var p=jQuery(r);p.removeClass("oo-choosed");var m=p.data("qti-id");var o=jQuery("#"+n+"_items div[data-qti-id='"+m+"']").size();if(o==0){p.appendTo(jQuery("#"+n+"_items"))}else{p.remove()}}function j(){function m(){return Math.floor((1+Math.random())*65536).toString(16).substring(1)}return m()+m()+m()+m()+m()+m()+m()}function l(m,o){var n=jQuery("#"+m+"_panel");n.find("input[type='hidden']").remove();jQuery("#"+m+"_panel .association").each(function(p,u){var r=jQuery(u).find(".o_associate_item");if(r.length==2){var s=jQuery(r.get(0)).data("qti-id");var q=jQuery(r.get(1)).data("qti-id");var t=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+o.responseIdentifier).attr("value",s+" "+q);n.prepend(t)}else{if(r.length==0&&o.unrestricted){u.remove()}else{jQuery(u).find(".association_box").each(function(x,w){var v=jQuery(w).find(".o_associate_item").size();if(v==0&&jQuery(w).hasClass("oo-filled")){jQuery(w).removeClass("oo-filled")}})}}});i(m,o)}function i(m,p){if(!p.unrestricted||!p.opened){return}var n=jQuery("#"+m+"_panel");var o=true;jQuery("#"+m+"_panel .association").each(function(s,u){var t=jQuery(u).find(".o_associate_item");if(t.length!=2){o=false}});if(o){var r=d(m,p);var q=jQuery("#"+r+" .association_box");k(q,m,p)}}function d(m,n){var o=j();var p='<div id="'+o+'" class="association" style="">\n  <div class="association_box left" style="width: 100px; height:50px; float:left;"></div>\n  <div class="association_box right" style="width: 100px; height:50px; float:right;"></div>\n  <div style="clear:both; "></div>\n</div>\n';jQuery("#"+m+"_panel").append(p);jQuery("#"+m+"_panel").append('<div style="clear:both; "></div>\n');return o}}(jQuery));(function(b){b.fn.choiceInteraction=function(d){var f=b.extend({responseIdentifier:null,formDispatchFieldId:null,maxChoices:0,},d);try{if(f.maxChoices>0){a(this,f);c(f)}}catch(g){if(window.console){console.log(g)}}return this};function a(f,d){var e=jQuery("#qti_container_"+d.responseIdentifier+" input[type=checkbox]");e.on("click",function(g,h){c(d)})}function c(d){var f=jQuery("#qti_container_"+d.responseIdentifier+" input[type=checkbox]");var e=0;f.each(function(g,h){if(h.checked){e++}});if(e>=d.maxChoices){f.each(function(g,h){if(h.checked){h.disabled=false}else{h.disabled=true}})}else{f.each(function(g,h){h.disabled=false})}}}(jQuery));(function(f){f.fn.gapMatchInteraction=function(h){var j=f.extend({responseIdentifier:null,formDispatchFieldId:null,gapChoiceData:{},gapData:{},opened:false,gapChoiceMap:{},gapMap:{},matched:{}},h);for(var i in j.gapChoiceData){var k=jQuery("#qtiworks_id_"+j.responseIdentifier+"_"+i);j.gapChoiceMap[i]={matchMax:j.gapChoiceData[i],matchCount:0,query:k,text:k.text()}}for(var i in j.gapData){var k=jQuery("#qtiworks_id_"+j.responseIdentifier+"_"+i);j.gapMap[i]={required:j.gapData[i],matched:false,matchedGapChoice:null,query:k,label:k.text()}}try{d(this,j)}catch(l){if(window.console){console.log(l)}}return this};function b(j,k,n){var m=k.value;var i=m.split(" ");var h=j.gapChoiceMap[i[0]];var l=j.gapMap[i[1]];n(j,k,m,h,l)}function d(i,h){if(h.opened){e(h.responseIdentifier).on("click",function(){a(h,this);setFlexiFormDirty(h.formDispatchFieldId)})}c(h);g(h)}function e(h){return jQuery("input[name=qtiworks_response_"+h+"]")}function c(j){j.matchCount=0;for(var i in j.gapChoiceMap){j.gapChoiceMap[i].matchCount=0}for(var i in j.gapMap){j.gapMap[i].matched=false;j.gapMap[i].matchedGapChoice=null}e(j.responseIdentifier).each(function(l,m){b(j,this,function(o,p,r,n,q){if(p.checked){n.matchCount++;q.matched=true;q.matchedGapChoice=n;o.matched[r]=true}})});for(var i in j.gapMap){var k=j.gapMap[i];var h;if(k.matched){h=k.matchedGapChoice.text}else{h=k.label}k.query.text(h)}}function g(h){e(h.responseIdentifier).each(function(){b(h,this,function(j,k,m,i,l){if(!j.opened){k.disabled=true}else{if(k.checked){k.disabled=false}else{if(l.matched||(i.matchMax!=0&&i.matchCount>=i.matchMax)){k.disabled=true}else{k.disabled=false}}}})})}function a(h,i){b(h,i,function(k,l,n,j,m){if(l.checked){if(m.matched||(j.matchMax!=0&&j.matchMax<=j.matchCount)){l.checked=false}else{j.matchCount++;m.matched=true;m.matchedGapChoice=j}m.query.text(j.text)}else{j.matchCount--;m.matched=false;m.matchedGapChoice=null;m.query.text(m.label)}g(k)})}}(jQuery));(function(d){d.fn.graphicAssociateInteraction=function(g){var h=d.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxAssociations:1,opened:false},g);try{if(!(typeof h.responseValue==="undefined")&&h.responseValue.length>0){e(this,h.responseValue,h.responseIdentifier)}if(h.opened){c(this,h.maxAssociations,h.responseIdentifier)}}catch(j){if(window.console){console.log(j)}}return this};function c(k,j,h){var g=k.attr("id");jQuery("#"+g+"_container area").on("click",function(t){var l=8;var q=jQuery("#"+g+"_container").data("openolat")||{};if(q.listOfPairs==undefined){q.currentSpot="";q.listOfPairs=[];jQuery("#"+g+"_container").data("openolat",q)}var w=jQuery(this).data("qti-id");if(q.currentSpot==""||q.currentSpot==w){q.currentSpot=w}else{var A=[q.currentSpot,w];q.listOfPairs.push(A);q.currentSpot=""}var m=document.getElementById(g+"_canvas");var u=m.getContext("2d");u.clearRect(0,0,jQuery(m).width(),jQuery(m).height());var B=jQuery("#"+g+"_container");B.find("input[type='hidden']").remove();var z=[];if(q.currentSpot!=""){b(u,"ac_"+h+"_"+q.currentSpot);z.push(q.currentSpot)}for(var p=q.listOfPairs.length;p-->0;){var o=q.listOfPairs[p];for(var n=o.length;n-->0;){if(0>z.indexOf(o[n])){b(u,"ac_"+h+"_"+o[n]);z.push(o[n])}}var s=jQuery("#ac_"+h+"_"+o[1]);var v=jQuery("#ac_"+h+"_"+o[0]);var C=f(s);var y=f(v);u.beginPath();u.moveTo(C[0],C[1]);u.lineTo(y[0],y[1]);u.lineWidth=3;u.stroke();var x=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+h).attr("value",v.data("qti-id")+" "+s.data("qti-id"));B.prepend(x)}})}function e(g,v,t){var o=g.attr("id");var x=jQuery("#"+o+"_container");var k=document.getElementById(o+"_canvas");var q=k.getContext("2d");q.clearRect(0,0,jQuery(k).width(),jQuery(k).height());var w=[];var h=v.split(",");for(var n=h.length;n-->0;){var m=h[n].split(" ");for(var l=m.length;l-->0;){if(0>w.indexOf(m[l])){b(q,"ac_"+t+"_"+m[l]);w.push(m[l])}}if(m.length==2){var p=jQuery("#ac_"+t+"_"+m[1]);var r=jQuery("#ac_"+t+"_"+m[0]);var y=f(p);var u=f(r);q.beginPath();q.moveTo(y[0],y[1]);q.lineTo(u[0],u[1]);q.lineWidth=3;q.stroke();var s=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+t).attr("value",r.data("qti-id")+" "+p.data("qti-id"));x.prepend(s)}}}function b(h,g){jQuery("#"+g).each(function(k,m){var l=jQuery(m);var n=f(l);var j=l.attr("shape");a(h,j,n,0,0)})}function a(j,g,k,h,l){h=h||0;l=l||0;j.beginPath();if(g=="rect"){j.rect(k[0]+h,k[1]+l,k[2]-k[0],k[3]-k[1])}else{if(g=="poly"){j.moveTo(k[0]+h,k[1]+l);for(i=2;i<k.length;i+=2){j.lineTo(k[i]+h,k[i+1]+l)}}else{if(g=="circ"||g=="circle"){j.arc(k[0]+h,k[1]+l,k[2]-2,0,Math.PI*2,false)}}}j.closePath();j.lineWidth=4;j.strokeStyle="#003300";j.stroke();j.fillStyle="green";j.fill()}function f(g){var h=g.attr("coords").split(",");for(i=h.length;i-->0;){h[i]=parseFloat(h[i])}return h}}(jQuery));(function(f){f.fn.graphicGapInteraction=function(j){var k=f.extend({maphilight:null,responseIdentifier:null,formDispatchFieldId:null,responseValue:null,opened:false},j);try{if(!(typeof k.responseValue==="undefined")&&k.responseValue.length>0){b(this,k)}if(k.opened){c(this,k)}}catch(l){if(window.console){console.log(l)}}return this};function b(j,m){var q=j.attr("id");var v=jQuery("#"+q);var l=m.responseValue.split(",");for(var n=l.length;n-->0;){var k=l[n].split(" ");var p=jQuery("#ac_"+m.responseIdentifier+"_"+k[0]);var o=jQuery("#ac_"+m.responseIdentifier+"_"+k[1]);var r,u;if(p.hasClass("gap_item")){r=p;u=o}else{r=o;u=p}var s=g(u);r.css("position","absolute");r.css("left",s[0]+"px");r.css("top",s[1]+"px");r.addClass("oo-choosed");var t=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+m.responseIdentifier).attr("value",r.data("qti-id")+" "+u.data("qti-id"));v.prepend(t)}}function c(l,k){var j=l.attr("id");jQuery(".gap_item").on("click",function(q,p){var o=jQuery(this);if(o.hasClass("oo-choosed")){var n=o.data("drop-timestamp");if(!(typeof n==="undefined")&&n!=null){if((Date.now()-n)<1500){o.data("drop-timestamp",null);return}}o.removeClass("oo-choosed");var m=o.data("qti-id");jQuery("#"+j).find("input[type='hidden']").each(function(r,s){var t=jQuery(s).val();if(t.indexOf(m+" ")==0){jQuery(s).remove()}});o.css({position:"relative",left:"0px",top:"0px"})}else{o.addClass("oo-selected")}}).draggable({containment:"#"+j,scroll:false,revert:"invalid",stop:function(m,n){if(!jQuery(this).hasClass("oo-choosed")){jQuery(this).css({position:"relative",left:"0px",top:"0px"})}}}).mousemove(function(m,s){var u=jQuery(this);if(u.hasClass("ui-draggable-dragging")){var q=jQuery("#"+j+"_img");var p=q.offset();var o=u.offset();var n=o.left+(u.width()/2)-p.left;var t=o.top+(u.height()/2)-p.top;var r=h(n,t,j);if("invalid"!=r){jQuery("#"+j+" area").each(function(v,x){var w=jQuery(x);var y=w.attr("id");if(r==y){w.mouseover()}else{w.mouseout()}});jQuery("#"+r).mouseover()}else{jQuery("#"+j+" area").each(function(v,w){jQuery(w).mouseout()})}}});jQuery("#"+j).droppable({drop:function(m,t){var r=jQuery("#"+j+"_img");var p=r.offset();var u=jQuery(t.draggable);var o=u.offset();var n=o.left+(u.width()/2)-p.left;var w=o.top+(u.height()/2)-p.top;var s=h(n,w,j);if("invalid"!=s){var z=jQuery("#"+s);var v=g(z);var x=z.data("qti-id");var q=u.data("qti-id");u.css("position","absolute");u.css("left",v[0]+"px");u.css("top",v[1]+"px");u.css("border","none");u.removeClass("oo-selected");u.addClass("oo-choosed");var y=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+k.responseIdentifier).attr("value",q+" "+x);jQuery(this).prepend(y);jQuery(z).mouseout();u.data("drop-timestamp",Date.now())}}});jQuery("#"+j+" area").on("click",function(o,n){var m=jQuery(this);jQuery(".gap_item.oo-selected").each(function(q,s){var r=jQuery(s);var t=g(m);var w=m.data("qti-id");var v=r.data("qti-id");r.css("position","absolute");r.css("left",t[0]+"px");r.css("top",t[1]+"px");r.css("border","none");r.removeClass("oo-selected");r.addClass("oo-choosed");var p=jQuery("#"+j);var u=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+k.responseIdentifier).attr("value",v+" "+w);p.prepend(u)})})}function h(l,k,j){var m="invalid";jQuery("#"+j+" area").each(function(r,o){var v=jQuery(o);var u=v.attr("id");var t=v.attr("coords");var s=v.attr("shape");var w=g(v);if("circle"==s){if(a(l,k,w[0],w[1],w[2])){m=u}}else{if("rect"==s){if(d(l,k,w[0],w[1],w[2],w[3])){m=u}}else{if("poly"==s){var n={};n.x=[];n.y=[];var q=w.length/2;var p=0;for(ix=0;ix<q;ix++){n.x[ix]=w[p];n.y[ix]=w[p+1];p+=2}for(i=0;i<n.length;i++){if(e(n.x.length,n.x,n.y,l,k)){m=n.id;break}}}}}});return m}function a(k,o,m,l,j){var n=Math.pow(k-m,2)+Math.pow(o-l,2);return Math.pow(j,2)>=n}function d(j,o,n,l,k,m){if((n<=j)&&(j<=k)&&(l<=o)&&(o<=m)){return true}else{return false}}function e(l,p,o,k,r){var n,m,q=false;for(n=0,m=l-1;n<l;m=n++){if(((o[n]>r)!=(o[m]>r))&&(k<(p[m]-p[n])*(r-o[n])/(o[m]-o[n])+p[n])){q=!q}}return q}function g(j){var k=j.attr("coords").split(",");for(i=k.length;i-->0;){k[i]=parseFloat(k[i])}return k}}(jQuery));(function(c){c.fn.graphicOrderInteraction=function(d){var f=c.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxChoices:1,opened:false},d);try{if(!(typeof f.responseValue==="undefined")&&f.responseValue.length>0){b(this,f)}if(f.opened){a(this,f)}}catch(g){if(window.console){console.log(g)}}return this};function b(d,h){var m=d.attr("id");var r=jQuery("#"+m+"_container");var e=document.getElementById(m+"_canvas");var o=e.getContext("2d");o.clearRect(0,0,jQuery(e).width(),jQuery(e).height());var n=h.responseValue.split(",");for(var k=n.length;k-->0;){if(n[k].length==0){continue}var q=jQuery("#ac_"+h.responseIdentifier+"_"+n[k]);var f=q.data("qti-id");var l=q.attr("coords").split(",");var j=l[0];var g=l[1];o.font="16px Arial";o.fillText(""+(k+1),j,g);var p=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+h.responseIdentifier).attr("value",f);r.prepend(p)}}function a(f,e){var d=f.attr("id");jQuery("#"+d+"_container area").on("click",function(v){var h=8;var x=jQuery(this).attr("id");var l=jQuery(this).data("qti-id");var u=jQuery(this).attr("coords").split(",");var o=u[0];var n=u[1];var t=jQuery("#"+d+"_container").data("openolat")||{};if(t.listOfPoints==undefined){t.listOfPoints=[];jQuery("#"+d+"_container").data("openolat",t)}var s=false;var m=[];for(var q=t.listOfPoints.length;q-->0;){var j=t.listOfPoints[q];var g=((j.x-o)*(j.x-o))+((j.y-n)*(j.y-n));if(h*h>g){s=true}else{m.push(j)}}if(s){t.listOfPoints=m}else{if(t.listOfPoints.length>=e.maxChoices){return false}else{t.listOfPoints.push({x:o,y:n,areaId:x,spotQtiId:l})}}var k=document.getElementById(d+"_canvas");var w=k.getContext("2d");w.clearRect(0,0,jQuery(k).width(),jQuery(k).height());var z=jQuery("#"+d+"_container");z.find("input[type='hidden']").remove();for(var q=t.listOfPoints.length;q-->0;){var j=t.listOfPoints[q];w.font="16px Arial";w.fillText(""+(q+1),j.x,j.y);var y=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+e.responseIdentifier).attr("value",j.spotQtiId);z.prepend(y)}})}}(jQuery));(function(c){c.fn.hotspotInteraction=function(f){var g=c.extend({responseIdentifier:null,formDispatchFieldId:null,maxChoices:1,singleChoice:false,responseValue:null,opened:false,maphilightSettings:{}},f);try{if(!(typeof g.responseValue==="undefined")&&g.responseValue.length>0){a(this,g)}if(g.opened){e(this,g)}}catch(h){if(window.console){console.log(h)}}return this};function a(n,k){var f=n.attr("id");var g=jQuery("#"+f);var j=k.responseValue.split(",");for(i=j.length;i-->0;){var h=jQuery("#ac_"+k.responseIdentifier+"_"+j[i]);var l=h.data("maphilight")||{};l.selectedOn=true;b(l,k.maphilightSettings);h.data("maphilight",l).trigger("alwaysOn.maphilight");var m=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+k.responseIdentifier).attr("value",h.data("qti-id"));g.append(m)}}function e(h,g){var f=h.attr("id");jQuery("#"+f+" map area").each(function(j,k){jQuery(k).on("click",function(){d(this,f,g.responseIdentifier,g.maxChoices,g.singleChoice,g.maphilightSettings)})})}function d(l,j,o,k,q,m){var n=jQuery(l);var h=n.data("maphilight")||{};if((typeof h.selectedOn==="undefined")||!h.selectedOn){if(q){jQuery("area","map[name='"+j+"_map']").each(function(r,t){var s=jQuery(t).data("maphilight")||{};if(s.selectedOn){s.selectedOn=false;b(s,m);jQuery(t).data("maphilight",s).trigger("alwaysOn.maphilight")}})}var f=k;if(f>0){var g=0;jQuery("area","map[name='"+j+"_map']").each(function(r,t){var s=jQuery(t).data("maphilight")||{};if(s.selectedOn){g++}});if(g>=f){return false}}}if(typeof h.selectedOn==="undefined"){h.selectedOn=true}else{h.selectedOn=!h.selectedOn}b(h,m);n.data("maphilight",h).trigger("alwaysOn.maphilight");var p=jQuery("#"+j);p.find("input[type='hidden']").remove();jQuery("area","map[name='"+j+"_map']").each(function(r,t){var u=jQuery(t);var s=u.data("maphilight")||{};if(s.selectedOn){var v=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+o).attr("value",u.data("qti-id"));p.append(v)}})}function b(g,f){if(g.selectedOn){g.fillColor=f.selectedFillColor;g.fillOpacity=f.selectedFillOpacity;g.strokeColor=f.selectedStrokeColor;g.strokeOpacity=f.selectedStrokeOpacity;g.shadow=f.selectedShadow;g.shadowX=0;g.shadowY=0;g.shadowRadius=7;g.shadowColor="000000";g.shadowOpacity=0.8;g.shadowPosition="outside"}else{g.fillColor=f.fillColor;g.fillOpacity=f.fillOpacity;g.strokeColor=f.strokeColor;g.strokeOpacity=f.strokeOpacity;g.shadow=false}}}(jQuery));(function(a){a.fn.rwdImageMaps=function(c){var e=a.extend({fillColor:"bbbbbb",fillOpacity:0.5,strokeColor:"6E6E6E",strokeOpacity:1,},c);var d=this;var b=function(){d.each(function(){if(typeof(a(this).attr("usemap"))=="undefined"){return}var g=this,f=a(g);a("<img />").on("load",function(){var j="width",o="height",p=f.attr(j),l=f.attr(o);if(!p||!l){var q=new Image();q.src=f.attr("src");if(!p){p=q.width}if(!l){l=q.height}}var i=f.width()/100,m=f.height()/100,k=f.attr("usemap").replace("#",""),n="coords";a('map[name="'+k+'"]').find("area").each(function(){var t=a(this);if(!t.data(n)){t.data(n,t.attr(n))}var s=t.data(n).split(","),r=new Array(s.length);for(var h=0;h<r.length;++h){if(h%2===0){r[h]=parseInt(((s[h]/p)*100)*i)}else{r[h]=parseInt(((s[h]/l)*100)*m)}}t.attr(n,r.toString())});f.maphilight({fillColor:e.fillColor,fillOpacity:e.fillOpacity,strokeColor:e.strokeColor,strokeOpacity:e.strokeOpacity,strokeWidth:3,alwaysOn:true})}).attr("src",f.attr("src"))})};a(window).resize(b).trigger("resize");return this}})(jQuery);(function(f){f.fn.matchInteraction=function(h){var j=f.extend({responseIdentifier:null,formDispatchFieldId:null,maxAssociations:1,leftData:{},rightData:{},leftMap:{},rightMap:{},matched:[]},h);for(var i in j.leftData){j.leftMap[i]={matchMax:j.leftData[i],matchCount:0}}for(var i in j.rightData){j.rightMap[i]={matchMax:j.rightData[i],matchCount:0}}try{d(this,j)}catch(k){if(window.console){console.log(k)}}return this};function d(i,h){e(h.responseIdentifier).on("click",function(){a(h,this)});c(h);g(h)}function e(h){return jQuery("input[name=qtiworks_response_"+h+"]")}function b(j,l,n){var m=l.value;var h=m.split(" ");var k=j.leftMap[h[0]];var i=j.rightMap[h[1]];n(l,m,k,i)}function c(i){i.matchCount=0;i.matched={};for(var h in i.leftMap){i.leftMap[h].matchCount=0}for(var h in i.rightMap){i.rightMap[h].matchCount=0}e(i.responseIdentifier).each(function(){b(i,this,function(l,m,k,j){if(l.checked){i.matchCount++;k.matchCount++;j.matchCount++;i.matched[m]=true}})})}function g(h){e(h.responseIdentifier).each(function(){b(h,this,function(k,l,j,i){if(k.checked){k.disabled=false}else{if((h.maxAssociations!=0&&h.matchCount>=h.maxAssociations)||(j.matchMax!=0&&j.matchCount>=j.matchMax)||(i.matchMax!=0&&i.matchCount>=i.matchMax)){k.disabled=true}else{k.disabled=false}}})})}function a(h,i){b(h,i,function(m,n,l,k){if(m.checked){var j=false;if(l.matchMax!=0&&l.matchMax<=l.matchCount){m.checked=false}else{l.matchCount++;h.matchCount++;j=true}if(k.matchMax!=0&&k.matchMax<=k.matchCount){m.checked=false}else{k.matchCount++;if(!j){h.matchCount++}}}else{h.matchCount--;l.matchCount--;k.matchCount--}g(h)})}}(jQuery));(function(h){h.fn.matchInteractionDnd=function(m){var n=h.extend({responseIdentifier:null,formDispatchFieldId:null,maxAssociations:1,responseValue:null,opened:false},m);try{if(typeof n.responseValue!="undefined"&&n.responseValue.length>0){f(this,n)}if(n.opened){i(this,n)}}catch(o){if(window.console){console.log(o)}}return this};function f(m,o){var q=m.attr("id");var w=o.responseValue.split(",");var r=jQuery("#"+q);for(var p=0;p<w.length;p++){var n=w[p].split(" ");var t=n[0];var s=n[1];var v=jQuery("#"+q+" .o_match_dnd_sources li[data-qti-id='"+t+"']");if(g(v,q)){v=jQuery(v).clone()}var u=jQuery("#"+q+" .o_match_dnd_targets ul[data-qti-id='"+s+"']");jQuery(v).addClass("oo-choosed");jQuery(u).addClass("oo-choosed");jQuery(u).addClass("oo-filled").append(v)}l(q,o);if(o.unrestricted&&o.opened){addNewAssociationBoxAndEvents(q,o)}}function i(q,p){var n=q.attr("id");a(n,p);var o=jQuery("#"+n+" .o_match_dnd_source");e(o,n,p);var m=jQuery("#"+n+" .o_match_dnd_target");k(m,n,p)}function a(m,n){jQuery("#"+m+" .o_match_dnd_sources").droppable({tolerance:"pointer",over:function(o,p){jQuery(this).addClass("oo-accepted")},out:function(o,p){jQuery(this).removeClass("oo-accepted")},drop:function(s,t){var r=jQuery(this);r.removeClass("oo-accepted");var q=jQuery(t.draggable);var o=q.data("qti-id");var p=r.find("li[data-qti-id='"+o+"']");if(p.size()>0){if(q.parents(".o_match_dnd_sources").size()==0){q.remove()}}else{q.appendTo(r)}l(m,n);setFlexiFormDirty(n.formDispatchFieldId,false)}}).on("click",{formId:n.formDispatchFieldId},setFlexiFormDirtyByListener)}function e(n,m,o){n.on("click",function(r,q){var p=jQuery(this);if(!p.hasClass("oo-choosed")&&!p.hasClass("oo-selected")){jQuery("#"+m+" .o_match_dnd_sources .o_match_dnd_source").each(function(s,t){jQuery(t).removeClass("oo-selected")});p.addClass("oo-selected")}else{if(p.parents(".o_match_dnd_targets").size()>0&&!p.hasClass("oo-dropped-mrk")){d(p,m);l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}}}).draggable({containment:"#"+m,scroll:false,revert:"invalid",cursorAt:{left:5,top:5},start:function(p,q){jQuery(q.helper).removeClass("oo-dropped-mrk")},stop:function(p,q){jQuery(this).css({left:"0px",top:"0px","z-index":""});jQuery(q.helper).removeClass("oo-drag")},helper:function(){var q=jQuery(this);var r=q.parent(".o_match_dnd_target").size()>0;if(!r&&g(this,m)){q.removeClass("oo-selected");var p=q.clone();jQuery(p).attr("id","n"+j()).data("qti-cloned","true").addClass("oo-drag").addClass("oo-drag-mrk").css("z-index",10).css("width",q.width()).css("height",q.height());return p}q.addClass("oo-drag").addClass("oo-drag-mrk").css("z-index",10);return q}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function j(){function m(){return Math.floor((1+Math.random())*65536).toString(16).substring(1)}return m()+m()+m()+m()+m()+m()+m()}function g(r,n){var q=jQuery(r);if(q.parents(".o_match_dnd_target").size()>0){return false}var o=q.data("qti-match-max");var m=q.data("qti-id");var p=jQuery("#"+n+" .o_match_dnd_targets li[data-qti-id='"+m+"']").size();return(o==0||p+1<o)}function k(n,m,o){n.on("click",function(r,p){var q=jQuery(this);var s=jQuery(".o_associate_item",this).size();if(s==0){jQuery("#"+m+" .o_match_dnd_sources .oo-selected").each(function(t,v){var u=jQuery(v);if(g(v,m)){u.removeClass("oo-selected");u=u.clone();b(u,q,m);e(u,m,o)}else{b(u,q,m)}})}l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}).droppable({tolerance:"pointer",accept:function(q){var p=jQuery(q).data("qti-id");var r=jQuery(".o_match_dnd_source[data-qti-id='"+p+"']",this).size()==0;if(r){var t=jQuery(this).data("qti-match-max");if(t>0){var s=jQuery(".o_match_dnd_source",this).size();if(s>=t){r=false}}}return r},over:function(p,q){jQuery(this).addClass("oo-accepted")},out:function(p,q){jQuery(this).removeClass("oo-accepted")},drop:function(t,u){var s=jQuery(this);s.removeClass("oo-accepted");var r=jQuery(u.draggable);var q=r.data("qti-id");var p=jQuery(".o_match_dnd_source[data-qti-id='"+q+"']",this).size();if(p>0){return}if(u.helper!=null&&jQuery(u.helper).data("qti-cloned")=="true"){r.removeClass("oo-selected").removeClass("oo-drag");r=r.clone();e(r,m,o);b(r,s,m)}else{r.removeClass("oo-selected").removeClass("oo-drag");b(r,s,m)}r.addClass("oo-dropped-mrk");setTimeout(function(){r.removeClass("oo-dropped-mrk")},100);l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function b(o,p,n){var m=p.find("ul.o_match_dnd_target_drop_zone");o.removeClass("oo-selected").css({width:"auto",left:"0px",top:"0px","z-index":""}).addClass("oo-choosed").appendTo(m);p.addClass("oo-filled")}function d(q,n){var p=jQuery(q);p.removeClass("oo-choosed");var m=p.data("qti-id");var o=jQuery("#"+n+" .o_match_dnd_sources li[data-qti-id='"+m+"']").size();if(o==0){p.css({width:"auto",left:"0px",top:"0px","z-index":""}).appendTo(jQuery("#"+n+" .o_match_dnd_sources"))}else{p.remove()}}function l(m,p){p.matchCount=0;p.matched={};for(var o in p.leftMap){p.leftMap[o].matchCount=0}for(var o in p.rightMap){p.rightMap[o].matchCount=0}var n=jQuery("#"+m);n.find("input[type='hidden']").remove();jQuery("#"+m+" .o_match_dnd_target_drop_zone").each(function(r,q){jQuery(q).find(".o_match_dnd_source").each(function(w,s){var u=jQuery(s).data("qti-id");var t=jQuery(q).data("qti-id");var v=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+p.responseIdentifier).attr("value",u+" "+t);n.prepend(v)})})}function c(m,n){withCheckbox(m,n,function(r,s,q,p){if(r.checked){var o=false;if(q.matchMax!=0&&q.matchMax<=q.matchCount){r.checked=false}else{q.matchCount++;m.matchCount++;o=true}if(p.matchMax!=0&&p.matchMax<=p.matchCount){r.checked=false}else{p.matchCount++;if(!o){m.matchCount++}}}else{m.matchCount--;q.matchCount--;p.matchCount--}updateDisabledStates(m)})}}(jQuery));(function(c){c.fn.orderInteraction=function(d){var f=c.extend({responseIdentifier:null,formDispatchFieldId:null,minChoices:null,maxChoices:null,responseValue:null,opened:false},d);try{console.log(f.responseValue);if(typeof f.responseValue!="undefined"&&f.responseValue.length>0){b(f)}if(f.opened){a(this,f)}}catch(g){if(window.console){console.log(g)}}return this};function a(k,g){var d="#qtiworks_response_"+g.responseIdentifier;var i=jQuery(d+" div.source ul");var j=jQuery(d+" div.target ul");var h=jQuery(d+" div.source ul").get(0);var f=jQuery(d+" div.target ul").get(0);var e=dragula([h,f],{copy:function(l,m){return false},accepts:function(l,m){return m!==h}});e.on("drag",function(m,l){}).on("over",function(m,l,n){if(l===f){jQuery(l).addClass("oo-accepted")}}).on("drop",function(m,o,n,l){b(g);setFlexiFormDirty(g.formDispatchFieldId)}).on("dragend",function(l){jQuery(f).removeClass("oo-accepted")}).on("out",function(l){jQuery(f).removeClass("oo-accepted")})}function b(h){var d="#qtiworks_response_"+h.responseIdentifier;var i=jQuery(d+" div.source ul");var j=jQuery(d+" div.target ul");var e=jQuery(d+" div.target");var g=jQuery(d+" div.hiddenInputContainer");var f=j.children("li").size();if(h.minChoices!=null&&h.maxChoices!=null){if(f<h.minChoices||f>h.maxChoices){if(h.minChoices!=h.maxChoices){alert("You must select and order between "+h.minChoices+" and "+h.maxChoices+" items")}else{alert("You must select and order exactly "+h.minChoices+" item"+(minChoices>1?"s":""))}e.toggleClass("highlight",true);return false}else{e.toggleClass("highlight",false)}}var g=jQuery(d+" div.hiddenInputContainer");g.empty();j.children("li").each(function(l){var k=this.id.substring("qtiworks_response_".length);var m=jQuery('<input type="hidden">');m.attr("name","qtiworks_response_"+h.responseIdentifier);m.attr("value",k);g.append(m)})}}(jQuery));(function(b){b.fn.positionObjectStage=function(f){var g=b.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxChoices:1,opened:false},f);try{var d=this.attr("id");jQuery("#"+d+" .items_container .o_item.o_"+g.responseIdentifier).each(function(e,i){jQuery(i).attr("id","object-item-"+e)});if(!(typeof g.responseValue==="undefined")&&g.responseValue.length>0){c(this,g)}if(g.opened){a(this,g)}}catch(h){if(window.console){console.log(h)}}return this};function c(d,f){var k=d.attr("id");var r=jQuery("#"+k);var j=f.responseValue.split(":");var l=jQuery("#"+k+" .items_container .o_item.o_"+f.responseIdentifier);for(var h=j.length;h-->0;){var n=j[h].split(" ");var g=n[0];var e=n[1];var q=jQuery(l.get(h));q.css("position","absolute");q.css("top",e+"px");q.css("left",g+"px");var m=q.attr("id");var o="in-"+m+"-"+f.responseIdentifier;var p=jQuery('<input type="hidden"/>').attr("id",o).attr("name","qtiworks_response_"+f.responseIdentifier).attr("value",g+" "+e);r.prepend(p)}}function a(g,f){var d=g.attr("id");var e=jQuery("#"+d);jQuery("#"+d+" .items_container .o_item.o_"+f.responseIdentifier).draggable({containment:"#"+d,scroll:false,stop:function(h,p){var i=jQuery("#"+d+"_img");var k=jQuery(i).offset().top-jQuery(window).scrollTop();var n=jQuery(i).offset().left-jQuery(window).scrollLeft();var m=jQuery(this).offset().top-jQuery(window).scrollTop();var q=jQuery(this).offset().left-jQuery(window).scrollLeft();var l=Math.round((q-n));var j=Math.round((m-k));var o=jQuery(this).attr("id");var r="in-"+o+"-"+f.responseIdentifier;var s=e.find("#"+r);if(s.length==0){var t=jQuery('<input type="hidden"/>').attr("id",r).attr("name","qtiworks_response_"+f.responseIdentifier).attr("value",l+" "+j);e.prepend(t)}else{s.val(l+" "+j)}setFlexiFormDirty(f.formDispatchFieldId)}})}}(jQuery));(function(a){a.fn.selectPointInteraction=function(d){var f=a.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxChoices:1,opened:false},d);try{if(!(typeof f.responseValue==="undefined")&&f.responseValue.length>0){b(this,f)}if(f.opened){c(this,f)}}catch(g){if(window.console){console.log(g)}}return this};function b(d,h){var e=8;var j=d.attr("id");var q=jQuery("#"+j);var n=h.responseValue.split(":");var g=document.getElementById(j+"_canvas");var k=g.getContext("2d");k.clearRect(0,0,jQuery(g).width(),jQuery(g).height());for(i=n.length;i-->0;){if(n[i].length==0){continue}var f=n[i].split(" ");var m=f[0];var l=f[1];k.beginPath();k.arc(m,l,e,0,Math.PI*2,false);k.stroke();k.closePath();var o=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+h.responseIdentifier).attr("value",m+" "+l);q.append(o)}}function c(f,e){var d=f.attr("id");jQuery("#"+d+"_canvas").on("click",function(u,z){var h=8;var q=jQuery(this).offset().top-jQuery(window).scrollTop();var w=jQuery(this).offset().left-jQuery(window).scrollLeft();var n=Math.round((u.clientX-w));var m=Math.round((u.clientY-q));var s=jQuery("#"+d).data("openolat")||{};if(s.listOfPoints==undefined){s.listOfPoints=[];jQuery("#"+d).data("openolat",s)}var o=false;var l=[];for(i=s.listOfPoints.length;i-->0;){var j=s.listOfPoints[i];var g=((j.x-n)*(j.x-n))+((j.y-m)*(j.y-m));if(Math.pow(h,2)>g){o=true}else{l.push(j)}}if(o){s.listOfPoints=l}else{if(s.listOfPoints.length>=e.maxChoices){return false}else{s.listOfPoints.push({x:n,y:m})}}var k=document.getElementById(d+"_canvas");var v=k.getContext("2d");v.clearRect(0,0,jQuery(k).width(),jQuery(k).height());var y=jQuery("#"+d);y.find("input[type='hidden']").remove();for(i=s.listOfPoints.length;i-->0;){var j=s.listOfPoints[i];v.beginPath();v.arc(j.x,j.y,h,0,Math.PI*2,false);v.stroke();v.closePath();var x=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+e.responseIdentifier).attr("value",j.x+" "+j.y);y.append(x)}setFlexiFormDirty(e.formDispatchFieldId)})}}(jQuery));(function(b){b.fn.sliderInteraction=function(c){var d=b.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,min:1,max:1,step:1,orientation:null,isReversed:false,isDiscrete:false,opened:false,initialValue:null},c);try{a(this,d)}catch(f){if(window.console){console.log(f)}}return this};function a(g,d){var e=jQuery("#qtiworks_id_slider_"+d.responseIdentifier);var f=jQuery('input[name="qtiworks_response_'+d.responseIdentifier+'"]');var c=f.get(0).value||d.min;e.slider({value:c,step:d.step,disabled:!d.opened,orientation:d.orientation,min:d.isReversed?-d.max:d.min,max:d.isReversed?-d.min:d.max,slide:function(h,j){var i=d.isReversed?-j.value:j.value;var l=jQuery("#qtiworks_id_slidervalue_"+d.responseIdentifier);var k=jQuery('input[name="qtiworks_response_'+d.responseIdentifier+'"]');k.get(0).value=i;l.text(i);e.slider("value",d.isReversed?-i:i);setFlexiFormDirty(d.formDispatchFieldId)}})}}(jQuery));
\ No newline at end of file
+(function(g){g.fn.associateInteraction=function(m){var n=g.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,opened:false,unrestricted:false},m);try{if(typeof n.responseValue!="undefined"&&n.responseValue.length>0){c(this,n)}if(n.opened){a(this,n)}}catch(o){if(window.console){console.log(o)}}return this};function c(m,q){var t=m.attr("id");var w=q.responseValue.split(",");var u=jQuery("#"+t+"_panel .association");for(var r=0;r<w.length;r++){var p=w[r].split(" ");var s=jQuery(u.get(r));if(s.size()==0){var v=d(t,q);s=jQuery("#"+v)}var o=jQuery("#"+t+"_items div[data-qti-id='"+p[0]+"']");if(e(o,t)){o=jQuery(o).clone()}var n=jQuery("#"+t+"_items div[data-qti-id='"+p[1]+"']");if(e(n,t)){n=jQuery(n).clone()}jQuery(o).addClass("oo-choosed");jQuery(n).addClass("oo-choosed");jQuery(s.find(".association_box.left")).addClass("oo-filled").append(o);jQuery(s.find(".association_box.right")).addClass("oo-filled").append(n)}l(t,q);if(q.unrestricted&&q.opened){i(t,q)}}function a(q,o){var m=q.attr("id");var n=jQuery("#"+m+" .o_associate_item");b(n,m,o);var p=jQuery("#"+m+"_panel .association_box");k(p,m,o)}function b(n,m,o){n.on("click",function(r,q){var p=jQuery(this);if(!p.hasClass("oo-choosed")&&!p.hasClass("oo-selected")){p.addClass("oo-selected")}}).draggable({containment:"#"+m,scroll:false,revert:"invalid",stop:function(p,q){jQuery(this).css({left:"0px",top:"0px"});jQuery(q.helper).removeClass("oo-drag")},helper:function(){var q=jQuery(this);var r=q.parent(".association_box").size()>0;if(!r&&e(this,m)){q.removeClass("oo-selected");var p=q.clone();jQuery(p).attr("id","n"+j()).data("qti-cloned","true").addClass("oo-drag");return p}q.addClass("oo-drag");return q}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function e(r,n){var q=jQuery(r);var p=q.data("qti-match-max");var m=q.data("qti-id");var o=jQuery("#"+n+"_panel div[data-qti-id='"+m+"']").size();return(p==0||o+1<p)}function k(n,m,o){n.on("click",function(r,p){var q=jQuery(this);var s=jQuery(".o_associate_item",this).size();if(s==1){jQuery(".o_associate_item",this).each(function(t,u){h(u,q,m)})}else{jQuery("#"+m+"_items .o_associate_item.oo-selected").each(function(t,v){var u=jQuery(v);if(e(v,m)){u.removeClass("oo-selected");f(u.clone(),q,m)}else{f(u,q,m)}})}l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}).droppable({drop:function(r,s){var q=jQuery(this);var t=jQuery(".o_associate_item",this).size();if(t>0){jQuery(".o_associate_item",this).each(function(u,v){h(v,q,m)})}var p;if(s.helper!=null&&jQuery(s.helper).data("qti-cloned")=="true"){var p=jQuery(s.draggable);p.removeClass("oo-selected").removeClass("oo-drag");p=p.clone();b(p,m,o);f(p,q,m)}else{var p=jQuery(s.draggable);p.removeClass("oo-selected").removeClass("oo-drag");f(p,q,m)}l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function f(o,n,m){o.removeClass("oo-selected").css({left:"0px",top:"0px"}).addClass("oo-choosed").appendTo(n);n.addClass("oo-filled")}function h(r,q,n){q.removeClass("oo-filled");var p=jQuery(r);p.removeClass("oo-choosed");var m=p.data("qti-id");var o=jQuery("#"+n+"_items div[data-qti-id='"+m+"']").size();if(o==0){p.appendTo(jQuery("#"+n+"_items"))}else{p.remove()}}function j(){function m(){return Math.floor((1+Math.random())*65536).toString(16).substring(1)}return m()+m()+m()+m()+m()+m()+m()}function l(m,o){var n=jQuery("#"+m+"_panel");n.find("input[type='hidden']").remove();jQuery("#"+m+"_panel .association").each(function(p,u){var r=jQuery(u).find(".o_associate_item");if(r.length==2){var s=jQuery(r.get(0)).data("qti-id");var q=jQuery(r.get(1)).data("qti-id");var t=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+o.responseIdentifier).attr("value",s+" "+q);n.prepend(t)}else{if(r.length==0&&o.unrestricted){u.remove()}else{jQuery(u).find(".association_box").each(function(x,w){var v=jQuery(w).find(".o_associate_item").size();if(v==0&&jQuery(w).hasClass("oo-filled")){jQuery(w).removeClass("oo-filled")}})}}});i(m,o)}function i(m,p){if(!p.unrestricted||!p.opened){return}var n=jQuery("#"+m+"_panel");var o=true;jQuery("#"+m+"_panel .association").each(function(s,u){var t=jQuery(u).find(".o_associate_item");if(t.length!=2){o=false}});if(o){var r=d(m,p);var q=jQuery("#"+r+" .association_box");k(q,m,p)}}function d(m,n){var o=j();var p='<div id="'+o+'" class="association" style="">\n  <div class="association_box left" style="width: 100px; height:50px; float:left;"></div>\n  <div class="association_box right" style="width: 100px; height:50px; float:right;"></div>\n  <div style="clear:both; "></div>\n</div>\n';jQuery("#"+m+"_panel").append(p);jQuery("#"+m+"_panel").append('<div style="clear:both; "></div>\n');return o}}(jQuery));(function(b){b.fn.choiceInteraction=function(d){var f=b.extend({responseIdentifier:null,formDispatchFieldId:null,maxChoices:0,},d);try{if(f.maxChoices>0){a(this,f);c(f)}}catch(g){if(window.console){console.log(g)}}return this};function a(f,d){var e=jQuery("#qti_container_"+d.responseIdentifier+" input[type=checkbox]");e.on("click",function(g,h){c(d)})}function c(d){var f=jQuery("#qti_container_"+d.responseIdentifier+" input[type=checkbox]");var e=0;f.each(function(g,h){if(h.checked){e++}});if(e>=d.maxChoices){f.each(function(g,h){if(h.checked){h.disabled=false}else{h.disabled=true}})}else{f.each(function(g,h){h.disabled=false})}}}(jQuery));(function(f){f.fn.gapMatchInteraction=function(h){var j=f.extend({responseIdentifier:null,formDispatchFieldId:null,gapChoiceData:{},gapData:{},opened:false,gapChoiceMap:{},gapMap:{},matched:{}},h);for(var i in j.gapChoiceData){var k=jQuery("#qtiworks_id_"+j.responseIdentifier+"_"+i);j.gapChoiceMap[i]={matchMax:j.gapChoiceData[i],matchCount:0,query:k,text:k.text()}}for(var i in j.gapData){var k=jQuery("#qtiworks_id_"+j.responseIdentifier+"_"+i);j.gapMap[i]={required:j.gapData[i],matched:false,matchedGapChoice:null,query:k,label:k.text()}}try{d(this,j)}catch(l){if(window.console){console.log(l)}}return this};function b(j,k,n){var m=k.value;var i=m.split(" ");var h=j.gapChoiceMap[i[0]];var l=j.gapMap[i[1]];n(j,k,m,h,l)}function d(i,h){if(h.opened){e(h.responseIdentifier).on("click",function(){a(h,this);setFlexiFormDirty(h.formDispatchFieldId)})}c(h);g(h)}function e(h){return jQuery("input[name=qtiworks_response_"+h+"]")}function c(j){j.matchCount=0;for(var i in j.gapChoiceMap){j.gapChoiceMap[i].matchCount=0}for(var i in j.gapMap){j.gapMap[i].matched=false;j.gapMap[i].matchedGapChoice=null}e(j.responseIdentifier).each(function(l,m){b(j,this,function(o,p,r,n,q){if(p.checked){n.matchCount++;q.matched=true;q.matchedGapChoice=n;o.matched[r]=true}})});for(var i in j.gapMap){var k=j.gapMap[i];var h;if(k.matched){h=k.matchedGapChoice.text}else{h=k.label}k.query.text(h)}}function g(h){e(h.responseIdentifier).each(function(){b(h,this,function(j,k,m,i,l){if(!j.opened){k.disabled=true}else{if(k.checked){k.disabled=false}else{if(l.matched||(i.matchMax!=0&&i.matchCount>=i.matchMax)){k.disabled=true}else{k.disabled=false}}}})})}function a(h,i){b(h,i,function(k,l,n,j,m){if(l.checked){if(m.matched||(j.matchMax!=0&&j.matchMax<=j.matchCount)){l.checked=false}else{j.matchCount++;m.matched=true;m.matchedGapChoice=j}m.query.text(j.text)}else{j.matchCount--;m.matched=false;m.matchedGapChoice=null;m.query.text(m.label)}g(k)})}}(jQuery));(function(d){d.fn.graphicAssociateInteraction=function(g){var h=d.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxAssociations:1,opened:false},g);try{if(!(typeof h.responseValue==="undefined")&&h.responseValue.length>0){e(this,h.responseValue,h.responseIdentifier)}if(h.opened){c(this,h.maxAssociations,h.responseIdentifier)}}catch(j){if(window.console){console.log(j)}}return this};function c(k,j,h){var g=k.attr("id");jQuery("#"+g+"_container area").on("click",function(t){var l=8;var q=jQuery("#"+g+"_container").data("openolat")||{};if(q.listOfPairs==undefined){q.currentSpot="";q.listOfPairs=[];jQuery("#"+g+"_container").data("openolat",q)}var w=jQuery(this).data("qti-id");if(q.currentSpot==""||q.currentSpot==w){q.currentSpot=w}else{var A=[q.currentSpot,w];q.listOfPairs.push(A);q.currentSpot=""}var m=document.getElementById(g+"_canvas");var u=m.getContext("2d");u.clearRect(0,0,jQuery(m).width(),jQuery(m).height());var B=jQuery("#"+g+"_container");B.find("input[type='hidden']").remove();var z=[];if(q.currentSpot!=""){b(u,"ac_"+h+"_"+q.currentSpot);z.push(q.currentSpot)}for(var p=q.listOfPairs.length;p-->0;){var o=q.listOfPairs[p];for(var n=o.length;n-->0;){if(0>z.indexOf(o[n])){b(u,"ac_"+h+"_"+o[n]);z.push(o[n])}}var s=jQuery("#ac_"+h+"_"+o[1]);var v=jQuery("#ac_"+h+"_"+o[0]);var C=f(s);var y=f(v);u.beginPath();u.moveTo(C[0],C[1]);u.lineTo(y[0],y[1]);u.lineWidth=3;u.stroke();var x=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+h).attr("value",v.data("qti-id")+" "+s.data("qti-id"));B.prepend(x)}})}function e(g,v,t){var o=g.attr("id");var x=jQuery("#"+o+"_container");var k=document.getElementById(o+"_canvas");var q=k.getContext("2d");q.clearRect(0,0,jQuery(k).width(),jQuery(k).height());var w=[];var h=v.split(",");for(var n=h.length;n-->0;){var m=h[n].split(" ");for(var l=m.length;l-->0;){if(0>w.indexOf(m[l])){b(q,"ac_"+t+"_"+m[l]);w.push(m[l])}}if(m.length==2){var p=jQuery("#ac_"+t+"_"+m[1]);var r=jQuery("#ac_"+t+"_"+m[0]);var y=f(p);var u=f(r);q.beginPath();q.moveTo(y[0],y[1]);q.lineTo(u[0],u[1]);q.lineWidth=3;q.stroke();var s=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+t).attr("value",r.data("qti-id")+" "+p.data("qti-id"));x.prepend(s)}}}function b(h,g){jQuery("#"+g).each(function(k,m){var l=jQuery(m);var n=f(l);var j=l.attr("shape");a(h,j,n,0,0)})}function a(j,g,k,h,l){h=h||0;l=l||0;j.beginPath();if(g=="rect"){j.rect(k[0]+h,k[1]+l,k[2]-k[0],k[3]-k[1])}else{if(g=="poly"){j.moveTo(k[0]+h,k[1]+l);for(i=2;i<k.length;i+=2){j.lineTo(k[i]+h,k[i+1]+l)}}else{if(g=="circ"||g=="circle"){j.arc(k[0]+h,k[1]+l,k[2]-2,0,Math.PI*2,false)}}}j.closePath();j.lineWidth=4;j.strokeStyle="#003300";j.stroke();j.fillStyle="green";j.fill()}function f(g){var h=g.attr("coords").split(",");for(i=h.length;i-->0;){h[i]=parseFloat(h[i])}return h}}(jQuery));(function(f){f.fn.graphicGapInteraction=function(j){var k=f.extend({maphilight:null,responseIdentifier:null,formDispatchFieldId:null,responseValue:null,opened:false},j);try{if(!(typeof k.responseValue==="undefined")&&k.responseValue.length>0){b(this,k)}if(k.opened){c(this,k)}}catch(l){if(window.console){console.log(l)}}return this};function b(j,m){var q=j.attr("id");var v=jQuery("#"+q);var l=m.responseValue.split(",");for(var n=l.length;n-->0;){var k=l[n].split(" ");var p=jQuery("#ac_"+m.responseIdentifier+"_"+k[0]);var o=jQuery("#ac_"+m.responseIdentifier+"_"+k[1]);var r,u;if(p.hasClass("gap_item")){r=p;u=o}else{r=o;u=p}var s=g(u);r.css("position","absolute");r.css("left",s[0]+"px");r.css("top",s[1]+"px");r.addClass("oo-choosed");var t=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+m.responseIdentifier).attr("value",r.data("qti-id")+" "+u.data("qti-id"));v.prepend(t)}}function c(l,k){var j=l.attr("id");jQuery(".gap_item").on("click",function(q,p){var o=jQuery(this);if(o.hasClass("oo-choosed")){var n=o.data("drop-timestamp");if(!(typeof n==="undefined")&&n!=null){if((Date.now()-n)<1500){o.data("drop-timestamp",null);return}}o.removeClass("oo-choosed");var m=o.data("qti-id");jQuery("#"+j).find("input[type='hidden']").each(function(r,s){var t=jQuery(s).val();if(t.indexOf(m+" ")==0){jQuery(s).remove()}});o.css({position:"relative",left:"0px",top:"0px"})}else{o.addClass("oo-selected")}}).draggable({containment:"#"+j,scroll:false,revert:"invalid",stop:function(m,n){if(!jQuery(this).hasClass("oo-choosed")){jQuery(this).css({position:"relative",left:"0px",top:"0px"})}}}).mousemove(function(m,s){var u=jQuery(this);if(u.hasClass("ui-draggable-dragging")){var q=jQuery("#"+j+"_img");var p=q.offset();var o=u.offset();var n=o.left+(u.width()/2)-p.left;var t=o.top+(u.height()/2)-p.top;var r=h(n,t,j);if("invalid"!=r){jQuery("#"+j+" area").each(function(v,x){var w=jQuery(x);var y=w.attr("id");if(r==y){w.mouseover()}else{w.mouseout()}});jQuery("#"+r).mouseover()}else{jQuery("#"+j+" area").each(function(v,w){jQuery(w).mouseout()})}}});jQuery("#"+j).droppable({drop:function(m,t){var r=jQuery("#"+j+"_img");var p=r.offset();var u=jQuery(t.draggable);var o=u.offset();var n=o.left+(u.width()/2)-p.left;var w=o.top+(u.height()/2)-p.top;var s=h(n,w,j);if("invalid"!=s){var z=jQuery("#"+s);var v=g(z);var x=z.data("qti-id");var q=u.data("qti-id");u.css("position","absolute");u.css("left",v[0]+"px");u.css("top",v[1]+"px");u.css("border","none");u.removeClass("oo-selected");u.addClass("oo-choosed");var y=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+k.responseIdentifier).attr("value",q+" "+x);jQuery(this).prepend(y);jQuery(z).mouseout();u.data("drop-timestamp",Date.now())}}});jQuery("#"+j+" area").on("click",function(o,n){var m=jQuery(this);jQuery(".gap_item.oo-selected").each(function(q,s){var r=jQuery(s);var t=g(m);var w=m.data("qti-id");var v=r.data("qti-id");r.css("position","absolute");r.css("left",t[0]+"px");r.css("top",t[1]+"px");r.css("border","none");r.removeClass("oo-selected");r.addClass("oo-choosed");var p=jQuery("#"+j);var u=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+k.responseIdentifier).attr("value",v+" "+w);p.prepend(u)})})}function h(l,k,j){var m="invalid";jQuery("#"+j+" area").each(function(r,o){var v=jQuery(o);var u=v.attr("id");var t=v.attr("coords");var s=v.attr("shape");var w=g(v);if("circle"==s){if(a(l,k,w[0],w[1],w[2])){m=u}}else{if("rect"==s){if(d(l,k,w[0],w[1],w[2],w[3])){m=u}}else{if("poly"==s){var n={};n.x=[];n.y=[];var q=w.length/2;var p=0;for(ix=0;ix<q;ix++){n.x[ix]=w[p];n.y[ix]=w[p+1];p+=2}for(i=0;i<n.length;i++){if(e(n.x.length,n.x,n.y,l,k)){m=n.id;break}}}}}});return m}function a(k,o,m,l,j){var n=Math.pow(k-m,2)+Math.pow(o-l,2);return Math.pow(j,2)>=n}function d(j,o,n,l,k,m){if((n<=j)&&(j<=k)&&(l<=o)&&(o<=m)){return true}else{return false}}function e(l,p,o,k,r){var n,m,q=false;for(n=0,m=l-1;n<l;m=n++){if(((o[n]>r)!=(o[m]>r))&&(k<(p[m]-p[n])*(r-o[n])/(o[m]-o[n])+p[n])){q=!q}}return q}function g(j){var k=j.attr("coords").split(",");for(i=k.length;i-->0;){k[i]=parseFloat(k[i])}return k}}(jQuery));(function(c){c.fn.graphicOrderInteraction=function(d){var f=c.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxChoices:1,opened:false},d);try{if(!(typeof f.responseValue==="undefined")&&f.responseValue.length>0){b(this,f)}if(f.opened){a(this,f)}}catch(g){if(window.console){console.log(g)}}return this};function b(d,h){var m=d.attr("id");var r=jQuery("#"+m+"_container");var e=document.getElementById(m+"_canvas");var o=e.getContext("2d");o.clearRect(0,0,jQuery(e).width(),jQuery(e).height());var n=h.responseValue.split(",");for(var k=n.length;k-->0;){if(n[k].length==0){continue}var q=jQuery("#ac_"+h.responseIdentifier+"_"+n[k]);var f=q.data("qti-id");var l=q.attr("coords").split(",");var j=l[0];var g=l[1];o.font="16px Arial";o.fillText(""+(k+1),j,g);var p=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+h.responseIdentifier).attr("value",f);r.prepend(p)}}function a(f,e){var d=f.attr("id");jQuery("#"+d+"_container area").on("click",function(v){var h=8;var x=jQuery(this).attr("id");var l=jQuery(this).data("qti-id");var u=jQuery(this).attr("coords").split(",");var o=u[0];var n=u[1];var t=jQuery("#"+d+"_container").data("openolat")||{};if(t.listOfPoints==undefined){t.listOfPoints=[];jQuery("#"+d+"_container").data("openolat",t)}var s=false;var m=[];for(var q=t.listOfPoints.length;q-->0;){var j=t.listOfPoints[q];var g=((j.x-o)*(j.x-o))+((j.y-n)*(j.y-n));if(h*h>g){s=true}else{m.push(j)}}if(s){t.listOfPoints=m}else{if(t.listOfPoints.length>=e.maxChoices){return false}else{t.listOfPoints.push({x:o,y:n,areaId:x,spotQtiId:l})}}var k=document.getElementById(d+"_canvas");var w=k.getContext("2d");w.clearRect(0,0,jQuery(k).width(),jQuery(k).height());var z=jQuery("#"+d+"_container");z.find("input[type='hidden']").remove();for(var q=t.listOfPoints.length;q-->0;){var j=t.listOfPoints[q];w.font="16px Arial";w.fillText(""+(q+1),j.x,j.y);var y=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+e.responseIdentifier).attr("value",j.spotQtiId);z.prepend(y)}})}}(jQuery));(function(c){c.fn.hotspotInteraction=function(f){var g=c.extend({responseIdentifier:null,formDispatchFieldId:null,maxChoices:1,singleChoice:false,responseValue:null,opened:false,maphilightSettings:{}},f);try{if(!(typeof g.responseValue==="undefined")&&g.responseValue.length>0){a(this,g)}if(g.opened){e(this,g)}}catch(h){if(window.console){console.log(h)}}return this};function a(n,k){var f=n.attr("id");var g=jQuery("#"+f);var j=k.responseValue.split(",");for(i=j.length;i-->0;){var h=jQuery("#ac_"+k.responseIdentifier+"_"+j[i]);var l=h.data("maphilight")||{};l.selectedOn=true;b(l,k.maphilightSettings);h.data("maphilight",l).trigger("alwaysOn.maphilight");var m=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+k.responseIdentifier).attr("value",h.data("qti-id"));g.append(m)}}function e(h,g){var f=h.attr("id");jQuery("#"+f+" map area").each(function(j,k){jQuery(k).on("click",function(){d(this,f,g.responseIdentifier,g.maxChoices,g.singleChoice,g.maphilightSettings)})})}function d(l,j,o,k,q,m){var n=jQuery(l);var h=n.data("maphilight")||{};if((typeof h.selectedOn==="undefined")||!h.selectedOn){if(q){jQuery("area","map[name='"+j+"_map']").each(function(r,t){var s=jQuery(t).data("maphilight")||{};if(s.selectedOn){s.selectedOn=false;b(s,m);jQuery(t).data("maphilight",s).trigger("alwaysOn.maphilight")}})}var f=k;if(f>0){var g=0;jQuery("area","map[name='"+j+"_map']").each(function(r,t){var s=jQuery(t).data("maphilight")||{};if(s.selectedOn){g++}});if(g>=f){return false}}}if(typeof h.selectedOn==="undefined"){h.selectedOn=true}else{h.selectedOn=!h.selectedOn}b(h,m);n.data("maphilight",h).trigger("alwaysOn.maphilight");var p=jQuery("#"+j);p.find("input[type='hidden']").remove();jQuery("area","map[name='"+j+"_map']").each(function(r,t){var u=jQuery(t);var s=u.data("maphilight")||{};if(s.selectedOn){var v=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+o).attr("value",u.data("qti-id"));p.append(v)}})}function b(g,f){if(g.selectedOn){g.fillColor=f.selectedFillColor;g.fillOpacity=f.selectedFillOpacity;g.strokeColor=f.selectedStrokeColor;g.strokeOpacity=f.selectedStrokeOpacity;g.shadow=f.selectedShadow;g.shadowX=0;g.shadowY=0;g.shadowRadius=7;g.shadowColor="000000";g.shadowOpacity=0.8;g.shadowPosition="outside"}else{g.fillColor=f.fillColor;g.fillOpacity=f.fillOpacity;g.strokeColor=f.strokeColor;g.strokeOpacity=f.strokeOpacity;g.shadow=false}}}(jQuery));(function(a){a.fn.rwdImageMaps=function(c){var e=a.extend({fillColor:"bbbbbb",fillOpacity:0.5,strokeColor:"6E6E6E",strokeOpacity:1,},c);var d=this;var b=function(){d.each(function(){if(typeof(a(this).attr("usemap"))=="undefined"){return}var g=this,f=a(g);a("<img />").on("load",function(){var j="width",o="height",p=f.attr(j),l=f.attr(o);if(!p||!l){var q=new Image();q.src=f.attr("src");if(!p){p=q.width}if(!l){l=q.height}}var i=f.width()/100,m=f.height()/100,k=f.attr("usemap").replace("#",""),n="coords";a('map[name="'+k+'"]').find("area").each(function(){var t=a(this);if(!t.data(n)){t.data(n,t.attr(n))}var s=t.data(n).split(","),r=new Array(s.length);for(var h=0;h<r.length;++h){if(h%2===0){r[h]=parseInt(((s[h]/p)*100)*i)}else{r[h]=parseInt(((s[h]/l)*100)*m)}}t.attr(n,r.toString())});f.maphilight({fillColor:e.fillColor,fillOpacity:e.fillOpacity,strokeColor:e.strokeColor,strokeOpacity:e.strokeOpacity,strokeWidth:3,alwaysOn:true})}).attr("src",f.attr("src"))})};a(window).resize(b).trigger("resize");return this}})(jQuery);(function(f){f.fn.matchInteraction=function(h){var j=f.extend({responseIdentifier:null,formDispatchFieldId:null,maxAssociations:1,leftData:{},rightData:{},leftMap:{},rightMap:{},matched:[]},h);for(var i in j.leftData){j.leftMap[i]={matchMax:j.leftData[i],matchCount:0}}for(var i in j.rightData){j.rightMap[i]={matchMax:j.rightData[i],matchCount:0}}try{d(this,j)}catch(k){if(window.console){console.log(k)}}return this};function d(i,h){e(h.responseIdentifier).on("click",function(){a(h,this)});c(h);g(h)}function e(h){return jQuery("input[name=qtiworks_response_"+h+"]")}function b(j,l,n){var m=l.value;var h=m.split(" ");var k=j.leftMap[h[0]];var i=j.rightMap[h[1]];n(l,m,k,i)}function c(i){i.matchCount=0;i.matched={};for(var h in i.leftMap){i.leftMap[h].matchCount=0}for(var h in i.rightMap){i.rightMap[h].matchCount=0}e(i.responseIdentifier).each(function(){b(i,this,function(l,m,k,j){if(l.checked){i.matchCount++;k.matchCount++;j.matchCount++;i.matched[m]=true}})})}function g(h){e(h.responseIdentifier).each(function(){b(h,this,function(k,l,j,i){if(k.checked){k.disabled=false}else{if(h.maxAssociations!=0&&h.matchCount>=h.maxAssociations){k.disabled=true}else{if(j.matchMax!=0&&j.matchCount>=j.matchMax){if(j.matchMax!=1&&j.matchCount!=1){k.disabled=true}else{k.disabled=false}}else{if(i.matchMax!=0&&i.matchCount>=i.matchMax){k.disabled=true}else{k.disabled=false}}}}})})}function a(h,i){b(h,i,function(p,q,o,m){if(p.checked){var l=false;if(o.matchMax==1){var n=jQuery(p);var k=n.attr("id");var j=n.attr("value").split(" ")[0];e(h.responseIdentifier).each(function(){b(h,this,function(s,w,v,r){var u=jQuery(s);if(k!==u.attr("id")&&s.checked){var t=u.attr("value").split(" ")[0];if(j===t){s.checked=false;v.matchCount--;h.matchCount--}}})});o.matchCount++;h.matchCount++;l=true}else{if(o.matchMax!=0&&o.matchMax<=o.matchCount){p.checked=false}else{o.matchCount++;h.matchCount++;l=true}}if(m.matchMax!=0&&m.matchMax<=m.matchCount){p.checked=false}else{m.matchCount++;if(!l){h.matchCount++}}}else{h.matchCount--;o.matchCount--;m.matchCount--}g(h)})}}(jQuery));(function(h){h.fn.matchInteractionDnd=function(m){var n=h.extend({responseIdentifier:null,formDispatchFieldId:null,maxAssociations:1,responseValue:null,opened:false},m);try{if(typeof n.responseValue!="undefined"&&n.responseValue.length>0){f(this,n)}if(n.opened){i(this,n)}}catch(o){if(window.console){console.log(o)}}return this};function f(m,o){var q=m.attr("id");var w=o.responseValue.split(",");var r=jQuery("#"+q);for(var p=0;p<w.length;p++){var n=w[p].split(" ");var t=n[0];var s=n[1];var v=jQuery("#"+q+" .o_match_dnd_sources li[data-qti-id='"+t+"']");if(g(v,q)){v=jQuery(v).clone()}var u=jQuery("#"+q+" .o_match_dnd_targets ul[data-qti-id='"+s+"']");jQuery(v).addClass("oo-choosed");jQuery(u).addClass("oo-choosed");jQuery(u).addClass("oo-filled").append(v)}l(q,o);if(o.unrestricted&&o.opened){addNewAssociationBoxAndEvents(q,o)}}function i(q,p){var n=q.attr("id");a(n,p);var o=jQuery("#"+n+" .o_match_dnd_source");e(o,n,p);var m=jQuery("#"+n+" .o_match_dnd_target");k(m,n,p)}function a(m,n){jQuery("#"+m+" .o_match_dnd_sources").droppable({tolerance:"pointer",over:function(o,p){jQuery(this).addClass("oo-accepted")},out:function(o,p){jQuery(this).removeClass("oo-accepted")},drop:function(s,t){var r=jQuery(this);r.removeClass("oo-accepted");var q=jQuery(t.draggable);var o=q.data("qti-id");var p=r.find("li[data-qti-id='"+o+"']");if(p.size()>0){if(q.parents(".o_match_dnd_sources").size()==0){q.remove()}}else{q.appendTo(r)}l(m,n);setFlexiFormDirty(n.formDispatchFieldId,false)}}).on("click",{formId:n.formDispatchFieldId},setFlexiFormDirtyByListener)}function e(n,m,o){n.on("click",function(r,q){var p=jQuery(this);if(!p.hasClass("oo-choosed")&&!p.hasClass("oo-selected")){jQuery("#"+m+" .o_match_dnd_sources .o_match_dnd_source").each(function(s,t){jQuery(t).removeClass("oo-selected")});p.addClass("oo-selected")}else{if(p.parents(".o_match_dnd_targets").size()>0&&!p.hasClass("oo-dropped-mrk")){d(p,m);l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}}}).draggable({containment:"#"+m,scroll:false,revert:"invalid",cursorAt:{left:5,top:5},start:function(p,q){jQuery(q.helper).removeClass("oo-dropped-mrk")},stop:function(p,q){jQuery(this).css({left:"0px",top:"0px","z-index":""});jQuery(q.helper).removeClass("oo-drag")},helper:function(){var q=jQuery(this);var r=q.parent(".o_match_dnd_target").size()>0;if(!r&&g(this,m)){q.removeClass("oo-selected");var p=q.clone();jQuery(p).attr("id","n"+j()).data("qti-cloned","true").addClass("oo-drag").addClass("oo-drag-mrk").css("z-index",10).css("width",q.width()).css("height",q.height());return p}q.addClass("oo-drag").addClass("oo-drag-mrk").css("z-index",10);return q}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function j(){function m(){return Math.floor((1+Math.random())*65536).toString(16).substring(1)}return m()+m()+m()+m()+m()+m()+m()}function g(r,n){var q=jQuery(r);if(q.parents(".o_match_dnd_target").size()>0){return false}var o=q.data("qti-match-max");var m=q.data("qti-id");var p=jQuery("#"+n+" .o_match_dnd_targets li[data-qti-id='"+m+"']").size();return(o==0||p+1<o)}function k(n,m,o){n.on("click",function(r,p){var q=jQuery(this);var s=jQuery(".o_associate_item",this).size();if(s==0){jQuery("#"+m+" .o_match_dnd_sources .oo-selected").each(function(t,v){var u=jQuery(v);if(g(v,m)){u.removeClass("oo-selected");u=u.clone();b(u,q,m);e(u,m,o)}else{b(u,q,m)}})}l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}).droppable({tolerance:"pointer",accept:function(q){var p=jQuery(q).data("qti-id");var r=jQuery(".o_match_dnd_source[data-qti-id='"+p+"']",this).size()==0;if(r){var t=jQuery(this).data("qti-match-max");if(t>0){var s=jQuery(".o_match_dnd_source",this).size();if(s>=t){r=false}}}return r},over:function(p,q){jQuery(this).addClass("oo-accepted")},out:function(p,q){jQuery(this).removeClass("oo-accepted")},drop:function(t,u){var s=jQuery(this);s.removeClass("oo-accepted");var r=jQuery(u.draggable);var q=r.data("qti-id");var p=jQuery(".o_match_dnd_source[data-qti-id='"+q+"']",this).size();if(p>0){return}if(u.helper!=null&&jQuery(u.helper).data("qti-cloned")=="true"){r.removeClass("oo-selected").removeClass("oo-drag");r=r.clone();e(r,m,o);b(r,s,m)}else{r.removeClass("oo-selected").removeClass("oo-drag");b(r,s,m)}r.addClass("oo-dropped-mrk");setTimeout(function(){r.removeClass("oo-dropped-mrk")},100);l(m,o);setFlexiFormDirty(o.formDispatchFieldId,false)}}).on("click",{formId:o.formDispatchFieldId},setFlexiFormDirtyByListener)}function b(o,p,n){var m=p.find("ul.o_match_dnd_target_drop_zone");o.removeClass("oo-selected").css({width:"auto",left:"0px",top:"0px","z-index":""}).addClass("oo-choosed").appendTo(m);p.addClass("oo-filled")}function d(q,n){var p=jQuery(q);p.removeClass("oo-choosed");var m=p.data("qti-id");var o=jQuery("#"+n+" .o_match_dnd_sources li[data-qti-id='"+m+"']").size();if(o==0){p.css({width:"auto",left:"0px",top:"0px","z-index":""}).appendTo(jQuery("#"+n+" .o_match_dnd_sources"))}else{p.remove()}}function l(m,p){p.matchCount=0;p.matched={};for(var o in p.leftMap){p.leftMap[o].matchCount=0}for(var o in p.rightMap){p.rightMap[o].matchCount=0}var n=jQuery("#"+m);n.find("input[type='hidden']").remove();jQuery("#"+m+" .o_match_dnd_target_drop_zone").each(function(r,q){jQuery(q).find(".o_match_dnd_source").each(function(w,s){var u=jQuery(s).data("qti-id");var t=jQuery(q).data("qti-id");var v=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+p.responseIdentifier).attr("value",u+" "+t);n.prepend(v)})})}function c(m,n){withCheckbox(m,n,function(r,s,q,p){if(r.checked){var o=false;if(q.matchMax!=0&&q.matchMax<=q.matchCount){r.checked=false}else{q.matchCount++;m.matchCount++;o=true}if(p.matchMax!=0&&p.matchMax<=p.matchCount){r.checked=false}else{p.matchCount++;if(!o){m.matchCount++}}}else{m.matchCount--;q.matchCount--;p.matchCount--}updateDisabledStates(m)})}}(jQuery));(function(c){c.fn.orderInteraction=function(d){var f=c.extend({responseIdentifier:null,formDispatchFieldId:null,minChoices:null,maxChoices:null,responseValue:null,opened:false},d);try{if(typeof f.responseValue!="undefined"&&f.responseValue.length>0){b(f)}if(f.opened){a(this,f)}}catch(g){if(window.console){console.log(g)}}return this};function a(k,g){var d="#qtiworks_response_"+g.responseIdentifier;var i=jQuery(d+" div.source ul");var j=jQuery(d+" div.target ul");var h=jQuery(d+" div.source ul").get(0);var f=jQuery(d+" div.target ul").get(0);var e=dragula([h,f],{copy:function(l,m){return false},accepts:function(l,m){return m!==h}});e.on("drag",function(m,l){}).on("over",function(m,l,n){if(l===f){jQuery(l).addClass("oo-accepted")}}).on("drop",function(m,o,n,l){b(g);setFlexiFormDirty(g.formDispatchFieldId)}).on("dragend",function(l){jQuery(f).removeClass("oo-accepted")}).on("out",function(l){jQuery(f).removeClass("oo-accepted")})}function b(h){var d="#qtiworks_response_"+h.responseIdentifier;var i=jQuery(d+" div.source ul");var j=jQuery(d+" div.target ul");var e=jQuery(d+" div.target");var g=jQuery(d+" div.hiddenInputContainer");var f=j.children("li").size();if(h.minChoices!=null&&h.maxChoices!=null){if(f<h.minChoices||f>h.maxChoices){if(h.minChoices!=h.maxChoices){alert("You must select and order between "+h.minChoices+" and "+h.maxChoices+" items")}else{alert("You must select and order exactly "+h.minChoices+" item"+(minChoices>1?"s":""))}e.toggleClass("highlight",true);return false}else{e.toggleClass("highlight",false)}}var g=jQuery(d+" div.hiddenInputContainer");g.empty();j.children("li").each(function(l){var k=this.id.substring("qtiworks_response_".length);var m=jQuery('<input type="hidden">');m.attr("name","qtiworks_response_"+h.responseIdentifier);m.attr("value",k);g.append(m)})}}(jQuery));(function(b){b.fn.positionObjectStage=function(f){var g=b.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxChoices:1,opened:false},f);try{var d=this.attr("id");jQuery("#"+d+" .items_container .o_item.o_"+g.responseIdentifier).each(function(e,i){jQuery(i).attr("id","object-item-"+e)});if(!(typeof g.responseValue==="undefined")&&g.responseValue.length>0){c(this,g)}if(g.opened){a(this,g)}}catch(h){if(window.console){console.log(h)}}return this};function c(d,f){var k=d.attr("id");var r=jQuery("#"+k);var j=f.responseValue.split(":");var l=jQuery("#"+k+" .items_container .o_item.o_"+f.responseIdentifier);for(var h=j.length;h-->0;){var n=j[h].split(" ");var g=n[0];var e=n[1];var q=jQuery(l.get(h));q.css("position","absolute");q.css("top",e+"px");q.css("left",g+"px");var m=q.attr("id");var o="in-"+m+"-"+f.responseIdentifier;var p=jQuery('<input type="hidden"/>').attr("id",o).attr("name","qtiworks_response_"+f.responseIdentifier).attr("value",g+" "+e);r.prepend(p)}}function a(g,f){var d=g.attr("id");var e=jQuery("#"+d);jQuery("#"+d+" .items_container .o_item.o_"+f.responseIdentifier).draggable({containment:"#"+d,scroll:false,stop:function(h,p){var i=jQuery("#"+d+"_img");var k=jQuery(i).offset().top-jQuery(window).scrollTop();var n=jQuery(i).offset().left-jQuery(window).scrollLeft();var m=jQuery(this).offset().top-jQuery(window).scrollTop();var q=jQuery(this).offset().left-jQuery(window).scrollLeft();var l=Math.round((q-n));var j=Math.round((m-k));var o=jQuery(this).attr("id");var r="in-"+o+"-"+f.responseIdentifier;var s=e.find("#"+r);if(s.length==0){var t=jQuery('<input type="hidden"/>').attr("id",r).attr("name","qtiworks_response_"+f.responseIdentifier).attr("value",l+" "+j);e.prepend(t)}else{s.val(l+" "+j)}setFlexiFormDirty(f.formDispatchFieldId)}})}}(jQuery));(function(a){a.fn.selectPointInteraction=function(d){var f=a.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,maxChoices:1,opened:false},d);try{if(!(typeof f.responseValue==="undefined")&&f.responseValue.length>0){b(this,f)}if(f.opened){c(this,f)}}catch(g){if(window.console){console.log(g)}}return this};function b(d,h){var e=8;var j=d.attr("id");var q=jQuery("#"+j);var n=h.responseValue.split(":");var g=document.getElementById(j+"_canvas");var k=g.getContext("2d");k.clearRect(0,0,jQuery(g).width(),jQuery(g).height());for(i=n.length;i-->0;){if(n[i].length==0){continue}var f=n[i].split(" ");var m=f[0];var l=f[1];k.beginPath();k.arc(m,l,e,0,Math.PI*2,false);k.stroke();k.closePath();var o=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+h.responseIdentifier).attr("value",m+" "+l);q.append(o)}}function c(f,e){var d=f.attr("id");jQuery("#"+d+"_canvas").on("click",function(u,z){var h=8;var q=jQuery(this).offset().top-jQuery(window).scrollTop();var w=jQuery(this).offset().left-jQuery(window).scrollLeft();var n=Math.round((u.clientX-w));var m=Math.round((u.clientY-q));var s=jQuery("#"+d).data("openolat")||{};if(s.listOfPoints==undefined){s.listOfPoints=[];jQuery("#"+d).data("openolat",s)}var o=false;var l=[];for(i=s.listOfPoints.length;i-->0;){var j=s.listOfPoints[i];var g=((j.x-n)*(j.x-n))+((j.y-m)*(j.y-m));if(Math.pow(h,2)>g){o=true}else{l.push(j)}}if(o){s.listOfPoints=l}else{if(s.listOfPoints.length>=e.maxChoices){return false}else{s.listOfPoints.push({x:n,y:m})}}var k=document.getElementById(d+"_canvas");var v=k.getContext("2d");v.clearRect(0,0,jQuery(k).width(),jQuery(k).height());var y=jQuery("#"+d);y.find("input[type='hidden']").remove();for(i=s.listOfPoints.length;i-->0;){var j=s.listOfPoints[i];v.beginPath();v.arc(j.x,j.y,h,0,Math.PI*2,false);v.stroke();v.closePath();var x=jQuery('<input type="hidden"/>').attr("name","qtiworks_response_"+e.responseIdentifier).attr("value",j.x+" "+j.y);y.append(x)}setFlexiFormDirty(e.formDispatchFieldId)})}}(jQuery));(function(b){b.fn.sliderInteraction=function(c){var d=b.extend({responseIdentifier:null,formDispatchFieldId:null,responseValue:null,min:1,max:1,step:1,orientation:null,isReversed:false,isDiscrete:false,opened:false,initialValue:null},c);try{a(this,d)}catch(f){if(window.console){console.log(f)}}return this};function a(g,d){var e=jQuery("#qtiworks_id_slider_"+d.responseIdentifier);var f=jQuery('input[name="qtiworks_response_'+d.responseIdentifier+'"]');var c=f.get(0).value||d.min;e.slider({value:c,step:d.step,disabled:!d.opened,orientation:d.orientation,min:d.isReversed?-d.max:d.min,max:d.isReversed?-d.min:d.max,slide:function(h,j){var i=d.isReversed?-j.value:j.value;var l=jQuery("#qtiworks_id_slidervalue_"+d.responseIdentifier);var k=jQuery('input[name="qtiworks_response_'+d.responseIdentifier+'"]');k.get(0).value=i;l.text(i);e.slider("value",d.isReversed?-i:i);setFlexiFormDirty(d.formDispatchFieldId)}})}}(jQuery));
\ No newline at end of file
diff --git a/src/main/webapp/static/themes/light/_config.scss b/src/main/webapp/static/themes/light/_config.scss
index 0756478dabc02637899485ed7c3725fe641ce944..4bea91ac194b1da24473a2bfc43a340d437e719b 100644
--- a/src/main/webapp/static/themes/light/_config.scss
+++ b/src/main/webapp/static/themes/light/_config.scss
@@ -433,6 +433,9 @@ $o-qti-match-drop-accept-border-color				: darken($brand-info, 25%) !default;
 $o-qti-match-target-border-color						: $brand-info !default;
 $o-qti-match-target-bg								: $state-info-bg !default;
 $o-qti-match-border-radius							: $panel-border-radius !default;
+$o-qti-match-true-false-unanswered-bg				: lighten($gray-lighter, 5%) !default;
+$o-qti-match-true-false-right-bg						: lighten($brand-success, 40%) !default;
+$o-qti-match-true-false-wrong-bg						: lighten($brand-danger, 40%) !default;
 $o-qti-order-source-border-style						: dashed !default;
 $o-qti-order-sources-border-color					: $o-qti-run-infos-border-color !default;
 $o-qti-order-border-radius							: $panel-border-radius !default;
diff --git a/src/main/webapp/static/themes/light/content.css.map b/src/main/webapp/static/themes/light/content.css.map
index e8dc4a71ecfc588b904e61074ff5bc7905548336..f5106438231becc6fea18bcebc823439cb6fdb15 100644
--- a/src/main/webapp/static/themes/light/content.css.map
+++ b/src/main/webapp/static/themes/light/content.css.map
@@ -1,6 +1,6 @@
 {
 "version": 3,
-"mappings": "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",
+"mappings": "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",
 "sources": ["_license.scss","../../bootstrap/stylesheets/bootstrap/_normalize.scss","../../bootstrap/stylesheets/bootstrap/_print.scss","../../bootstrap/stylesheets/bootstrap/_scaffolding.scss","../../bootstrap/stylesheets/bootstrap/mixins/_vendor-prefixes.scss","_config.scss","../../bootstrap/stylesheets/bootstrap/_variables.scss","../../bootstrap/stylesheets/bootstrap/mixins/_tab-focus.scss","../../bootstrap/stylesheets/bootstrap/mixins/_image.scss","../../bootstrap/stylesheets/bootstrap/_type.scss","../../bootstrap/stylesheets/bootstrap/mixins/_text-emphasis.scss","../../bootstrap/stylesheets/bootstrap/mixins/_background-variant.scss","../../bootstrap/stylesheets/bootstrap/mixins/_clearfix.scss","../../bootstrap/stylesheets/bootstrap/mixins/_text-overflow.scss","../../font-awesome/scss/_path.scss","../../font-awesome/scss/_core.scss","modules/_helpers.scss","../../bootstrap/stylesheets/bootstrap/mixins/_opacity.scss","modules/_dialog.scss","modules/_mixins.scss","modules/_emoticons.scss","modules/_content.scss","modules/_content_embedded.scss","../../bootstrap/stylesheets/bootstrap/mixins/_border-radius.scss","../../font-awesome/scss/_variables.scss","modules/_tinymce.scss","modules/_print.scss"],
 "names": [],
 "file": "content.css"
diff --git a/src/main/webapp/static/themes/light/modules/_icons.scss b/src/main/webapp/static/themes/light/modules/_icons.scss
index 38512891dbd9dba5342e7140ccc03bcfadda3a1d..d76767176e8e2fdbc048904bfc2bddb911b80614 100644
--- a/src/main/webapp/static/themes/light/modules/_icons.scss
+++ b/src/main/webapp/static/themes/light/modules/_icons.scss
@@ -470,6 +470,7 @@ $fa-css-prefix: "o_icon" !default;
 .o_mi_qtisc:before { content: $fa-var-dot-circle-o; }
 .o_mi_qtimatch:before { content: $fa-var-table; }
 .o_mi_qtimatch_draganddrop:before { content: $fa-var-clone; }
+.o_mi_qtimatch_truefalse:before { content: $fa-var-list-ol; }
 .o_mi_qtimc:before { content: $fa-var-check-square-o; }
 .o_mi_qtikprim:before { content: $fa-var-check-square;  }
 .o_mi_qtifib:before { content: $fa-var-ellipsis-h; }
diff --git a/src/main/webapp/static/themes/light/modules/_qti21.scss b/src/main/webapp/static/themes/light/modules/_qti21.scss
index 746cee42ba4687bc1286d117b46a34cfbb39b2bc..acf88255f843db3d9922e4b1155cc912d07e31ae 100644
--- a/src/main/webapp/static/themes/light/modules/_qti21.scss
+++ b/src/main/webapp/static/themes/light/modules/_qti21.scss
@@ -866,6 +866,53 @@ tr.choiceinteraction {
 	}
 }
 
+/* Match true/false */
+.table.o_match_true_false_edit {
+	th.o_sel_match_target_0, th.o_sel_match_target_1, th.o_sel_match_target_2 {
+		width: 12%;
+	}
+}
+
+.match_true_false {
+
+	input[type="checkbox"] {
+		-webkit-appearance: radio;
+		-moz-appearance: radio;
+		-ms-appearance: radio;
+		appearance: radio;
+	}
+
+	.table>tbody>tr>td.o_match_true_false_unanswered,
+	.table>tbody>tr>td.o_match_true_false_right,
+	.table>tbody>tr>td.o_match_true_false_wrong {
+		vertical-align: middle;
+		width: 11%;
+	}
+	
+	th.o_match_true_false_unanswered,
+	th.o_match_true_false_right,
+	th.o_match_true_false_wrong {
+		width: 11%;
+	}
+	
+	td.o_match_true_false_answer,
+	th.o_match_true_false_answer {
+		width: 67%;
+	}
+	
+	td.o_match_true_false_unanswered {
+		background-color: $o-qti-match-true-false-unanswered-bg;
+	}
+	
+	td.o_match_true_false_right {
+		background-color: $o-qti-match-true-false-right-bg;
+	}
+	
+	td.o_match_true_false_wrong {
+		background-color: $o-qti-match-true-false-wrong-bg;
+	}
+}
+
 /* MathEntryInteraction styling for MathAssess */
 .o_assessmentitem .mathEntryInteraction {
 	border: 1px solid #ddedfc;
diff --git a/src/main/webapp/static/themes/openolat/content.css.map b/src/main/webapp/static/themes/openolat/content.css.map
index ced71d8c4e1e1ec9be1733241d9a22f739fdfd58..3b26712a57c9247d51836102c73f0480e6080b9c 100644
--- a/src/main/webapp/static/themes/openolat/content.css.map
+++ b/src/main/webapp/static/themes/openolat/content.css.map
@@ -1,6 +1,6 @@
 {
 "version": 3,
-"mappings": "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",
+"mappings": "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",
 "sources": ["../light/_license.scss","../../bootstrap/stylesheets/bootstrap/_normalize.scss","../../bootstrap/stylesheets/bootstrap/_print.scss","../../bootstrap/stylesheets/bootstrap/_scaffolding.scss","../../bootstrap/stylesheets/bootstrap/mixins/_vendor-prefixes.scss","../light/_config.scss","../../bootstrap/stylesheets/bootstrap/_variables.scss","../../bootstrap/stylesheets/bootstrap/mixins/_tab-focus.scss","../../bootstrap/stylesheets/bootstrap/mixins/_image.scss","../../bootstrap/stylesheets/bootstrap/_type.scss","../../bootstrap/stylesheets/bootstrap/mixins/_text-emphasis.scss","../../bootstrap/stylesheets/bootstrap/mixins/_background-variant.scss","../../bootstrap/stylesheets/bootstrap/mixins/_clearfix.scss","../../bootstrap/stylesheets/bootstrap/mixins/_text-overflow.scss","../../font-awesome/scss/_path.scss","../../font-awesome/scss/_core.scss","../light/modules/_helpers.scss","../../bootstrap/stylesheets/bootstrap/mixins/_opacity.scss","../light/modules/_dialog.scss","../light/modules/_mixins.scss","../light/modules/_emoticons.scss","../light/modules/_content.scss","../light/modules/_content_embedded.scss","../../bootstrap/stylesheets/bootstrap/mixins/_border-radius.scss","../../font-awesome/scss/_variables.scss","../light/modules/_tinymce.scss","../light/modules/_print.scss"],
 "names": [],
 "file": "content.css"
diff --git a/src/test/java/org/olat/core/util/xml/XMLDigitalSignatureUtilTest.java b/src/test/java/org/olat/core/util/xml/XMLDigitalSignatureUtilTest.java
index c24d2b36287b4ca0d497799c23af1c798b33dc5e..61cdd7ac87ac4c5bd6791b13d890ba4ffb85f79e 100644
--- a/src/test/java/org/olat/core/util/xml/XMLDigitalSignatureUtilTest.java
+++ b/src/test/java/org/olat/core/util/xml/XMLDigitalSignatureUtilTest.java
@@ -40,6 +40,19 @@ import org.w3c.dom.NodeList;
  */
 public class XMLDigitalSignatureUtilTest {
 	
+	/**
+	 * Preliminary test which read the certificate. The method is used in
+	 * every other test of the class.
+	 * 
+	 * @throws Exception
+	 */
+	@Test
+	public void readCertificatePrivateKeyPair() throws Exception {
+		X509CertificatePrivateKeyPair keyPair = getCertificatePrivateKeyPair();
+		Assert.assertNotNull(keyPair);
+		Assert.assertNotNull(keyPair.getPrivateKey());
+		Assert.assertNotNull(keyPair.getX509Cert());
+	}
 	
 	/**
 	 * Check if the cycle sign -> validation works
diff --git a/src/test/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctionsTest.java b/src/test/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctionsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8feee7bf9280a8f58f6b0f15ef5edadd8e48c7da
--- /dev/null
+++ b/src/test/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctionsTest.java
@@ -0,0 +1,75 @@
+package org.olat.ims.qti21.ui.components;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import uk.ac.ed.ph.jqtiplus.types.Identifier;
+import uk.ac.ed.ph.jqtiplus.value.IdentifierValue;
+import uk.ac.ed.ph.jqtiplus.value.IntegerValue;
+import uk.ac.ed.ph.jqtiplus.value.MultipleValue;
+import uk.ac.ed.ph.jqtiplus.value.NullValue;
+import uk.ac.ed.ph.jqtiplus.value.OrderedValue;
+import uk.ac.ed.ph.jqtiplus.value.Value;
+
+/**
+ * 
+ * Initial date: 5 févr. 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentRenderFunctionsTest {
+
+	@Test
+	public void valueContains_nullValue() {
+		NullValue nullVal = NullValue.INSTANCE;
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(null, Identifier.parseString("noid")));
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(nullVal, Identifier.parseString("noid")));
+	}
+	
+	@Test
+	public void valueContains_identifierValue() {
+		IdentifierValue identifierVal = new IdentifierValue(Identifier.parseString("reference-id"));
+		Assert.assertTrue(AssessmentRenderFunctions.valueContains(identifierVal, Identifier.parseString("reference-id")));
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(identifierVal, Identifier.parseString("noid")));
+	}
+	
+	@Test
+	public void valueContains_multipleValues() {
+		Value identifierValues = MultipleValue.createMultipleValue(
+				new IdentifierValue(Identifier.parseString("reference-id")),
+				new IdentifierValue(Identifier.parseString("reference-id")));
+		
+		Assert.assertTrue(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("reference-id")));
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("noid")));
+	}
+	
+	@Test
+	public void valueContains_multipleAlienValues() {
+		Value identifierValues = MultipleValue.createMultipleValue(
+				new IntegerValue(6),
+				new IntegerValue(7));
+		
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("6")));
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("noid")));
+	}
+	
+	@Test
+	public void valueContains_orderedValues() {
+		Value identifierValues = OrderedValue.createOrderedValue(
+				new IdentifierValue(Identifier.parseString("reference-id")),
+				new IdentifierValue(Identifier.parseString("reference-id")));
+		
+		Assert.assertTrue(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("reference-id")));
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("noid")));
+	}
+	
+	@Test
+	public void valueContains_orderedAlienValues() {
+		Value identifierValues = OrderedValue.createOrderedValue(
+				new IntegerValue(6),
+				new IntegerValue(7));
+		
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("7")));
+		Assert.assertFalse(AssessmentRenderFunctions.valueContains(identifierValues, Identifier.parseString("noid")));
+	}
+}
diff --git a/src/test/java/org/olat/portfolio/manager/EPStructureManagerTest.java b/src/test/java/org/olat/portfolio/manager/EPStructureManagerTest.java
index 7120df27658011c2ecc64689a672a1bd4be34b1e..fbcf19300e2cc08b6e9ca01a53b0825fd6220704 100644
--- a/src/test/java/org/olat/portfolio/manager/EPStructureManagerTest.java
+++ b/src/test/java/org/olat/portfolio/manager/EPStructureManagerTest.java
@@ -40,13 +40,12 @@ import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Persistable;
 import org.olat.core.id.Roles;
-import org.olat.portfolio.manager.EPFrontendManager;
-import org.olat.portfolio.manager.EPStructureManager;
 import org.olat.portfolio.model.artefacts.AbstractArtefact;
 import org.olat.portfolio.model.structel.EPStructureElement;
 import org.olat.portfolio.model.structel.EPStructureToStructureLink;
 import org.olat.portfolio.model.structel.EPStructuredMap;
 import org.olat.portfolio.model.structel.EPTargetResource;
+import org.olat.portfolio.model.structel.ElementType;
 import org.olat.portfolio.model.structel.PortfolioStructure;
 import org.olat.portfolio.model.structel.PortfolioStructureMap;
 import org.olat.repository.RepositoryEntry;
@@ -102,29 +101,55 @@ public class EPStructureManagerTest extends OlatTestCase {
 	}
 	
 	@Test
-	public void testGetStructureElementsForUser(){
+	public void testGetStructureElementsForUser() {
 		Identity user = JunitTestHelper.createAndPersistIdentityAsRndUser("EP-1-");
 		
 		PortfolioStructure el = epFrontendManager.createAndPersistPortfolioDefaultMap(user, "users-test-map", "a-map-to-test-get-afterwards");
-		assertNotNull(el);
+		Assert.assertNotNull(el);
 		dbInstance.commitAndCloseSession();
 		
 		List<SecurityGroup> secGroups = securityManager.getSecurityGroupsForIdentity(user);
-		assertNotNull(secGroups);
-		assertTrue(secGroups.size() >= 1);
+		Assert.assertNotNull(secGroups);
+		Assert.assertTrue(secGroups.size() >= 1);
 		
-		List<PortfolioStructure> elRes = epFrontendManager.getStructureElementsForUser(user);
-		assertNotNull(elRes);
-		assertTrue(elRes.size() == 1);
-		assertEquals( ((EPStructureElement)elRes.get(0)).getTitle(), "users-test-map");
+		List<PortfolioStructure> elRes = epStructureManager.getStructureElementsForUser(user, ElementType.DEFAULT_MAP);
+		Assert.assertNotNull(elRes);
+		Assert.assertEquals(1, elRes.size());
+		Assert.assertEquals("users-test-map", elRes.get(0).getTitle());
 
 		// get another map
 		PortfolioStructure el2 = epFrontendManager.createAndPersistPortfolioDefaultMap(user, "users-test-map-2", "2-a-map-to-test-get-afterwards");
-		assertNotNull(el2);
+		Assert.assertNotNull(el2);
 		dbInstance.commitAndCloseSession();
-		List<PortfolioStructure> elRes2 = epFrontendManager.getStructureElementsForUser(user);
-		assertNotNull(elRes2);
-		assertTrue(elRes2.size() == 2);
+		List<PortfolioStructure> elRes2 = epStructureManager.getStructureElementsForUser(user);
+		Assert.assertNotNull(elRes2);
+		Assert.assertEquals(2, elRes2.size());
+	}
+	
+	@Test
+	public void testGetStructureElementsForUser_byElementTypes() {
+		Identity user = JunitTestHelper.createAndPersistIdentityAsRndUser("EP-1-");
+		
+		PortfolioStructure el = epFrontendManager.createAndPersistPortfolioDefaultMap(user, "users-def-map", "");
+		Assert.assertNotNull(el);
+		dbInstance.commitAndCloseSession();
+		
+		//by default map
+		List<PortfolioStructure> defaultRes = epStructureManager.getStructureElementsForUser(user, ElementType.DEFAULT_MAP);
+		Assert.assertNotNull(defaultRes);
+		Assert.assertEquals(1, defaultRes.size());
+		Assert.assertEquals("users-def-map", defaultRes.get(0).getTitle());
+		
+		//by default map and structured
+		List<PortfolioStructure> multipleRes = epStructureManager.getStructureElementsForUser(user, ElementType.DEFAULT_MAP, ElementType.STRUCTURED_MAP);
+		Assert.assertNotNull(multipleRes);
+		Assert.assertEquals(1, multipleRes.size());
+		Assert.assertEquals("users-def-map", multipleRes.get(0).getTitle());
+		
+		//by structured
+		List<PortfolioStructure> structuredRes = epStructureManager.getStructureElementsForUser(user, ElementType.STRUCTURED_MAP);
+		Assert.assertNotNull(structuredRes);
+		Assert.assertTrue(structuredRes.isEmpty());
 	}
 	
 	@Test
diff --git a/src/test/java/org/olat/selenium/BusinessGroupTest.java b/src/test/java/org/olat/selenium/BusinessGroupTest.java
index ca6f172de2312406a3f995c9b55da2cc2e1ff229..0ac3b8593da514b2288a99e6427834b4d6c92259 100644
--- a/src/test/java/org/olat/selenium/BusinessGroupTest.java
+++ b/src/test/java/org/olat/selenium/BusinessGroupTest.java
@@ -311,8 +311,7 @@ public class BusinessGroupTest extends Deployments {
 			.openAddDropMenu()
 			.addTokenMethod()
 			.configureTokenMethod(token, description)
-			.assertOnToken(token)
-			.save();
+			.assertOnToken(token);
 		
 		//members see members
 		group = GroupPage.getGroup(browser)
@@ -801,6 +800,7 @@ public class BusinessGroupTest extends Deployments {
 		Assert.assertEquals(1, participants);
 		Assert.assertEquals(2, waitingList);
 	}
+	
 	/**
 	 * An author create a course, with an enrollment course element. It
 	 * configure it and create 3 groups and set the maximum enrollment counter to 2<br>
@@ -813,7 +813,6 @@ public class BusinessGroupTest extends Deployments {
 	 * @throws IOException
 	 * @throws URISyntaxException
 	 */
-
 	@Test
 	@RunAsClient
 	public void enrollmentWithMultiEnrollment(@InitialPage LoginPage authorLoginPage,
diff --git a/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java b/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java
index 75a334bfecb8d7da982d4b7a50a8ad94146195f2..d9373778750c9e7884a1474bfdb7888422170c3b 100644
--- a/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java
+++ b/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java
@@ -50,6 +50,7 @@ import org.olat.selenium.page.qti.QTI21MatchEditorPage;
 import org.olat.selenium.page.qti.QTI21MultipleChoiceEditorPage;
 import org.olat.selenium.page.qti.QTI21Page;
 import org.olat.selenium.page.qti.QTI21SingleChoiceEditorPage;
+import org.olat.selenium.page.qti.QTI21Page.TrueFalse;
 import org.olat.selenium.page.repository.RepositoryAccessPage.UserAccess;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.rest.UserRestClient;
@@ -153,6 +154,85 @@ public class ImsQTI21EditorTest extends Deployments {
 			.assertOnAssessmentTestMaxScore(9);
 	}
 	
+	/**
+	 * Create a test, import a CSV with some match variants,
+	 * remove the first single choice which come if someone
+	 * create a test. Change the delivery settings of the test
+	 * to show the detailled results.<br>
+	 * Run the test and check the results. 
+	 * 
+	 * @param loginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void importQuestionsCSVMatchVariants(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "ExcelMatch QTI 2.1 " + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createQTI21Test(qtiTestTitle)
+			.clickToolbarBack();
+
+		QTI21Page qtiPage = QTI21Page
+			.getQTI12Page(browser);
+		QTI21EditorPage qtiEditor = qtiPage
+			.edit();
+		
+		// import a single choice, a multiple and 2 gap texts
+		qtiEditor
+			.importTable()
+			.importFile("qti21/import_qti21_excel_match.txt")
+			.next()
+			.assertOnNumberOfQuestions(3)
+			.finish();
+		
+		//remove the single choice which come from the creation
+		// of the test
+		qtiEditor
+			.selectNode("Single choice")
+			.deleteNode();
+		
+		// go to options and show the results
+		qtiPage
+			.clickToolbarBack()
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		
+		//go to the test
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerMatch("Berlin", "Deutschland", true)
+			.answerMatch("Bern", "Schweiz", true)
+			.answerMatch("Paris", "Frankreich", true)
+			.saveAnswer()
+			.nextAnswer()
+			.assertOnAssessmentItem("Afrika")
+			.answerMatchDropSourceToTarget("Nairobi", "Kenia")
+			.answerMatchDropSourceToTarget("Windhoek", "Namibia")
+			.answerMatchDropSourceToTarget("Algier", "Algerien")
+			.saveAnswer()
+			.assertOnAssessmentItem("Europa")
+			.answerMatch("Paris", TrueFalse.right, true)
+			.answerMatch("Bern", TrueFalse.right, true)
+			.answerMatch("Stockholm", TrueFalse.wrong, true)
+			.saveAnswer()
+			.endTest();
+		
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentTestScore(9)
+			.assertOnAssessmentTestMaxScore(9);
+	}
+	
 	/**
 	 * Test different settings in the single choice editor. An author
 	 * make a test with 2 single choices, one with score all answer correct,
@@ -2525,6 +2605,184 @@ public class ImsQTI21EditorTest extends Deployments {
 			.assertOnAssessmentResults()
 			.assertOnAssessmentTestScore(12);// 4 points from the first question, 8 from the second	
 	}
+	
+
+	/**
+	 * An author make a test with 2 matches of the True/false variant. A match
+	 * with score "all answers", a second with score "per answers".<br>
+	 * A first user make the test, but doesn't answer all questions
+	 * correctly, log out and a second user make the perfect test.
+	 * 
+	 * @param authorLoginPage
+	 * @param participantBrowser
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21EditorMatchTrueFalse(@InitialPage LoginPage authorLoginPage,
+			@Drone @User WebDriver participantBrowser)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		UserVO rei = new UserRestClient(deploymentUrl).createRandomUser("Rei");
+		UserVO asuka = new UserRestClient(deploymentUrl).createRandomUser("Asuka");
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		String qtiTestTitle = "True false QTI 2.1 " + UUID.randomUUID();
+		navBar
+			.openAuthoringEnvironment()
+			.createQTI21Test(qtiTestTitle)
+			.clickToolbarBack();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		QTI21EditorPage qtiEditor = qtiPage
+				.edit();
+		//start a blank test
+		qtiEditor
+			.selectNode("Single choice")
+			.deleteNode();
+		
+		//add a match, score "all answers"
+		QTI21MatchEditorPage matchEditor = qtiEditor
+			.addMatchTrueFalse();
+		matchEditor
+			.setSource(0, "Eclipse is a Java IDE")
+			.setSource(1, "vim is Database viewer")
+			.setMatch(0, 1, true)
+			.setMatch(1, 2, true)
+			.save();
+		// change max score
+		matchEditor
+			.selectScores()
+			.setMaxScore("4")
+			.save();
+		// set some feedbacks
+		matchEditor
+			.selectFeedbacks()
+			.setHint("Hint", "This is only an hint")
+			.setCorrectSolution("Correct solution", "This is the correct solution")
+			.setCorrectFeedback("Correct feedback", "This is correct")
+			.setIncorrectFeedback("Incorrect", "Your answer is not correct")
+			.save();
+		
+		// second match
+		matchEditor = qtiEditor
+			.addMatchTrueFalse()
+			.setSource(0, "Java has several IDE like Eclipse")
+			.setSource(1, "C is object oriented")
+			.addRow()
+			.setSource(2, "What do you think of PHP?")
+			.setMatch(0, 1, true)
+			.setMatch(1, 2, true)
+			.setMatch(2, 0, true)
+			.save();
+		// select score "per answer" and set the scores
+		matchEditor
+			.selectScores()
+			.selectAssessmentMode(ScoreEvaluation.perAnswer)
+			.setMaxScore("3")
+			.setScore(0, 0, "0.0")
+			.setScore(0, 1, "1.0")
+			.setScore(0, 2, "0.0")
+			.setScore(1, 0, "0.0")
+			.setScore(1, 1, "0.0")
+			.setScore(1, 2, "1.0")
+			.setScore(2, 0, "1.0")
+			.setScore(2, 1, "0.0")
+			.setScore(2, 2, "0.0")
+			.save();
+		matchEditor
+			.selectFeedbacks()
+			.setHint("Hint", "The hint")
+			.setCorrectSolution("Correct solution", "This is the correct solution")
+			.setCorrectFeedback("Correct feedback", "This is correct")
+			.setIncorrectFeedback("Incorrect", "Your answer is not correct")
+			.save();
+		
+
+		qtiPage
+			.clickToolbarBack();
+		// access to all
+		qtiPage
+			.accessConfiguration()
+			.setUserAccess(UserAccess.guest)
+			.clickToolbarBack();
+		// show results
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		
+		//a user search the content package
+		LoginPage reiLoginPage = LoginPage.getLoginPage(participantBrowser, deploymentUrl);
+		reiLoginPage
+			.loginAs(rei.getLogin(), rei.getPassword())
+			.resume();
+		NavigationPage reiNavBar = new NavigationPage(participantBrowser);
+		reiNavBar
+			.openMyCourses()
+			.openSearch()
+			.extendedSearch(qtiTestTitle)
+			.select(qtiTestTitle)
+			.start();
+		
+		// make the test
+		QTI21Page reiQtiPage = QTI21Page
+				.getQTI12Page(participantBrowser);
+		reiQtiPage
+			.assertOnAssessmentItem()
+			.answerMatch("Eclipse", TrueFalse.right, true)
+			.answerMatch("vim", TrueFalse.right, true)
+			.saveAnswer()
+			.assertFeedback("Incorrect")
+			.assertCorrectSolution("Correct solution")
+			.hint()
+			.assertFeedback("Hint")
+			.answerMatch("vim", TrueFalse.wrong, true)
+			.saveAnswer()
+			.assertFeedback("Correct feedback")
+			.nextAnswer()
+			.answerMatch("Java", TrueFalse.right, true)
+			.answerMatch("oriented", TrueFalse.wrong, true)
+			.answerMatch("PHP", TrueFalse.wrong, true)
+			.saveAnswer()
+			.assertCorrectSolution("Correct solution")
+			.assertFeedback("Incorrect")
+			.endTest()
+			.assertOnAssessmentResults()
+			.assertOnAssessmentTestScore(6);// 4 points from the first question, 2 from the second
+		
+
+		//a second user search the content package
+		LoginPage asukaLoginPage = LoginPage.getLoginPage(participantBrowser, deploymentUrl);
+		asukaLoginPage
+			.loginAs(asuka.getLogin(), asuka.getPassword())
+			.resume();
+		NavigationPage asukaNavBar = new NavigationPage(participantBrowser);
+		asukaNavBar
+			.openMyCourses()
+			.openSearch()
+			.extendedSearch(qtiTestTitle)
+			.select(qtiTestTitle)
+			.start();
+		
+		// make the test
+		QTI21Page
+			.getQTI12Page(participantBrowser)
+			.assertOnAssessmentItem()
+			.answerMatch("Eclipse", TrueFalse.right, true)
+			.answerMatch("vim", TrueFalse.wrong, true)
+			.saveAnswer()
+			.assertFeedback("Correct feedback")
+			.nextAnswer()
+			.answerMatch("Java", TrueFalse.right, true)
+			.answerMatch("oriented", TrueFalse.wrong, true)
+			.saveAnswer()
+			.endTest()
+			.assertOnAssessmentResults()
+			.assertOnAssessmentTestScore(7);// 4 points from the first question, 6 from the second
+	}
 
 	/**
 	 * An author make a test with 1 upload and feedbacks.<br>
diff --git a/src/test/java/org/olat/selenium/ImsQTI21InteractionsTest.java b/src/test/java/org/olat/selenium/ImsQTI21InteractionsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..781d4edff6a3977fce2d058b0575f425856f8a86
--- /dev/null
+++ b/src/test/java/org/olat/selenium/ImsQTI21InteractionsTest.java
@@ -0,0 +1,687 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.selenium;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.UUID;
+
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.arquillian.graphene.page.InitialPage;
+import org.jboss.arquillian.graphene.page.Page;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.olat.ims.qti21.QTI21AssessmentResultsOptions;
+import org.olat.selenium.page.LoginPage;
+import org.olat.selenium.page.NavigationPage;
+import org.olat.selenium.page.qti.QTI21Page;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.rest.UserRestClient;
+import org.olat.user.restapi.UserVO;
+import org.openqa.selenium.WebDriver;
+
+
+/**
+ * This suite tests the interactions in runtime and only in runtime. The source used
+ * come from the IMS examples.
+ * 
+ * <ul>
+ *   <li>Hotspot
+ *   <li>Associate
+ *   <li>Graphic associate
+ *   <li>Match
+ *   <li>Graphic Gap Match (with click and drop)
+ *   <li>End interaction with inline and modal feedbacks (classic hint)
+ *   <li>Select point interaction
+ *   <li>Position object interaction
+ *   <li>Order interaction
+ *   <li>Graphic order interaction
+ *   <li>Inline choice
+ *   <li>Slider
+ * </ul>
+ * 
+ * Initial date: 26 janv. 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@RunWith(Arquillian.class)
+public class ImsQTI21InteractionsTest extends Deployments {
+	
+	@Drone
+	private WebDriver browser;
+	@ArquillianResource
+	private URL deploymentUrl;
+	@Page
+	private NavigationPage navBar;
+	
+	/**
+	 * Check if the hotspot interaction send a "correct" feedback.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21HotspotInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Hotspot QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_hotspot.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerHotspot("circle")
+			.saveAnswer()
+			.assertFeedback("Correct!")
+			.endTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentTestScore(1)
+			.assertOnAssessmentTestMaxScore(1);
+	}
+	
+	/**
+	 * Check if the associate interaction return its 4 points.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21AssociateInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Associate QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_associate_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerAssociate("Antonio", 1, true)
+			.answerAssociate("Prospero", 1, false)
+			.answerAssociate("Capulet", 2, true)
+			.answerAssociate("Montague", 2, false)
+			.answerAssociate("Demetrius", 3, true)
+			.answerAssociate("Lysander", 3, false)
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Shakespearian Rivals", 4);
+	}
+	
+	/**
+	 * Check if the graphic associate interaction return its 2 points.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21GraphicAssociateInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Graphic associate QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_graphic_associate_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerGraphicAssociate("B")
+			.answerGraphicAssociate("C")
+			.answerGraphicAssociate("C")
+			.answerGraphicAssociate("D")
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Low-cost Flying", 2);
+	}
+	
+	/**
+	 * Check if the classic match interaction return its 3 points.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21MatchInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Match QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_match_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerMatch("Prospero", "Romeo and Juliet", true)
+			.answerMatch("Capulet", "Romeo and Juliet", true)
+			.answerMatch("Demetrius", "A Midsummer", true)
+			.answerMatch("Lysander", "A Midsummer", true)
+			//ooops
+			.answerMatch("Prospero", "Romeo and Juliet", false)
+			.answerMatch("Prospero", "The Tempest", true)
+			.saveAnswer()
+			.endTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Characters and Plays", 3);
+	}
+	
+	/**
+	 * Check if the order interaction return its 1 point.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21OrderInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Order QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_order_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerOrderDropItem("Jenson")
+			.answerOrderDropItem("Rubens")
+			.answerOrderDropItem("Michael")
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Grand Prix of Bahrain", 1);
+	}
+	
+	/**
+	 * Check if hint with modal and inline feedbacks used
+	 * with choice interaction.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21EndInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "End QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_end_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.hint()
+			.assertFeedbackText("Tony lives in the United Kingdom")
+			.answerSingleChoice("Tony")
+			.saveAnswer()
+			.assertFeedbackText("No, the correct answer is Vicente Fox")
+			.assertFeedbackInline("No, he is the Prime Minister of England.")
+			.assertNoFeedbackText("Tony lives in the United Kingdom")
+			.answerSingleChoice("George")
+			.saveAnswer()
+			.assertFeedbackText("No, the correct answer is Vicente Fox")
+			.assertFeedbackInline("No, he is the President of the USA.")
+			.assertNoFeedbackText("Tony lives in the United Kingdom")
+			.assertNoFeedbackInline("No, he is the Prime Minister of England.")
+			.answerSingleChoice("Vicente")
+			.saveAnswer()
+			.assertFeedbackText("Yes, that is correct")
+			.assertNoFeedbackText("Tony lives in the United Kingdom")
+			.assertNoFeedbackInline("No, he is the Prime Minister of England.")
+			.assertNoFeedbackInline("No, he is the President of the USA.")
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Mexican President", 1);
+	}
+	
+	/**
+	 * Check if hint with modal and inline feedbacks used
+	 * with choice interaction.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21GraphicGapInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Graphic Gap Match QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_graphic_gap_match_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerGraphicGapClick("GLA", "A")
+			.answerGraphicGapClick("EDI", "B")
+			.answerGraphicGapClick("MAN", "C")
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Airport Tags", 3);
+	}
+	
+	/**
+	 * Check if the select point interaction returns 1 point
+	 * if answered correctly.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21SelectPointInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Select point QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_select_point_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerSelectPoint(100, 110)
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Where is Edinburgh", 1);
+	}
+	
+	/**
+	 * Check if the graphic order interaction returns 1 point
+	 * if answered correctly.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21GraphicOrderInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Graphic order QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_graphic_order_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerGraphicOrderById("A")
+			.answerGraphicOrderById("D")
+			.answerGraphicOrderById("C")
+			.answerGraphicOrderById("B")
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Flying Home", 1);
+	}
+	
+	/**
+	 * Check if the position object interaction returns 3 points
+	 * if answered correctly.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21PositionObjectInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Position object QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_position_object_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerPositionObject(0, 118, 184)
+			.answerPositionObject(1, 150, 235)
+			.answerPositionObject(2, 96, 114)
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Airport Locations", 3);
+	}
+	
+	/**
+	 * Check if the position object interaction returns 3 points
+	 * if answered correctly.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21InlineChoiceInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Inline choice QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_inline_choice_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerInlineChoice("Y")
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Richard III", 1);
+	}
+	
+	/**
+	 * Check if the slider interaction returns 1 point
+	 * if answered correctly.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21SliderInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Slider QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_slider_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerVerticalSlider(16)
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Jedi Knights", 1);
+	}
+	
+	/**
+	 * Check if the gap match returns 3 points
+	 * if answered correctly.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21GapMatchInteraction(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Gap match QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_gap_match_ims.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		// to the test and spot it
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerGapMatch(1, "winter", true)
+			.answerGapMatch(2, "summer", true)
+			.saveAnswer()
+			.endTest()
+			.closeTest();
+		//check the results
+		qtiPage
+			.assertOnAssessmentResults()
+			.assertOnAssessmentItemScore("Richard III", 3);
+	}
+
+}
diff --git a/src/test/java/org/olat/selenium/ImsQTI21Test.java b/src/test/java/org/olat/selenium/ImsQTI21Test.java
index 35ad90f665e1c9356886994c1ddbb01f97b35b2d..62cfbc4a287c5ae3fcee7be7f71c4bc6262559d3 100644
--- a/src/test/java/org/olat/selenium/ImsQTI21Test.java
+++ b/src/test/java/org/olat/selenium/ImsQTI21Test.java
@@ -674,50 +674,6 @@ public class ImsQTI21Test extends Deployments {
 			.assertOnCourseAssessmentTestScore(1)
 			.assertOnAssessmentResults();
 	}
-	
-	/**
-	 * Check if the hotspot interaction send a "correct" feedback.
-	 * 
-	 * @param authorLoginPage
-	 * @throws IOException
-	 * @throws URISyntaxException
-	 */
-	@Test
-	@RunAsClient
-	public void qti21GraphicInteraction(@InitialPage LoginPage authorLoginPage)
-	throws IOException, URISyntaxException {
-		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
-		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
-		
-		//upload a test
-		String qtiTestTitle = "Simple QTI 2.1 " + UUID.randomUUID();
-		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/simple_QTI_21_hotspot.zip");
-		File qtiTestFile = new File(qtiTestUrl.toURI());
-		navBar
-			.openAuthoringEnvironment()
-			.uploadResource(qtiTestTitle, qtiTestFile)
-			.clickToolbarRootCrumb();
-		
-		QTI21Page qtiPage = QTI21Page
-				.getQTI12Page(browser);
-		qtiPage
-			.options()
-			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
-			.save();
-		// to the test and spot it
-		qtiPage
-			.clickToolbarBack()
-			.assertOnAssessmentItem()
-			.answerHotspot("circle")
-			.saveAnswer()
-			.assertFeedback("Correct!")
-			.endTest();
-		//check the results
-		qtiPage
-			.assertOnAssessmentResults()
-			.assertOnAssessmentTestScore(1)
-			.assertOnAssessmentTestMaxScore(1);
-	}
 
 	/**
 	 * Upload a test in QTI 2.1 format, create a course, bind
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java b/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
index 4a84cb36731510d90ec9adb679fc1a15786365d2..3e3f3a096b93d8d4f30e7b4e5fb40e8731f0704b 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21EditorPage.java
@@ -122,6 +122,11 @@ public class QTI21EditorPage {
 		return new QTI21MatchEditorPage(browser);
 	}
 	
+	public QTI21MatchEditorPage addMatchTrueFalse() {
+		addQuestion(QTI21QuestionType.matchtruefalse);
+		return new QTI21MatchEditorPage(browser);
+	}
+	
 	public QTI21LobEditorPage addUpload() {
 		addQuestion(QTI21QuestionType.upload);
 		return new QTI21LobEditorPage(browser);
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
index e0ec4b53898de7b3cb520b418a92896a04557b76..08e92e1e004c8bb8100484677097b23f2084086a 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
@@ -27,9 +27,11 @@ import org.olat.selenium.page.NavigationPage;
 import org.olat.selenium.page.graphene.OOGraphene;
 import org.olat.selenium.page.repository.RepositoryAccessPage;
 import org.openqa.selenium.By;
+import org.openqa.selenium.Dimension;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.ui.Select;
 
 /**
  * 
@@ -125,6 +127,20 @@ public class QTI21Page {
 		return this;
 	}
 	
+	/**
+	 * Select the key of the inline choice interaction.
+	 * 
+	 * @param key The key to select
+	 * @return Itself
+	 */
+	public QTI21Page answerInlineChoice(String key) {
+		By inlineBy = By.xpath("//span[@class='inlineChoiceInteraction']/select");
+		OOGraphene.waitElement(inlineBy, browser);
+		WebElement inlineEl = browser.findElement(inlineBy);
+		new Select(inlineEl).selectByValue(key);
+		return this;
+	}
+	
 	public QTI21Page answerHotspot(String shape) {
 		OOGraphene.waitElement(By.className("hotspotInteraction"), browser);
 		By areaBy = By.xpath("//div[contains(@class,'hotspotInteraction')]//map/area[@shape='" + shape + "']");
@@ -134,6 +150,20 @@ public class QTI21Page {
 		return this;
 	}
 	
+	/**
+	 * Select the area with the specified data-qti-id.
+	 * @param id The id save in data-qti-id
+	 * @return Itself
+	 */
+	public QTI21Page answerGraphicOrderById(String id) {
+		OOGraphene.waitElement(By.className("graphicOrderInteraction"), browser);
+		By areaBy = By.xpath("//div[contains(@class,'graphicOrderInteraction')]//map/area[@data-qti-id='" + id + "']");
+		List<WebElement> elements = browser.findElements(areaBy);
+		Assert.assertEquals("Hotspot with data-qti-id " + id, 1, elements.size()); 
+		elements.get(0).click();
+		return this;
+	}
+	
 	public QTI21Page answerHottext(int index) {
 		OOGraphene.waitElement(By.className("hottextInteraction"), browser);
 		By checkBy = By.xpath("//div[contains(@class,'hottextInteraction')]//p/span[@class='hottext'][" + index + "]/input[@type='checkbox']");
@@ -196,6 +226,14 @@ public class QTI21Page {
 		return this;
 	}
 	
+	/**
+	 * The method check text within a &lt;p&gt; element.
+	 * 
+	 * @param source Text in the source
+	 * @param target Text in the target
+	 * @param match Select or deselect
+	 * @return Itself
+	 */
 	public QTI21Page answerMatch(String source, String target, boolean match) {
 		By matchBy = By.xpath("//div[contains(@class,'matchInteraction')]/table//tr[th/p[contains(text(),'" + source + "')]]/td[count(//div[contains(@class,'matchInteraction')]/table//tr/th[p[contains(text(),'" + target + "')]]/preceding-sibling::th)]/input");
 		WebElement matchEl = browser.findElement(matchBy);
@@ -203,6 +241,13 @@ public class QTI21Page {
 		return this;
 	}
 	
+	public QTI21Page answerMatch(String source, TrueFalse target, boolean match) {
+		By matchBy = By.xpath("//div[contains(@class,'matchInteraction')]/table//tr[td/p[contains(text(),'" + source + "')]]/td[" + (target.ordinal() + 1) + "]/input");
+		WebElement matchEl = browser.findElement(matchBy);
+		OOGraphene.check(matchEl, match);
+		return this;
+	}
+	
 	public QTI21Page answerMatchDropSourceToTarget(String source, String target) {
 		By sourceBy = By.xpath("//li[contains(@class,'o_match_dnd_source')]/p[contains(text(),'" + source + "')]");
 		OOGraphene.waitElement(sourceBy, 5, browser);
@@ -245,6 +290,151 @@ public class QTI21Page {
 		return this;
 	}
 	
+	public QTI21Page answerAssociate(String source, int index, boolean left) {
+		By itemBy = By.xpath("//div[contains(@class,'o_associate_items')]/div[contains(@class,'o_associate_item')][contains(text(),'" + source + "')]");
+		WebElement itemEl = browser.findElement(itemBy);
+		By targetBy = By.xpath("//div[@class='association'][" + index + "]/div[contains(@class,'association_box')][contains(@class,'" + (left ? "left" : "right") + "')]");
+		WebElement targetEl = browser.findElement(targetBy);
+		new Actions(browser)
+			.moveToElement(itemEl, 10, 10)
+			.clickAndHold()
+			.moveToElement(targetEl, 10, 10)
+			.release()
+			.build()
+			.perform();
+		return this;
+	}
+	
+	public QTI21Page answerGraphicAssociate(String id) {
+		OOGraphene.waitElement(By.className("graphicAssociateInteraction"), browser);
+		By areaBy = By.xpath("//div[contains(@class,'graphicAssociateInteraction')]//map/area[@data-qti-id='" + id + "']");
+		List<WebElement> elements = browser.findElements(areaBy);
+		Assert.assertEquals("Area by " + id, 1, elements.size()); 
+		elements.get(0).click();
+		return this;
+	}
+	
+	public QTI21Page answerOrderDropItem(String source) {
+		By sourceBy = By.xpath("//li[contains(@class,'o_assessmentitem_order_item')][text()[contains(.,'" + source + "')]]");
+		OOGraphene.waitElement(sourceBy, 5, browser);
+		WebElement sourceEl = browser.findElement(sourceBy);
+		By targetBy = By.xpath("//div[@class='orderInteraction']//div[contains(@class,'target')]/ul");
+		WebElement targetEl = browser.findElement(targetBy);
+		new Actions(browser)
+			.moveToElement(sourceEl, 30, 30)
+			.clickAndHold()
+			.moveToElement(targetEl, 30, 30)
+			.release()
+			.build()
+			.perform();
+
+		By sourceDroppedBy = By.xpath("//div[@class='orderInteraction']//div[contains(@class,'target')]/ul/li[text()[contains(.,'" + source + "')]]");
+		OOGraphene.waitElement(sourceDroppedBy, 5, browser);
+		return this;
+	}
+	
+	/**
+	 * Select the gap match
+	 * 
+	 * @param source The row to check
+	 * @param target Text in the target
+	 * @param match Select or deselect
+	 * @return Itself
+	 */
+	public QTI21Page answerGapMatch(int row, String target, boolean match) {
+		By matchBy = By.xpath("//div[contains(@class,'gapMatchInteraction')]/table//tr[th[contains(text(),'" + row + "')]]/td[count(//div[contains(@class,'gapMatchInteraction')]/table//tr/th[text()[contains(.,'" + target + "')]]/preceding-sibling::th)]/input");
+		WebElement matchEl = browser.findElement(matchBy);
+		OOGraphene.check(matchEl, match);
+		return this;
+	}
+	
+	/**
+	 * Use the click and drop.
+	 * 
+	 * @param item The identifier of the item
+	 * @param gap The identifier of the gap
+	 * @return Itself
+	 */
+	public QTI21Page answerGraphicGapClick(String item, String gap) {
+		By sourceBy = By.xpath("//div[contains(@class,'gap_container')]/div[contains(@class,'o_gap_item')][@data-qti-id='" + item + "']");
+		OOGraphene.waitElement(sourceBy, 5, browser);
+		WebElement sourceEl = browser.findElement(sourceBy);
+		sourceEl.click();
+		By targetBy = By.xpath("//div[@class='graphicGapMatchInteraction']//map/area[@data-qti-id='" + gap + "']");
+		WebElement targetEl = browser.findElement(targetBy);
+		targetEl.click();
+		return this;
+	}
+	
+	/**
+	 * Select the point based on coordinates.
+	 * 
+	 * @param x The x coordinate
+	 * @param y The y coordinate
+	 * @return Itself
+	 */
+	public QTI21Page answerSelectPoint(int x, int y) {
+		By canvasBy = By.xpath("//div[contains(@class,'selectPointInteraction')]/div/canvas");
+		WebElement canvasEl = browser.findElement(canvasBy);
+		new Actions(browser)
+			.moveToElement(canvasEl, x, y)
+			.click()
+			.build()
+			.perform();
+		return this;
+	}
+	
+	/**
+	 * Select the object by its index (start with 0) and
+	 * move it on the image and the specified coodinates.
+	 * 
+	 * @param index The index of the object
+	 * @param x The x target coordinate
+	 * @param y The y target coordinate
+	 * @return Itself
+	 */
+	public QTI21Page answerPositionObject(int index, int x, int y) {
+		By itemBy = By.xpath("//div[contains(@class,'positionObjectStage')]//div[@id='object-item-" + index + "']");
+		OOGraphene.waitElement(itemBy, browser);
+		WebElement itemEl = browser.findElement(itemBy);
+		By targetBy = By.xpath("//div[@class='positionObjectStage']//img[contains(@id,'qtiworks_id_container_')]");
+		WebElement targetEl = browser.findElement(targetBy);
+		new Actions(browser)
+			.moveToElement(itemEl, 5, 5)
+			.clickAndHold()
+			.moveToElement(targetEl, x, y)
+			.release()
+			.build()
+			.perform();
+		return this;
+	}
+	
+	/**
+	 * Select the point based on coordinates.
+	 * 
+	 * @param x The x coordinate
+	 * @return Itself
+	 */
+	public QTI21Page answerVerticalSlider(int val) {
+		By sliderBy = By.xpath("//div[contains(@class,'sliderInteraction')]/div[contains(@class,'sliderVertical')]/div[contains(@class,'sliderWidget')]");
+		OOGraphene.waitElement(sliderBy, browser);
+		WebElement sliderEl = browser.findElement(sliderBy);
+		Dimension size = sliderEl.getSize();
+		float height = (size.getHeight() / 100f) * val;
+		float scaledY = size.getHeight() - height;
+		
+		new Actions(browser)
+			.moveToElement(sliderEl, 5, Math.round(scaledY))
+			.click()
+			.build()
+			.perform();
+		
+		
+		By valueBy = By.xpath("//div[contains(@class,'sliderInteraction')]/div[contains(@class,'sliderVertical')]/div[contains(@class,'sliderValue')]/span[text()='" + val + "']");
+		OOGraphene.waitElement(valueBy, browser);
+		return this;
+	}
+	
 	public QTI21Page answerUpload(File file) {
 		By inputBy = By.cssSelector(".uploadInteraction input[type='file']");
 		OOGraphene.uploadFile(inputBy, file, browser);
@@ -313,12 +503,61 @@ public class QTI21Page {
 		return this;
 	}
 	
+	/**
+	 * Check if the feedback with the specified content is visible.
+	 * 
+	 * @param text Text of the feedback.
+	 * @return Itself
+	 */
+	public QTI21Page assertFeedbackText(String text) {
+		By feedbackBy = By.xpath("//div[contains(@class,'modalFeedback')][text()[contains(normalize-space(.),'" + text + "')]]");
+		OOGraphene.waitElement(feedbackBy, 5, browser);
+		return this;
+	}
+	
+	/**
+	 * Check if an inline feedback with the specified text
+	 * is visible.
+	 * 
+	 * @param text The text of the inline feedback
+	 * @return Itself
+	 */
+	public QTI21Page assertFeedbackInline(String text) {
+		By feedbackBy = By.xpath("//span[contains(@class,'feedbackInline')][text()[contains(normalize-space(.),'" + text + "')]]");
+		OOGraphene.waitElement(feedbackBy, 5, browser);
+		return this;
+	}
+	
+	/**
+	 * Check that no inline feedback with the specified text
+	 * is visible.
+	 * 
+	 * @param text The text of the inline feedback
+	 * @return Itself
+	 */
+	public QTI21Page assertNoFeedbackInline(String text) {
+		By feedbackBy = By.xpath("//span[contains(@class,'feedbackInline')][text()[contains(normalize-space(.),'" + text + "')]]");
+		OOGraphene.waitElementDisappears(feedbackBy, 5, browser);
+		return this;
+	}
+	
 	public QTI21Page assertNoFeedback(String title) {
 		By feedbackBy = By.xpath("//div[contains(@class,'modalFeedback')]/h4[contains(text(),'" + title + "')]");
 		OOGraphene.waitElementDisappears(feedbackBy, 5, browser);
 		return this;
 	}
 	
+	/**
+	 * 
+	 * @param text The text of the feedback
+	 * @return Itself
+	 */
+	public QTI21Page assertNoFeedbackText(String text) {
+		By feedbackBy = By.xpath("//div[contains(@class,'modalFeedback')][text()[contains(normalize-space(.),'\" + text + \"')]]");
+		OOGraphene.waitElementDisappears(feedbackBy, 5, browser);
+		return this;
+	}
+	
 	/**
 	 * Check that there are no feedbacks visible.
 	 * 
@@ -448,6 +687,12 @@ public class QTI21Page {
 		return this;
 	}
 	
+	public QTI21Page assertOnAssessmentItemScore(String title, int score) {
+		By resultsBy = By.xpath("//div[contains(@class,'o_qti_item')][div/h4[text()[contains(.,'" + title + "')]]]//tr[contains(@class,'o_sel_assessmentitem_score')]//span[@class='o_sel_assessmentitem_score'][contains(text(),'" + score + "')]");
+		OOGraphene.waitElement(resultsBy, 5, browser);
+		return this;
+	}
+	
 	public QTI21Page assertOnAssessmentTestScore(String score) {
 		By resultsBy = By.xpath("//div[contains(@class,'o_sel_results_details')]//tr[contains(@class,'o_sel_assessmenttest_scores')]/td/div/span[contains(@class,'o_sel_assessmenttest_score')][contains(text(),'" + score + "')]");
 		OOGraphene.waitElement(resultsBy, 5, browser);
@@ -606,4 +851,10 @@ public class QTI21Page {
 		OOGraphene.waitBusy(browser);
 		return QTI21Page.getQTI12Page(browser);
 	}
+	
+	public enum TrueFalse {
+		unanswered,
+		right,
+		wrong
+	}
 }
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 891a3297bf51b3c2ed56146fa71d2be5537fa63f..bf0a00cfc17d8624946e43395e4bc9b4575d4e40 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -245,6 +245,7 @@ import org.junit.runners.Suite;
 	org.olat.ims.qti21.model.xml.OnyxToQtiWorksAssessementTestsTest.class,
 	org.olat.ims.qti21.model.xml.OpenOLATAssessementItemsTest.class,
 	org.olat.ims.qti21.model.xml.QTI21ExplorerHandlerTest.class,
+	org.olat.ims.qti21.ui.components.AssessmentRenderFunctionsTest.class,
 	org.olat.ims.lti.LTIManagerTest.class,
 	org.olat.modules.qpool.manager.MetadataConverterHelperTest.class,
 	org.olat.modules.qpool.manager.QuestionDAOTest.class,
diff --git a/src/test/java/org/olat/test/ArquillianDeployments.java b/src/test/java/org/olat/test/ArquillianDeployments.java
index 0f68293ddca31b06aae7268925616354f1b63b3f..3d7e841df87086bf5b58daa175e08f58199f83f1 100644
--- a/src/test/java/org/olat/test/ArquillianDeployments.java
+++ b/src/test/java/org/olat/test/ArquillianDeployments.java
@@ -47,10 +47,10 @@ public class ArquillianDeployments {
 	public static final String WEBINF    = "src/main/webapp/WEB-INF";
 	public static final String WEBINF_TOMCAT = "src/main/webapp-tomcat/WEB-INF";
 	public static final String TEST_RSRC = "src/test/resources";
-	public static final String LIB_DIR   = "target/openolat-lms-12.3-SNAPSHOT/WEB-INF/lib";
+	public static final String LIB_DIR   = "target/openolat-lms-12.4-SNAPSHOT/WEB-INF/lib";
 
 	public static WebArchive createDeployment() {
-		return createDeployment("openolat.war", new HashMap<String,String>());
+		return createDeployment("openolat.war", new HashMap<>());
 	}
 	
 	public static WebArchive createDeployment(Map<String,String> overrideProperties) {
diff --git a/src/test/java/org/olat/test/file_resources/qti21/import_qti21_excel_match.txt b/src/test/java/org/olat/test/file_resources/qti21/import_qti21_excel_match.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d54fbf1f6f2c46c4a822f71bfee226a7e26b352a
--- /dev/null
+++ b/src/test/java/org/olat/test/file_resources/qti21/import_qti21_excel_match.txt
@@ -0,0 +1,29 @@
+Typ	MATRIX		
+Title	Hauptstädte Europas		
+Question	Hauptstädte Europas	
+Feedback correct answer	Bravo! Die Antwort ich absolut korrekt weil ban wirklich verbannen heisst.		
+Points	3		
+	Deutschland	Frankreich	Schweiz
+Berlin	1	0	0
+Bern	0	0	1
+Paris	0	1	0
+			
+			
+Typ	Drag&drop		
+Title	Hauptstädte Afrika		
+Question	Hauptstädte Afrika		
+Points	3		
+	Algerien	Kenia	Namibia
+Nairobi	0	1	0
+Windhoek	0	0	1
+Algier	1	0	0
+			
+			
+Typ	Truefalse		
+Title	Hauptstädte Europa		
+Question	Hauptstädte Europa		
+Points	3		
+	Unanswered	Right	Wrong
+Paris ist in Frankreich	0	1	0
+Bern ist in Schweiz	0	1	0
+Stockholm ist in Danemark	0	0	1
\ No newline at end of file
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_associate_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_associate_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..9b934b71c3348f76ce414d70d79a12b9351a8701
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_associate_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_end_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_end_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..734c7968e5c35530872d5bcefbcb9d2b1436040f
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_end_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_gap_match_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_gap_match_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..9054f45e1c0ad30c32989d55e8cf996d7404e888
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_gap_match_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_associate_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_associate_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..b1a9e390d0d81196767f7c6e9c55ff25ecd17843
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_associate_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_gap_match_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_gap_match_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..6658b1444f31f894869792333accde652bfa6e13
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_gap_match_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_order_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_order_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..c6295034b81d860a7ca91e82d09162b4f116b184
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_graphic_order_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_inline_choice_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_inline_choice_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..bc8ac24ad6b99d1a0f83c1df9e93b46cce59617f
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_inline_choice_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_match_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_match_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..78a2c3679a8e4469f6dc5b5ea29342b1d8752e16
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_match_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_order_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_order_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..17feeda76f0d0c0e3b916432d6633a3cdaed2f6b
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_order_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_position_object_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_position_object_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..a4b7033e23ab14dd360fdf26656d25fad4b198db
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_position_object_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_select_point_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_select_point_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..61be744db788c68d9df72b535acefc60ba03ddc2
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_select_point_ims.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_slider_ims.zip b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_slider_ims.zip
new file mode 100644
index 0000000000000000000000000000000000000000..5cb3f2b418ee8d38f31efea77864950ff644b1a2
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/simple_QTI_21_slider_ims.zip differ