diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java
index 052f9bcfdd20648f6754fa0c47764106f004df83..5667bba3f965d1ac26e1c5f12ccdc597df77d41d 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java
@@ -636,13 +636,16 @@ public class Form {
 			 * check if this is the FormItem to be dispatched
 			 */
 			Component tmp = fi.getComponent();
-			String tmpD = FormBaseComponentIdProvider.DISPPREFIX + tmp.getDispatchID();
-
-			if (!foundDispatchItem && tmpD.equals(dispatchId)) {
-				dispatchFormItem = fi;
-				foundDispatchItem = true;
+			if(tmp != null) {
+				String tmpD = FormBaseComponentIdProvider.DISPPREFIX.concat(tmp.getDispatchID());
+				if (!foundDispatchItem && tmpD.equals(dispatchId)) {
+					dispatchFormItem = fi;
+					foundDispatchItem = true;
+				}
+			} else {
+				log.warn("Null component: {}", fi);
 			}
-			
+
 			/*
 			 * let the form item evaluate the form request, e.g. get out its data
 			 */
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
index 3c9c8d470c27c0d752d81a109a6f9ced6a3f3087..14ea534e3b1e0dcb2837498a44fa6a66fbe97aa3 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
@@ -1923,11 +1923,17 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		rootFormAvailable(extendedSearchButton);
 		rootFormAvailable(customTypeButton);
 		rootFormAvailable(classicTypeButton);
+		if(components != null) {
+			for(FormItem item:components.values()) {
+				rootFormAvailable(item);
+			}
+		}
 	}
 	
 	private final void rootFormAvailable(FormItem item) {
-		if(item != null && item.getRootForm() != getRootForm())
+		if(item != null && item.getRootForm() != getRootForm()) {
 			item.setRootForm(getRootForm());
+		}
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/core/util/FileUtils.java b/src/main/java/org/olat/core/util/FileUtils.java
index 3923a777b3be96b891b450982bfd8cdd0a5fc2e0..c2f8cffff3a051d7d6ad4b6854c9bed89920f061 100644
--- a/src/main/java/org/olat/core/util/FileUtils.java
+++ b/src/main/java/org/olat/core/util/FileUtils.java
@@ -488,7 +488,7 @@ public class FileUtils {
 				deleteFile(sourceFile);
 			}
 		} catch (IOException e) {
-			log.error("Could not copy file::" + sourceFile.getAbsolutePath() + " to file::" + targetFile.getAbsolutePath(), e);
+			log.error("Could not copy file::{} to file::{}", sourceFile.getAbsolutePath(), targetFile.getAbsolutePath(), e);
 			return false;
 		}
 		return true;
diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties
index cc5e89bae060cc7349bbfff8394fbb008ffd015f..a9b49dc9f7bbc9b9b22ed43f2489fdf934c9e119 100644
--- a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_de.properties
@@ -59,7 +59,7 @@ form.individual.assessment.docs=$org.olat.course.nodes.ms\:form.individual.asses
 form.error.date=Es muss ein Datum angegeben werden.
 form.error.scoreOutOfRange=$org.olat.course.assessment\:form.error.scoreOutOfRange
 form.error.wrongFloat=$org.olat.course.nodes.ms\:form.error.wrongFloat
-fully.assessed.trigger.status.done=Status durch Betreuer auf "abgeschlosen" gesetzt.
+fully.assessed.trigger.status.done=Status durch Betreuer auf "abgeschlossen" gesetzt.
 ignore.in.course.assessment=$org.olat.course.nodes.ms\:ignore.in.course.assessment
 info.title=$org.olat.course.nodes.ms\:info.title
 label=Beschriftung
diff --git a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java
index ab831cf0cc134a90b7dee70f1508dfa6dc33f30e..067a62afb4eee60071decf4e87f11b2c6153bc2e 100644
--- a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java
+++ b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java
@@ -35,6 +35,8 @@ import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
+import javax.persistence.CacheRetrieveMode;
+import javax.persistence.CacheStoreMode;
 import javax.persistence.LockModeType;
 import javax.persistence.Query;
 
@@ -1038,11 +1040,12 @@ public class GTAManagerImpl implements GTAManager, DeletableGroupData {
 
 		AssignmentResponse response;
 		if(currentTask == null || !StringHelper.containsNonWhitespace(currentTask.getTaskName())) {
-			TaskList reloadedTasks = loadForUpdate(tasks);
-
 			File tasksFolder = getTasksDirectory(courseEnv, cNode);
 			String[] taskFiles = tasksFolder.list(SystemFilenameFilter.FILES_ONLY);
+			
+			TaskList reloadedTasks = loadForUpdate(tasks);
 			List<String> assignedFilenames = getAssignedTasks(reloadedTasks);
+			assignedFilenames.retainAll(List.of(taskFiles));
 			
 			String taskName;
 			if(GTACourseNode.GTASK_SAMPLING_UNIQUE.equals(cNode.getModuleConfiguration().get(GTACourseNode.GTASK_SAMPLING))) {
@@ -1156,10 +1159,15 @@ public class GTAManagerImpl implements GTAManager, DeletableGroupData {
 	
 	@Override
 	public List<String> getAssignedTasks(TaskList taskList) {
-		return dbInstance.getCurrentEntityManager()
+		List<String> taskNames = dbInstance.getCurrentEntityManager()
 			.createNamedQuery("tasksByTaskList", String.class)
 			.setParameter("taskListKey", taskList.getKey())
+			.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS)
+			.setHint("javax.persistence.cache.storeMode", CacheStoreMode.BYPASS)
 			.getResultList();
+		return taskNames.stream()
+			.filter(name -> (StringHelper.containsNonWhitespace(name)))
+			.collect(Collectors.toList());
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/iq/QTI21EditLayoutForm.java b/src/main/java/org/olat/course/nodes/iq/QTI21EditLayoutForm.java
index e3ac1ffc94ef0670ae1fcfc1bcc24ef3b0496848..17552c5666d29bbfd7176f4b35c7b5665c0144ef 100644
--- a/src/main/java/org/olat/course/nodes/iq/QTI21EditLayoutForm.java
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21EditLayoutForm.java
@@ -244,7 +244,7 @@ public class QTI21EditLayoutForm extends FormBasicController {
 			displayScoreProgressEl.select(onKeys[0], true);
 		}
 		
-		boolean questionMaxScore = configRef ? deliveryOptions.isDisplayScoreProgress() :
+		boolean questionMaxScore = configRef ? deliveryOptions.isDisplayMaxScoreItem() :
 			modConfig.getBooleanSafe(IQEditController.CONFIG_KEY_QUESTION_MAX_SCORE, deliveryOptions.isDisplayMaxScoreItem());
 		displayMaxScoreItemEl = uifactory.addCheckboxesHorizontal("scoreMaxItem", "qti.form.max.score.item", formLayout, onKeys, onValues);
 		displayMaxScoreItemEl.setEnabled(!configRef);
diff --git a/src/main/java/org/olat/course/nodes/survey/SurveyManager.java b/src/main/java/org/olat/course/nodes/survey/SurveyManager.java
index ff6660e0534bd9c9d435cc7e01df6c36126ebc87..14de2bcbad13f875e287a1121619d78b04772afd 100644
--- a/src/main/java/org/olat/course/nodes/survey/SurveyManager.java
+++ b/src/main/java/org/olat/course/nodes/survey/SurveyManager.java
@@ -30,6 +30,7 @@ import org.olat.modules.forms.EvaluationFormParticipation;
 import org.olat.modules.forms.EvaluationFormSession;
 import org.olat.modules.forms.EvaluationFormSurvey;
 import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
+import org.olat.modules.forms.SessionFilter;
 import org.olat.modules.forms.model.xml.Form;
 import org.olat.repository.RepositoryEntry;
 
@@ -69,8 +70,8 @@ public interface SurveyManager {
 
 	public void onExecutionFinished(SurveyCourseNode courseNode, UserCourseEnvironment userCourseEnv);
 
-	public long getCountOfSessions(EvaluationFormSurvey survey);
-
+	public Long getSessionsCount(SessionFilter filter);
+	
 	public void deleteAllData(EvaluationFormSurvey survey, SurveyCourseNode courseNode, UserCourseEnvironment userCourseEnv);
 
 }
diff --git a/src/main/java/org/olat/course/nodes/survey/manager/SurveyManagerImpl.java b/src/main/java/org/olat/course/nodes/survey/manager/SurveyManagerImpl.java
index 645000326f78403449fd15555f977bcb0fa32537..fe79d2fd4b71cb5d2340193bcfe30c955bedadfc 100644
--- a/src/main/java/org/olat/course/nodes/survey/manager/SurveyManagerImpl.java
+++ b/src/main/java/org/olat/course/nodes/survey/manager/SurveyManagerImpl.java
@@ -43,6 +43,7 @@ import org.olat.modules.forms.EvaluationFormParticipationIdentifier;
 import org.olat.modules.forms.EvaluationFormSession;
 import org.olat.modules.forms.EvaluationFormSurvey;
 import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
+import org.olat.modules.forms.SessionFilter;
 import org.olat.modules.forms.model.xml.Form;
 import org.olat.repository.RepositoryEntry;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -176,8 +177,8 @@ public class SurveyManagerImpl implements SurveyManager {
 	}
 
 	@Override
-	public long getCountOfSessions(EvaluationFormSurvey survey) {
-		return evaluationFormManager.getCountOfSessions(survey);
+	public Long getSessionsCount(SessionFilter filter) {
+		return evaluationFormManager.loadSessionsCount(filter);
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/SurveyDeleteDataConfirmationController.java b/src/main/java/org/olat/course/nodes/survey/ui/SurveyDeleteDataConfirmationController.java
index d2dff8ce746013d536553fee9167698896d0e0db..557a58cd01fa72b41377682316cf5e5ba6984171 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/SurveyDeleteDataConfirmationController.java
+++ b/src/main/java/org/olat/course/nodes/survey/ui/SurveyDeleteDataConfirmationController.java
@@ -40,11 +40,13 @@ public class SurveyDeleteDataConfirmationController extends FormBasicController
 
 	private MultipleSelectionElement confirmationEl;
 	
-	private final long numberOfSessions;
+	private final Long allSessions;
+	private final Long doneSessions;
 	
-	public SurveyDeleteDataConfirmationController(UserRequest ureq, WindowControl wControl, long numberOfSessions) {
+	public SurveyDeleteDataConfirmationController(UserRequest ureq, WindowControl wControl, Long allSessions, Long doneSessions) {
 		super(ureq, wControl, "delete_data_confirmation");
-		this.numberOfSessions = numberOfSessions;
+		this.allSessions = allSessions;
+		this.doneSessions = doneSessions;
 		initForm(ureq);
 	}
 
@@ -54,7 +56,8 @@ public class SurveyDeleteDataConfirmationController extends FormBasicController
 		formLayout.add("confirm", confirmCont);
 		confirmCont.setRootForm(mainForm);
 		
-		flc.contextPut("numSessions", String.valueOf(numberOfSessions));
+		String message = translate("run.command.delete.data.all.message", new String[] {String.valueOf(allSessions), String.valueOf(doneSessions)} );
+		flc.contextPut("message", message);
 		
 		String[] conformationValues = new String[] { translate("run.command.delete.data.all.check") };
 		confirmationEl = uifactory.addCheckboxesHorizontal("confirm.delete", "", confirmCont, confirmationKeys, conformationValues);
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/SurveyRunController.java b/src/main/java/org/olat/course/nodes/survey/ui/SurveyRunController.java
index 4b3efbce6ae261d56a554392072cdb314ab6bafa..4c6b667705b70c8a737f85dc4be592243a13caa8 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/SurveyRunController.java
+++ b/src/main/java/org/olat/course/nodes/survey/ui/SurveyRunController.java
@@ -42,6 +42,7 @@ import org.olat.modules.forms.EvaluationFormParticipation;
 import org.olat.modules.forms.EvaluationFormSession;
 import org.olat.modules.forms.EvaluationFormSurvey;
 import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
+import org.olat.modules.forms.SessionFilterFactory;
 import org.olat.modules.forms.ui.EvaluationFormExecutionController;
 import org.olat.modules.forms.ui.ProgressEvent;
 import org.olat.repository.RepositoryEntry;
@@ -180,8 +181,9 @@ public class SurveyRunController extends BasicController {
 	}
 
 	private void doConfirmDeleteAllData(UserRequest ureq) {
-		long countOfSessions = surveyManager.getCountOfSessions(survey);
-		deleteDataConfirmationCtrl = new SurveyDeleteDataConfirmationController(ureq, getWindowControl(), countOfSessions);
+		Long allSessions = surveyManager.getSessionsCount(SessionFilterFactory.create(survey));
+		Long doneSessions = surveyManager.getSessionsCount(SessionFilterFactory.createSelectDone(survey));
+		deleteDataConfirmationCtrl = new SurveyDeleteDataConfirmationController(ureq, getWindowControl(), allSessions, doneSessions);
 		listenTo(deleteDataConfirmationCtrl);
 		cmc = new CloseableModalController(getWindowControl(), translate("close"),
 				deleteDataConfirmationCtrl.getInitialComponent(), true, translate("run.command.delete.data.all.title"), true);
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/_content/delete_data_confirmation.html b/src/main/java/org/olat/course/nodes/survey/ui/_content/delete_data_confirmation.html
index 124c56a8b3a0a6d6bcb6ae8cc36dbef083b7ddfb..47f005503974c3a20fb58b2cbf9a14b3665b52f6 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/_content/delete_data_confirmation.html
+++ b/src/main/java/org/olat/course/nodes/survey/ui/_content/delete_data_confirmation.html
@@ -1,4 +1,4 @@
 <div class="o_error">
-	$r.translate("run.command.delete.data.all.message", $numSessions)
+	$message
 </div>
 $r.render("confirm")
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_de.properties
index 56d4753a81a90b5ee40a1fd20ba7f389d0309749..965a3461de6648bbedea6bc104c5e343ed6644a8 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_de.properties
@@ -31,7 +31,7 @@ run.command.delete.data.all=Umfrage zur\u00fcksetzen
 run.command.delete.data.all.confirmation.error=Best\u00e4tigen Sie bitte das L\u00f6schen.
 run.command.delete.data.all.button=L\u00f6schen
 run.command.delete.data.all.check=Alle Antworten l\u00f6schen
-run.command.delete.data.all.message=Wollen Sie wirklich alle Antworten l\u00f6schen? Es haben bereits {0} Benutzer/innen an dieser Umfrage teilgenommen. Die Antworten k\u00f6nnen nicht wieder hergestellt werden!
+run.command.delete.data.all.message=Wollen Sie wirklich alle Antworten l\u00f6schen? Die Umfrage wurde bereits von {0} Benutzer/innen gestartet und von {1} Benutzer/innen abgeschlossen. Die Antworten k\u00f6nnen nicht wieder hergestellt werden!
 run.command.delete.data.all.title=Alle Antworten l\u00f6schen
 run.participation.done.message=Sie haben den Fragebogen bereits ausgef\u00fcllt. Vielen Dank f\u00fcr Ihre Teilnahme.
 run.participation.done.title=Fragebogen ausgef\u00fcllt
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_en.properties
index 56e0442448ccbd3b5f58881f173a8ecc6c24c07d..61967e710cfd6ee4f9118d6da65afce1b5041734 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_en.properties
@@ -31,7 +31,7 @@ run.command.delete.data.all=Reset survey
 run.command.delete.data.all.confirmation.error=Please confirm the deletion of the responses.
 run.command.delete.data.all.button=Delete
 run.command.delete.data.all.check=Delete all responses
-run.command.delete.data.all.message=Do you really want to delete all responses. Already {0} users participated in this survey. It is not possible to restore the responses.
+run.command.delete.data.all.message=Do you really want to delete all responses. The survey has already been started by {0} users and completed by {1} users. It is not possible to restore the responses.
 run.command.delete.data.all.title=Delete all responses
 run.participation.done.message=You have already finished this survey. Thank you for your participation.
 run.participation.done.title=Survey finished
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_fr.properties
index ee9f8a53adc59b6c1d24820f101d7f1e2a1c7557..da6b9f47a86e48ae3396fbc0761aeab44f3e3a80 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_fr.properties
@@ -1,45 +1,44 @@
 #Thu Oct 08 13:56:14 CEST 2020
-condition.accessibility.title=Acc\u00E8s
+condition.accessibility.title=Acc\u00e8s
 course.node.link.text=Questionnaire
-edit.choose=Choisir, cr\u00E9er ou importer
+edit.choose=Choisir, cr\u00e9er ou importer
 edit.choose.evaluation.form=Choisir un questionnaire
 edit.edit=Editer
 edit.evaluation.form=Questionnaire
 edit.evaluation.form.link={0}
-edit.evaluation.form.not.choosen=Pas de questionnaire s\u00E9lectionner
+edit.evaluation.form.not.choosen=Pas de questionnaire s\u00e9lectionner
 edit.execution=Participation par
 edit.execution.by.coach=Coaches
-edit.execution.by.guest=Invit\u00E9s
-edit.execution.by.owner=Propri\u00E9taires
+edit.execution.by.guest=Invit\u00e9s
+edit.execution.by.owner=Propri\u00e9taires
 edit.execution.by.participant=Participants
-edit.preview=Aper\u00E7u
+edit.preview=Aper\u00e7u
 edit.replace=Remplacer
-edit.report=R\u00E9sultats visible pour
+edit.report=R\u00e9sultats visible pour
 edit.report.for.coach=Coaches
-edit.report.for.guest=Invit\u00E9s
-edit.report.for.owner=Propri\u00E9taires
+edit.report.for.guest=Invit\u00e9s
+edit.report.for.owner=Propri\u00e9taires
 edit.report.for.participant=Participants
 edit.title=Questionnaire
-error.repo.entry.missing=Le questionnaire que vous voulez afficher \u00E0 \u00E9t\u00E9 effac\u00E9 entre-temps des ressources didactiques.
-error.repo.entry.not.replaceable=Le questionnaire ne peut plus \u00EAtre remplac\u00E9.
-error.repo.no.key.long=Pour "{0}", vous devez s\u00E9lectionner un questionnaire dans le tab "Questionnaire" dans la section configuration.
-error.repo.no.key.short=Pas de questionnaire s\u00E9lectionn\u00E9.
+error.repo.entry.missing=Le questionnaire que vous voulez afficher \u00e0 \u00e9t\u00e9 effac\u00e9 entre-temps des ressources didactiques.
+error.repo.entry.not.replaceable=Le questionnaire ne peut plus \u00eatre remplac\u00e9.
+error.repo.no.key.long=Pour "{0}", vous devez s\u00e9lectionner un questionnaire dans le tab "Questionnaire" dans la section configuration.
+error.repo.no.key.short=Pas de questionnaire s\u00e9lectionn\u00e9.
 figure.course=Cours
-figure.course.node=\u00C9lement de cours
+figure.course.node=\u00c9lement de cours
 fully.assessed.trigger.status.done=Questionnaire soumis
-pane.tab.accessibility=Acc\u00E8s
+pane.tab.accessibility=Acc\u00e8s
 pane.tab.config=Questionnaire
-report.noaccess=Vous n'avez pas acc\u00E8s aux statistiques de ce questionnaire. Soit vous n'avez pas les autorisations requises, soit vous n'avez pas termin\u00E9 de remplir le questionnaire.
-run.command.delete.data.all=R\u00E9initialiser le questionnaire
+report.noaccess=Vous n'avez pas acc\u00e8s aux statistiques de ce questionnaire. Soit vous n'avez pas les autorisations requises, soit vous n'avez pas termin\u00e9 de remplir le questionnaire.
+run.command.delete.data.all=R\u00e9initialiser le questionnaire
 run.command.delete.data.all.button=Effacer
-run.command.delete.data.all.check=Effacer toutes les r\u00E9ponses
-run.command.delete.data.all.confirmation.error=Veuillez confirmer l'effacement de toutes les r\u00E9ponses.
-run.command.delete.data.all.message=Voulez-vous vraiment effacer toutes les r\u00E9ponses de ce questionnaire? {0} utilisateurs l'ont d\u00E9j\u00E0 rempli. Il ne sera pas possible de restaurer les r\u00E9ponses effac\u00E9es.
-run.command.delete.data.all.title=Effacer toutes les r\u00E9ponses
-run.no.survey.message=Le questionnaire n'est pas pr\u00EAt \u00E0 \u00EAtre utilis\u00E9.
-run.no.survey.title=Le questionnaire n'est pas pr\u00EAt.
+run.command.delete.data.all.check=Effacer toutes les r\u00e9ponses
+run.command.delete.data.all.confirmation.error=Veuillez confirmer l'effacement de toutes les r\u00e9ponses.
+run.command.delete.data.all.title=Effacer toutes les r\u00e9ponses
+run.no.survey.message=Le questionnaire n'est pas pr\u00eat \u00e0 \u00eatre utilis\u00e9.
+run.no.survey.title=Le questionnaire n'est pas pr\u00eat.
 run.noaccess.message=Cette partie du cours ne vous est pas accessible.
-run.noaccess.title=Acc\u00E8s refus\u00E9
-run.participation.done.message=Vous avez d\u00E9j\u00E0 rempli ce questionnaire. Merci de votre participation.
-run.participation.done.title=Questionnaire termin\u00E9
-run.reset=R\u00E9initialiser
+run.noaccess.title=Acc\u00e8s refus\u00e9
+run.participation.done.message=Vous avez d\u00e9j\u00e0 rempli ce questionnaire. Merci de votre participation.
+run.participation.done.title=Questionnaire termin\u00e9
+run.reset=R\u00e9initialiser
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_it.properties
index b45b426ceb8f6724ea3d78a68e326d7415150569..1e2bb64785e0927d916da2f1990122b8e686ff74 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_it.properties
+++ b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_it.properties
@@ -19,8 +19,8 @@ edit.report.for.guest=Ospiti
 edit.report.for.owner=Proprietari
 edit.report.for.participant=Partecipanti
 edit.title=Indagine
-error.repo.entry.missing=Questa indagine \u00E8 stata nel frattempo cancellata all'interno della cartella di memorizzazione delle risorse di apprendimento.
-error.repo.entry.not.replaceable=Il questionario non pu\u00F2 pi\u00F9 essere sostituito.
+error.repo.entry.missing=Questa indagine \u00e8 stata nel frattempo cancellata all'interno della cartella di memorizzazione delle risorse di apprendimento.
+error.repo.entry.not.replaceable=Il questionario non pu\u00f2 pi\u00f9 essere sostituito.
 error.repo.no.key.long=Per "{0}" devi selezionare un questionario nella scheda " Indagine" all'interno della sezione di configurazione.
 error.repo.no.key.short=Nessun questionario scelto.
 fully.assessed.trigger.status.done=Indagine terminata
@@ -30,12 +30,11 @@ run.command.delete.data.all=Resettare indagine
 run.command.delete.data.all.button=Cancellare
 run.command.delete.data.all.check=Cancellare tutte le risposte
 run.command.delete.data.all.confirmation.error=Si prega di confermare la cancellazione delle risposte.
-run.command.delete.data.all.message=Vuole davvero cancellare tutte le risposte? Gi\u00E0 {0} utenti hanno partecipato a questa indagine. Non \u00E8 possibile ripristinare le risposte.
 run.command.delete.data.all.title=Cancellare tutte le risposte
-run.no.survey.message=Questa indagine non \u00E8 disponibile per la partecipazione.
+run.no.survey.message=Questa indagine non \u00e8 disponibile per la partecipazione.
 run.no.survey.title=Indagine non pronta
-run.noaccess.message=Questa parte del corso non \u00E8 accessibile per lei.
+run.noaccess.message=Questa parte del corso non \u00e8 accessibile per lei.
 run.noaccess.title=Nessuno accesso
-run.participation.done.message=Lei ha gi\u00E0 terminato questo sondaggio. Grazie per la sua partecipazione.
+run.participation.done.message=Lei ha gi\u00e0 terminato questo sondaggio. Grazie per la sua partecipazione.
 run.participation.done.title=Indagine terminata
 run.reset=Resettare
diff --git a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_pt_BR.properties
index dedcf67ac3c5ee55df023b2db5c07531af57acd0..c50631bab21dfd0359b19ce8d378fa20d06a9b46 100644
--- a/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_pt_BR.properties
+++ b/src/main/java/org/olat/course/nodes/survey/ui/_i18n/LocalStrings_pt_BR.properties
@@ -1,43 +1,42 @@
 #Fri Sep 25 19:50:24 CEST 2020
 course.node.link.text=Pesquisa
 edit.choose=Escolha, crie ou importe
-edit.choose.evaluation.form=Escolha o question\u00E1rio
+edit.choose.evaluation.form=Escolha o question\u00e1rio
 edit.edit=Editar
-edit.evaluation.form=Question\u00E1rio
+edit.evaluation.form=Question\u00e1rio
 edit.evaluation.form.link={0}
-edit.evaluation.form.not.choosen=Nenhum question\u00E1rio escolhido
-edit.execution=Participa\u00E7\u00E3o por
+edit.evaluation.form.not.choosen=Nenhum question\u00e1rio escolhido
+edit.execution=Participa\u00e7\u00e3o por
 edit.execution.by.coach=Treinadores
 edit.execution.by.guest=Convidados
-edit.execution.by.owner=Propriet\u00E1rios
+edit.execution.by.owner=Propriet\u00e1rios
 edit.execution.by.participant=Participantes
 edit.preview=Visualizar
 edit.replace=Substituir
-edit.report=Resultados vis\u00EDveis para
+edit.report=Resultados vis\u00edveis para
 edit.report.for.coach=Treinadores
 edit.report.for.guest=Convidados
-edit.report.for.owner=Propriet\u00E1rios
+edit.report.for.owner=Propriet\u00e1rios
 edit.report.for.participant=Participantes
 edit.title=Pesquisa
-error.repo.entry.missing=Esta pesquisa foi apagada enquanto isso dentro da pasta de armazenamento de recursos did\u00E1ticos.
-error.repo.entry.not.replaceable=O question\u00E1rio n\u00E3o pode mais ser substitu\u00EDdo.
-error.repo.no.key.long=Para "{0}" voc\u00EA tem que selecionar um question\u00E1rio na aba "Pesquisa" dentro da se\u00E7\u00E3o de configura\u00E7\u00E3o.
-error.repo.no.key.short=Nenhum question\u00E1rio escolhido.
+error.repo.entry.missing=Esta pesquisa foi apagada enquanto isso dentro da pasta de armazenamento de recursos did\u00e1ticos.
+error.repo.entry.not.replaceable=O question\u00e1rio n\u00e3o pode mais ser substitu\u00eddo.
+error.repo.no.key.long=Para "{0}" voc\u00ea tem que selecionar um question\u00e1rio na aba "Pesquisa" dentro da se\u00e7\u00e3o de configura\u00e7\u00e3o.
+error.repo.no.key.short=Nenhum question\u00e1rio escolhido.
 figure.course=Curso
 figure.course.node=Elemento do Curso
-fully.assessed.trigger.status.done=Pesquisa conclu\u00EDda
+fully.assessed.trigger.status.done=Pesquisa conclu\u00edda
 pane.tab.config=Pesquisa
-report.noaccess=Voc\u00EA n\u00E3o tem acesso \u00E0s estat\u00EDsticas desta pesquisa. Voc\u00EA n\u00E3o tem os direitos necess\u00E1rios ou n\u00E3o terminou sua participa\u00E7\u00E3o.
+report.noaccess=Voc\u00ea n\u00e3o tem acesso \u00e0s estat\u00edsticas desta pesquisa. Voc\u00ea n\u00e3o tem os direitos necess\u00e1rios ou n\u00e3o terminou sua participa\u00e7\u00e3o.
 run.command.delete.data.all=Redefinir pesquisa
 run.command.delete.data.all.button=Excluir
 run.command.delete.data.all.check=Excluir todas as respostas
-run.command.delete.data.all.confirmation.error=Por favor, confirme a exclus\u00E3o das respostas.
-run.command.delete.data.all.message=Voc\u00EA realmente deseja excluir todas as respostas? {0} usu\u00E1rios j\u00E1 participaram desta pesquisa. N\u00E3o \u00E9 poss\u00EDvel restaurar as respostas.
+run.command.delete.data.all.confirmation.error=Por favor, confirme a exclus\u00e3o das respostas.
 run.command.delete.data.all.title=Excluir todas as respostas
-run.no.survey.message=A pesquisa n\u00E3o est\u00E1 pronta para participar.
-run.no.survey.title=Pesquisa n\u00E3o est\u00E1 pronta
-run.noaccess.message=Esta parte do curso n\u00E3o est\u00E1 acess\u00EDvel para voc\u00EA.
+run.no.survey.message=A pesquisa n\u00e3o est\u00e1 pronta para participar.
+run.no.survey.title=Pesquisa n\u00e3o est\u00e1 pronta
+run.noaccess.message=Esta parte do curso n\u00e3o est\u00e1 acess\u00edvel para voc\u00ea.
 run.noaccess.title=Sem acesso
-run.participation.done.message=Voc\u00EA j\u00E1 terminou esta pesquisa. Obrigado pela sua participa\u00E7\u00E3o.
-run.participation.done.title=Pesquisa conclu\u00EDda
+run.participation.done.message=Voc\u00ea j\u00e1 terminou esta pesquisa. Obrigado pela sua participa\u00e7\u00e3o.
+run.participation.done.title=Pesquisa conclu\u00edda
 run.reset=Redefinir
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java
index 858f9b2615b55a991a76c355493e5ec59074b2c5..bcbfafe069934b4f943b74ac02aec47ecc5cadfc 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java
@@ -101,6 +101,9 @@ public class BigBlueButtonMeetingController extends FormBasicController implemen
 	private final boolean moderatorStartMeeting;
 	private final OLATResourceable meetingOres;
 
+	private boolean withTools = false;
+	private boolean withPublish = false;
+
 	private FormLink joinButton;
 	private FormLink uploadButton;
 	private FormLink guestJoinButton;
@@ -261,10 +264,12 @@ public class BigBlueButtonMeetingController extends FormBasicController implemen
 		
 		if(administrator) {
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(BRecordingsCols.publish));
+			withPublish = true;
 			if(recordingsHandler.canDeleteRecordings() && recordingsHandler.allowPermanentRecordings()) {
 				DefaultFlexiColumnModel toolsCol = new DefaultFlexiColumnModel(BRecordingsCols.tools);
 				toolsCol.setIconHeader("o_icon o_icon_actions o_icon-lg");
 				columnsModel.addFlexiColumnModel(toolsCol);
+				withTools = true;
 			} else if(recordingsHandler.canDeleteRecordings()) {
 				columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete"));
 			}
@@ -297,18 +302,22 @@ public class BigBlueButtonMeetingController extends FormBasicController implemen
 		boolean pusblished = isPublishedForMe(recording.getReference(), attendee);
 		BigBlueButtonRecordingRow row = new BigBlueButtonRecordingRow(recording, pusblished);
 		if(administrator || moderator) {
-			String recId = recording.getRecording().getRecordId().toString();
-			FormLink publishLink = uifactory.addFormLink("publish-".concat(recId),
-					"publish", "publish.recording", tableEl);
-			row.setPublishLink(publishLink);
-			publishLink.setUserObject(row);
+			String recId = recording.getRecording().getRecordId();
+			if(withPublish) {
+				FormLink publishLink = uifactory.addFormLink("publish-".concat(recId),
+						"publish", "publish.recording", tableEl);
+				row.setPublishLink(publishLink);
+				publishLink.setUserObject(row);
+			}
 			
-			FormLink toolsLink = uifactory.addFormLink("tools-".concat(recId),
-					"tools", "", tableEl, Link.LINK | Link.NONTRANSLATED);
-			toolsLink.setAriaLabel(translate("table.header.actions"));
-			toolsLink.setIconRightCSS("o_icon o_icon_actions o_icon-lg");
-			toolsLink.setUserObject(row);
-			row.setToolsLink(toolsLink);
+			if(withTools) {
+				FormLink toolsLink = uifactory.addFormLink("tools-".concat(recId),
+						"tools", "", tableEl, Link.LINK | Link.NONTRANSLATED);
+				toolsLink.setAriaLabel(translate("table.header.actions"));
+				toolsLink.setIconRightCSS("o_icon o_icon_actions o_icon-lg");
+				toolsLink.setUserObject(row);
+				row.setToolsLink(toolsLink);
+			}
 		}
 		return row;
 	}
diff --git a/src/main/java/org/olat/modules/forms/EvaluationFormManager.java b/src/main/java/org/olat/modules/forms/EvaluationFormManager.java
index 7040f63670449bcce9347318935438aa2f8c7330..bdb7e1a782c413376613e336c4fe974814b5a3d3 100644
--- a/src/main/java/org/olat/modules/forms/EvaluationFormManager.java
+++ b/src/main/java/org/olat/modules/forms/EvaluationFormManager.java
@@ -176,8 +176,6 @@ public interface EvaluationFormManager {
 	 */
 	public EvaluationFormSession reopenSession(EvaluationFormSession session);
 	
-	public long getCountOfSessions(EvaluationFormSurveyRef surveyRef);
-	
 	public List<EvaluationFormResponse> getResponses(List<String> responseIdentifiers, SessionFilter filter, Limit limit);
 
 	public EvaluationFormResponse createStringResponse(String responseIdentifier, EvaluationFormSession session,
diff --git a/src/main/java/org/olat/modules/forms/SessionFilterFactory.java b/src/main/java/org/olat/modules/forms/SessionFilterFactory.java
index f6ae46461c294e1289e5db458a167df250a07919..ff23376d0a1a947d8bf294b69802a16d57dbc1be 100644
--- a/src/main/java/org/olat/modules/forms/SessionFilterFactory.java
+++ b/src/main/java/org/olat/modules/forms/SessionFilterFactory.java
@@ -51,6 +51,10 @@ public class SessionFilterFactory {
 			EvaluationFormSessionStatus status) {
 		return new SurveysFilter(surveyIdentitfier, status);
 	}
+	
+	public static SessionFilter create(EvaluationFormSurveyRef survey) {
+		return new SurveysFilter(Collections.singletonList(survey));
+	}
 
 	public static SessionFilter createSelectDone(EvaluationFormSurveyRef survey) {
 		return createSelectDone(Collections.singletonList(survey));
diff --git a/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java b/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
index 3b37dc2ab2ba1f124d983fd33f469786d3867f66..31715c1762be393f0564c4e0940f6f869a1b3add 100644
--- a/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
+++ b/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
@@ -361,11 +361,6 @@ public class EvaluationFormManagerImpl implements EvaluationFormManager {
 		return finishedSesssion;
 	}
 
-	@Override
-	public long getCountOfSessions(EvaluationFormSurveyRef surveyRef) {
-		return evaluationFormSessionDao.getCountOfSessions(surveyRef);
-	}
-
 	@Override
 	public EvaluationFormResponse createFileResponse(String responseIdentifier, EvaluationFormSession session,
 			File file, String filename) throws IOException {
diff --git a/src/main/java/org/olat/modules/forms/manager/EvaluationFormSessionDAO.java b/src/main/java/org/olat/modules/forms/manager/EvaluationFormSessionDAO.java
index 68c000b9c50ecd3bc201758966a7bd027bd20a19..b237c3aee0ac741e5077c754ece9255dce57b662 100644
--- a/src/main/java/org/olat/modules/forms/manager/EvaluationFormSessionDAO.java
+++ b/src/main/java/org/olat/modules/forms/manager/EvaluationFormSessionDAO.java
@@ -228,20 +228,6 @@ class EvaluationFormSessionDAO {
 		}
 		return session;
 	}
-
-	long getCountOfSessions(EvaluationFormSurveyRef surveyRef) {
-		if (surveyRef == null) return 0;
-	
-		StringBuilder sb = new StringBuilder();
-		sb.append("select count(session.key) from evaluationformsession as session");
-		sb.append(" where session.survey.key=:surveyKey");
-		
-		List<Long> counts = dbInstance.getCurrentEntityManager()
-				.createQuery(sb.toString(), Long.class)
-				.setParameter("surveyKey", surveyRef.getKey())
-				.getResultList();
-		return counts.get(0);
-	}
 	
 	void deleteSessions(EvaluationFormSurveyRef surveyRef) {
 		if (surveyRef == null) return;
diff --git a/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java b/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java
index 989b5d22d85ae1ee1732ec600b5fd22191a2eff1..704e676ee94e43c6a65a0dc51c39df7debe77c51 100644
--- a/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java
+++ b/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java
@@ -19,21 +19,29 @@
  */
 package org.olat.course.nodes.gta.manager;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
 import java.io.File;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.logging.log4j.Logger;
 import org.junit.Assert;
 import org.junit.Test;
 import org.olat.basesecurity.GroupRoles;
 import org.olat.core.commons.persistence.DB;
+import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.id.Identity;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.FileUtils;
 import org.olat.core.util.nodes.INode;
 import org.olat.course.CourseFactory;
 import org.olat.course.ICourse;
@@ -41,12 +49,14 @@ import org.olat.course.nodes.CourseNode;
 import org.olat.course.nodes.GTACourseNode;
 import org.olat.course.nodes.gta.AssignmentResponse;
 import org.olat.course.nodes.gta.AssignmentResponse.Status;
+import org.olat.course.nodes.gta.GTAManager;
 import org.olat.course.nodes.gta.GTAType;
 import org.olat.course.nodes.gta.Task;
 import org.olat.course.nodes.gta.TaskList;
 import org.olat.course.nodes.gta.TaskProcess;
 import org.olat.course.nodes.gta.TaskRevisionDate;
 import org.olat.course.nodes.gta.model.TaskListImpl;
+import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.manager.BusinessGroupDAO;
@@ -914,6 +924,311 @@ public class GTAManagerTest extends OlatTestCase {
 		Assert.assertEquals(TaskProcess.correction, loadedTaskRevision.getTaskStatus());
 	}
 	
+	@Test
+	public void assignTaskAutomatically() {
+		//prepare
+		Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-1");
+		RepositoryEntry re = deployGTACourse();
+		GTACourseNode node = getGTACourseNode(re);
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name());
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_SAMPLING, GTACourseNode.GTASK_SAMPLING_REUSE);
+		TaskList tasks = gtaManager.createIfNotExists(re, node);
+
+		CourseEnvironment courseEnv = CourseFactory.loadCourse(re).getCourseEnvironment();
+		File tasksDirectory = gtaManager.getTasksDirectory(courseEnv, node);
+		FileUtils.deleteDirsAndFiles(tasksDirectory, true, false);
+		copyTestFile(tasksDirectory, "File00O.pdf");
+		copyTestFile(tasksDirectory, "File0O0.pdf");
+		copyTestFile(tasksDirectory, "FileO00.pdf");
+		dbInstance.commit();
+		
+		//select
+		AssignmentResponse response = gtaManager.assignTaskAutomatically(tasks, participant, courseEnv, node);
+		dbInstance.commitAndCloseSession();
+		//check
+		Assert.assertNotNull(response);
+		Assert.assertNotNull(response.getTask());
+		Assert.assertEquals(AssignmentResponse.Status.ok, response.getStatus());
+		
+		Task task = response.getTask();
+		Assert.assertNotNull(task.getKey());
+		Assert.assertNull(task.getBusinessGroup());
+		Assert.assertNotNull(task.getCreationDate());
+		Assert.assertNotNull(task.getLastModified());
+		Assert.assertEquals(tasks, task.getTaskList());
+		Assert.assertEquals(participant, task.getIdentity());
+		assertThat(task.getTaskName())
+			.isIn("File00O.pdf", "File0O0.pdf", "FileO00.pdf");
+	}
+	
+	@Test
+	public void assignTaskAutomaticallyHighload() {
+		RepositoryEntry re = deployGTACourse();
+		GTACourseNode node = getGTACourseNode(re);
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name());
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_SAMPLING, GTACourseNode.GTASK_SAMPLING_REUSE);
+		TaskList tasks = gtaManager.createIfNotExists(re, node);
+
+		CourseEnvironment courseEnv = CourseFactory.loadCourse(re).getCourseEnvironment();
+		File tasksDirectory = gtaManager.getTasksDirectory(courseEnv, node);
+		FileUtils.deleteDirsAndFiles(tasksDirectory, true, false);
+		copyTestFile(tasksDirectory, "File00O.pdf");
+		copyTestFile(tasksDirectory, "File0O0.pdf");
+		copyTestFile(tasksDirectory, "FileO00.pdf");
+		copyTestFile(tasksDirectory, "FileOO0.pdf");
+		copyTestFile(tasksDirectory, "FileO0O.pdf");
+		dbInstance.commit();
+
+		final int numThreads = 25;
+		final int batchSize = 10;
+		final int numOfPersons = batchSize * numThreads;
+		List<Identity> participants = new ArrayList<>(numOfPersons);
+		for(int i=0; i<numOfPersons; i++) {
+			Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-high-load-" + i);
+			participants.add(participant);
+		}
+		
+		CountDownLatch latch = new CountDownLatch(numThreads);
+		AssignThread[] threads = new AssignThread[numThreads];
+		for(int i=0; i<threads.length;i++) {
+			List<Identity> batch = participants.subList(i * batchSize, (i + 1) * batchSize);
+			threads[i] = new AssignThread(batch, tasks, node, courseEnv, gtaManager, latch);
+		}
+
+		for(int i=0; i<threads.length;i++) {
+			threads[i].start();
+		}
+		
+		try {
+			latch.await(60, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			Assert.fail("Takes too long (more than 120sec)");
+		}
+		
+		int countErrors = 0;
+		for(int i=0; i<threads.length;i++) {
+			countErrors += threads[i].getErrors();
+		}
+		Assert.assertEquals(0, countErrors);
+		
+		List<Task> taskList = gtaManager.getTasks(tasks, node);
+		Map<String, AtomicInteger> maps = Map.of("File00O.pdf", new AtomicInteger(0), "File0O0.pdf", new AtomicInteger(0), "FileO00.pdf", new AtomicInteger(0),
+				"FileOO0.pdf", new AtomicInteger(0), "FileO0O.pdf", new AtomicInteger(0));
+		for(Task task:taskList) {
+			maps.get(task.getTaskName()).incrementAndGet();
+		}
+
+		Assert.assertEquals(5, maps.size());
+		for(AtomicInteger count:maps.values()) {
+			log.info("Counter: {}", count.get());
+			Assert.assertEquals(50, count.get());
+		}
+	}
+	
+	@Test
+	public void assignTaskAutomaticallyHighloadPreload() {
+		RepositoryEntry re = deployGTACourse();
+		GTACourseNode node = getGTACourseNode(re);
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name());
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_SAMPLING, GTACourseNode.GTASK_SAMPLING_REUSE);
+		TaskList tasks = gtaManager.createIfNotExists(re, node);
+
+		CourseEnvironment courseEnv = CourseFactory.loadCourse(re).getCourseEnvironment();
+		File tasksDirectory = gtaManager.getTasksDirectory(courseEnv, node);
+		FileUtils.deleteDirsAndFiles(tasksDirectory, true, false);
+		copyTestFile(tasksDirectory, "File00O.pdf");
+		copyTestFile(tasksDirectory, "File0O0.pdf");
+		copyTestFile(tasksDirectory, "FileO00.pdf");
+		dbInstance.commit();
+
+		final int numThreads = 12;
+		final int batchSize = 10;
+		final int numOfPersons = batchSize * numThreads;
+		List<Identity> participants = new ArrayList<>(numOfPersons);
+		for(int i=0; i<numOfPersons; i++) {
+			Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-high-load-" + i);
+			participants.add(participant);
+			gtaManager.createAndPersistTask(null, tasks, TaskProcess.assignment, null, participant, node);
+			if(i % 10 == 0) {
+				dbInstance.commitAndCloseSession();
+			}
+		}
+		dbInstance.commitAndCloseSession();
+		
+		CountDownLatch latch = new CountDownLatch(numThreads);
+		AssignThread[] threads = new AssignThread[numThreads];
+		for(int i=0; i<threads.length;i++) {
+			List<Identity> batch = participants.subList(i * batchSize, (i + 1) * batchSize);
+			threads[i] = new AssignThread(batch, tasks, node, courseEnv, gtaManager, latch);
+		}
+
+		for(int i=0; i<threads.length;i++) {
+			threads[i].start();
+		}
+		
+		try {
+			latch.await(60, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			Assert.fail("Takes too long (more than 60sec)");
+		}
+		
+		int countErrors = 0;
+		for(int i=0; i<threads.length;i++) {
+			countErrors += threads[i].getErrors();
+		}
+		Assert.assertEquals(0, countErrors);
+		
+		List<Task> taskList = gtaManager.getTasks(tasks, node);
+		Map<String, AtomicInteger> maps = Map.of("File00O.pdf", new AtomicInteger(0), "File0O0.pdf", new AtomicInteger(0), "FileO00.pdf", new AtomicInteger(0));
+		for(Task task:taskList) {
+			maps.get(task.getTaskName()).incrementAndGet();
+		}
+
+		Assert.assertEquals(3, maps.size());
+		for(AtomicInteger count:maps.values()) {
+			log.info("Counter: {}", count.get());
+		}
+		for(AtomicInteger count:maps.values()) {
+			Assert.assertEquals(numOfPersons / maps.size(), count.get());
+		}
+	}
+	
+	@Test
+	public void assignTaskAutomaticallyDeletedFile() {
+		RepositoryEntry re = deployGTACourse();
+		GTACourseNode node = getGTACourseNode(re);
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name());
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_SAMPLING, GTACourseNode.GTASK_SAMPLING_REUSE);
+		TaskList tasks = gtaManager.createIfNotExists(re, node);
+
+		CourseEnvironment courseEnv = CourseFactory.loadCourse(re).getCourseEnvironment();
+		File tasksDirectory = gtaManager.getTasksDirectory(courseEnv, node);
+		FileUtils.deleteDirsAndFiles(tasksDirectory, true, false);
+		copyTestFile(tasksDirectory, "File00O.pdf");
+		copyTestFile(tasksDirectory, "File0O0.pdf");
+		copyTestFile(tasksDirectory, "FileO00.pdf");
+		dbInstance.commit();
+		
+		for(int i=0; i<10; i++) {
+			Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-high-load-" + i);
+			String name = "File" + (i % 5) + ".pdf";
+			gtaManager.createAndPersistTask(name, tasks, TaskProcess.assignment, null, participant, node);
+			if(i % 10 == 0) {
+				dbInstance.commitAndCloseSession();
+			}
+		}
+
+		final int numThreads = 3;
+		final int batchSize = 3;
+		final int numOfPersons = batchSize * numThreads;
+		List<Identity> participants = new ArrayList<>(numOfPersons);
+		for(int i=0; i<numOfPersons; i++) {
+			Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-high-load-" + i);
+			participants.add(participant);
+			gtaManager.createAndPersistTask(null, tasks, TaskProcess.assignment, null, participant, node);
+			if(i % 10 == 0) {
+				dbInstance.commitAndCloseSession();
+			}
+		}
+		dbInstance.commitAndCloseSession();
+		
+		CountDownLatch latch = new CountDownLatch(numThreads);
+		AssignThread[] threads = new AssignThread[numThreads];
+		for(int i=0; i<threads.length;i++) {
+			List<Identity> batch = participants.subList(i * batchSize, (i + 1) * batchSize);
+			threads[i] = new AssignThread(batch, tasks, node, courseEnv, gtaManager, latch);
+		}
+
+		for(int i=0; i<threads.length;i++) {
+			threads[i].start();
+		}
+		
+		try {
+			latch.await(60, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			Assert.fail("Takes too long (more than 120sec)");
+		}
+		
+		int countErrors = 0;
+		for(int i=0; i<threads.length;i++) {
+			countErrors += threads[i].getErrors();
+		}
+		Assert.assertEquals(0, countErrors);
+		
+		List<Task> taskList = gtaManager.getTasks(tasks, node);
+		Map<String, AtomicInteger> maps = Map.of("File00O.pdf", new AtomicInteger(0), "File0O0.pdf", new AtomicInteger(0), "FileO00.pdf", new AtomicInteger(0));
+		for(Task task:taskList) {
+			if(maps.containsKey(task.getTaskName())) {
+				maps.get(task.getTaskName()).incrementAndGet();
+			}
+		}
+
+		Assert.assertEquals(3, maps.size());
+		for(AtomicInteger count:maps.values()) {
+			log.info("Counter: {}", count.get());
+		}
+		for(AtomicInteger count:maps.values()) {
+			Assert.assertEquals(numOfPersons / maps.size(), count.get());
+		}
+	}
+
+	private static class AssignThread extends Thread {
+
+		private final TaskList tasks;
+		private final GTACourseNode node;
+		private final GTAManager gtaManager;
+		private final List<Identity> batch;
+		private final CourseEnvironment courseEnv;
+		
+		private int errors;
+		private final CountDownLatch latch;
+		
+		public AssignThread(List<Identity> batch, TaskList tasks, GTACourseNode node,
+				CourseEnvironment courseEnv, GTAManager gtaManager, CountDownLatch latch) {
+			this.batch = new ArrayList<>(batch);
+			this.latch = latch;
+			this.tasks = tasks;
+			this.node = node;
+			this.courseEnv = courseEnv;
+			this.gtaManager = gtaManager;
+		}
+		
+		public int getErrors() {
+			return errors;
+		}
+		
+		@Override
+		public void run() {
+			try {
+				for(Identity participant:batch) {
+					AssignmentResponse response = gtaManager.assignTaskAutomatically(tasks, participant, courseEnv, node);
+					if(response == null || response.getTask() == null || response.getStatus() != Status.ok) {
+						errors++;
+					}
+					DBFactory.getInstance().commitAndCloseSession();
+					log.info("Assigned: {} {}", response.getStatus(), participant);
+				}
+			} catch (Exception e) {
+				log.error("", e);
+				errors++;
+			} finally {
+				DBFactory.getInstance().commitAndCloseSession();
+				latch.countDown();
+			}
+		}
+	}
+	
+	private void copyTestFile(File dir, String name) {
+		try {
+			URL url = JunitTestHelper.class.getResource("file_resources/task_1_a.txt");
+			File courseFile = new File(url.toURI());
+			File targetFile = new File(dir, name);
+			FileUtils.copyFileToFile(courseFile, targetFile, false);
+		} catch (URISyntaxException e) {
+			log.error("", e);
+		}
+	}
+	
 	@Test
 	public void roundRobin() {
 		String[] slots = new String[]{ "A", "B", "C" };
diff --git a/src/test/java/org/olat/modules/forms/manager/EvaluationFormSessionDAOTest.java b/src/test/java/org/olat/modules/forms/manager/EvaluationFormSessionDAOTest.java
index 10a1f5ecfe09a44fffcb50530c54588634955566..9843df6dd3431a4677ab67d570285bf0b668bbb1 100644
--- a/src/test/java/org/olat/modules/forms/manager/EvaluationFormSessionDAOTest.java
+++ b/src/test/java/org/olat/modules/forms/manager/EvaluationFormSessionDAOTest.java
@@ -234,23 +234,6 @@ public class EvaluationFormSessionDAOTest extends OlatTestCase {
 		assertThat(hasSessions).isFalse();
 	}
 	
-	@Test
-	public void shouldGetCountOfSessionsForSurvey() {
-		EvaluationFormSurvey survey = evaTestHelper.createSurvey();
-		dbInstance.commit();
-		
-		long countOfSessions = sut.getCountOfSessions(survey);
-		assertThat(countOfSessions).isEqualTo(0);
-		
-		evaTestHelper.createSession(survey);
-		evaTestHelper.createSession(survey);
-		dbInstance.commit();
-		
-		countOfSessions = sut.getCountOfSessions(survey);
-		assertThat(countOfSessions).isEqualTo(2);
-		
-	}
-	
 	@Test
 	public void shouldDeleteSessionsOfSurvey() {
 		EvaluationFormSurvey survey = evaTestHelper.createSurvey();