diff --git a/src/main/java/org/olat/collaboration/CollaborationTools.java b/src/main/java/org/olat/collaboration/CollaborationTools.java
index 7335af2921113daa7c33204cf256a8305b15ffe0..6e1da8f06550055b1c2096d49f5f60fbc2b3788d 100644
--- a/src/main/java/org/olat/collaboration/CollaborationTools.java
+++ b/src/main/java/org/olat/collaboration/CollaborationTools.java
@@ -594,8 +594,6 @@ public class CollaborationTools implements Serializable {
 			portfolioService.updateBinderUserInformations(binder, ureq.getIdentity());
 			BinderSecurityCallback secCallback = BinderSecurityCallbackFactory.getCallbackForBusinessGroup();
 			BinderController binderCtrl = new BinderController(ureq, wControl, stackPanel, secCallback, binder, BinderConfiguration.createBusinessGroupConfig());
-			List<ContextEntry> entries = BusinessControlFactory.getInstance().createCEListFromResourceType("Toc");
-			binderCtrl.activate(ureq, entries, null);
 			ctrl = binderCtrl;
 		} else {
 			PortfolioStructureMap map = (PortfolioStructureMap) CoreSpringFactory.getImpl(EPFrontendManager.class)
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 2d713ea0357bed1007115e82b0b4eb68e78151ad..d424995e395d50eed3b6f1ea43441a3698ce41bc 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,6 @@ 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.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.Formatter;
@@ -227,6 +226,7 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 				mainVC.contextPut("hasPassedValue", (scoreEval.getPassed() == null ? Boolean.FALSE : Boolean.TRUE));
 				mainVC.contextPut("passed", scoreEval.getPassed());
 				mainVC.contextPut("attempts", attempts); //at least one attempt
+				mainVC.contextPut("showChangeLog", Boolean.TRUE);
 			}
 		} else if(courseNode instanceof IQTESTCourseNode) {
 			IQTESTCourseNode testCourseNode = (IQTESTCourseNode)courseNode;
@@ -238,6 +238,7 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 				mainVC.contextPut("passed", Boolean.FALSE);
 				mainVC.contextPut("comment", null);
 				mainVC.contextPut("attempts", 0);
+				mainVC.contextPut("showChangeLog", Boolean.FALSE);
 			} else {
 				Boolean passed = assessmentEntry.getPassed();
 				//block if test passed (and config set to check it)
@@ -248,7 +249,6 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 				}
 				mainVC.contextPut("blockAfterSuccess", blocked);
 				
-				Identity identity = userCourseEnv.getIdentityEnvironment().getIdentity();
 				boolean resultsVisible = assessmentEntry.getUserVisibility() == null || assessmentEntry.getUserVisibility().booleanValue();
 				mainVC.contextPut("resultsVisible", resultsVisible);
 				mainVC.contextPut("score", AssessmentHelper.getRoundedScore(assessmentEntry.getScore()));
@@ -262,11 +262,8 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 				}
 				Integer attempts = assessmentEntry.getAttempts();
 				mainVC.contextPut("attempts", attempts == null ? new Integer(0) : attempts);
-				
-				if(!anonym) {
-					UserNodeAuditManager am = userCourseEnv.getCourseEnvironment().getAuditManager();
-					mainVC.contextPut("log", am.getUserNodeLog(courseNode, identity));
-				}
+				boolean showChangelog = (!anonym && resultsVisible && isResultVisible(config));
+				mainVC.contextPut("showChangeLog", showChangelog);
 				
 				if(deliveryOptions.isDigitalSignature()) {
 					AssessmentTestSession session = qtiService.getAssessmentTestSession(assessmentEntry.getAssessmentId());
@@ -305,7 +302,7 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 	}
 	
 	/**
-	 * WARNING! The variables showResultsOnHomePage, showResultsVisible and showChangelog are not used 
+	 * WARNING! The variables showResultsOnHomePage and showResultsVisible are not used 
 	 * in the velocity template and the CONFIG_KEY_RESULT_ON_HOME_PAGE is not editable
 	 * in the configuration of the course element for QTI 2.1!!!!
 	 * 
@@ -345,9 +342,10 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 			}
 		}
 		
-		UserNodeAuditManager am = userCourseEnv.getCourseEnvironment().getAuditManager();
-		mainVC.contextPut("log", am.getUserNodeLog(courseNode, getIdentity()));	
-		mainVC.contextPut("showChangelog", showResultsOnHomePage);
+		if(!anonym) {
+			UserNodeAuditManager am = userCourseEnv.getCourseEnvironment().getAuditManager();
+			mainVC.contextPut("log", am.getUserNodeLog(courseNode, getIdentity()));	
+		}
 	}
 	
 	private boolean isResultVisible(ModuleConfiguration modConfig) {
diff --git a/src/main/java/org/olat/course/nodes/iq/_content/assessment_run.html b/src/main/java/org/olat/course/nodes/iq/_content/assessment_run.html
index 8411566bb23db500a64b027abb000fc0e2c58563..6305ce0af905135f64a2487a1f004b66136f2a62 100644
--- a/src/main/java/org/olat/course/nodes/iq/_content/assessment_run.html
+++ b/src/main/java/org/olat/course/nodes/iq/_content/assessment_run.html
@@ -169,8 +169,7 @@
 	
 	<div class="o_button_group">$r.render("start")</div>
 #end
-
-#if($r.isNotNull($log)) ##&& $showChangelog (in QTI 1.2)
+#if($r.isNotNull($log) && $r.isNotNull($showChangeLog) && $showChangeLog)
 <div class="o_box">
     #o_togglebox_start("o_course_run_log" $r.translate("log.title"))
     <pre class="small">$log</pre>
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
index de911c432189951d27548959a9c87841194a9733..23bbd6bfc4cda6ac856cec8f8fc99e25a822cead 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
@@ -1475,7 +1475,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 							mailing = new MailPackage(true);
 						}
 
-						BusinessGroupMailing.sendEmail(ureqIdentity, firstWaitingListIdentity, group, MailType.graduateFromWaitingListToParticpant, mailing);				
+						BusinessGroupMailing.sendEmail(null, firstWaitingListIdentity, group, MailType.graduateFromWaitingListToParticpant, mailing);				
 						counter++;
 				  }
 				}
diff --git a/src/main/java/org/olat/group/ui/BGMailHelper.java b/src/main/java/org/olat/group/ui/BGMailHelper.java
index e29acffcc06146506e5b41d76c0afbc8ae32bdad..c7d68019f25aa182e8d0306ee527c969cd184ad9 100644
--- a/src/main/java/org/olat/group/ui/BGMailHelper.java
+++ b/src/main/java/org/olat/group/ui/BGMailHelper.java
@@ -192,13 +192,18 @@ public class BGMailHelper {
 	 */
 	private static MailTemplate createMailTemplate(BusinessGroupShort group, Identity actor, String subjectKey, String bodyKey) {
 		// get some data about the actor and fetch the translated subject / body via i18n module
-		String[] bodyArgs = new String[] {
-				actor.getUser().getProperty(UserConstants.FIRSTNAME, null),
-				actor.getUser().getProperty(UserConstants.LASTNAME, null),
-				actor.getUser().getProperty(UserConstants.EMAIL, null),
-				actor.getUser().getProperty(UserConstants.EMAIL, null)// 2x for compatibility with old i18m properties
-		};
-		Locale locale = I18nManager.getInstance().getLocaleOrDefault(actor.getUser().getPreferences().getLanguage());
+		String[] bodyArgs = null;
+		String lang = null;
+		if (actor != null) {
+			bodyArgs = new String[] {
+					actor.getUser().getProperty(UserConstants.FIRSTNAME, null),
+					actor.getUser().getProperty(UserConstants.LASTNAME, null),
+					actor.getUser().getProperty(UserConstants.EMAIL, null),
+					actor.getUser().getProperty(UserConstants.EMAIL, null)// 2x for compatibility with old i18m properties
+			};
+			lang = actor.getUser().getPreferences().getLanguage();
+		}
+		Locale locale = I18nManager.getInstance().getLocaleOrDefault(lang);
 		Translator trans = Util.createPackageTranslator(BGMailHelper.class, locale,
 				Util.createPackageTranslator(BusinessGroupListController.class, locale));
 		String subject = trans.translate(subjectKey);
diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
index f52a68026d325b72089cc4b8ad965eed7536976e..b7fc5c8b69dbbd2ca3cf9fb6fc892ee91f7e32a5 100644
--- a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
+++ b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
@@ -790,6 +790,9 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 		listenTo(collabToolCtr);
 		toolbarPanel.popUpToRootController(ureq);
 		toolbarPanel.pushController("Portfolio", collabToolCtr);
+		
+		List<ContextEntry> entries = BusinessControlFactory.getInstance().createCEListFromResourceType("Toc");
+		((Activateable2)collabToolCtr).activate(ureq, entries, null);
 		return (Activateable2)collabToolCtr;
 	}
 	
diff --git a/src/main/java/org/olat/ims/qti21/QTI21StatisticsManager.java b/src/main/java/org/olat/ims/qti21/QTI21StatisticsManager.java
index 371f237ce4067a8aea8a067b7496980b55fe371e..e60bd2e7755abb49bd41d7d4f64b1fd34680bc0e 100644
--- a/src/main/java/org/olat/ims/qti21/QTI21StatisticsManager.java
+++ b/src/main/java/org/olat/ims/qti21/QTI21StatisticsManager.java
@@ -26,6 +26,7 @@ import org.olat.ims.qti.statistics.model.StatisticAssessment;
 import org.olat.ims.qti.statistics.model.StatisticsItem;
 import org.olat.ims.qti21.model.QTI21StatisticSearchParams;
 import org.olat.ims.qti21.model.statistics.AbstractTextEntryInteractionStatistics;
+import org.olat.ims.qti21.model.statistics.AssessmentItemStatistic;
 import org.olat.ims.qti21.model.statistics.ChoiceStatistics;
 import org.olat.ims.qti21.model.statistics.HotspotChoiceStatistics;
 import org.olat.ims.qti21.model.statistics.KPrimStatistics;
@@ -37,6 +38,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.interaction.HotspotInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.HottextInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.MatchInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.TextEntryInteraction;
+import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
 
 /**
  * 
@@ -86,5 +88,15 @@ public interface QTI21StatisticsManager {
 	
 	public List<AbstractTextEntryInteractionStatistics> getTextEntryInteractionsStatistic(String itemRefIdent,
 			AssessmentItem item, List<TextEntryInteraction> interactions, QTI21StatisticSearchParams searchParams);
+	
+	/**
+	 * 
+	 * @param items
+	 * @param searchParams
+	 * @param numOfParticipants
+	 * @return
+	 */
+	public List<AssessmentItemStatistic> getStatisticPerItem(ResolvedAssessmentTest resolvedAssessmentTest, QTI21StatisticSearchParams searchParams,
+			double numOfParticipants);
 
 }
diff --git a/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
index ce14890587a932ab8677c5a9b4d2686b4aef49e2..7d5d6457e6b7f544fe4dbee6fad649575e121b3f 100644
--- a/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
+++ b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
@@ -40,6 +40,7 @@ import org.olat.ims.qti.statistics.model.StatisticsItem;
 import org.olat.ims.qti21.QTI21StatisticsManager;
 import org.olat.ims.qti21.model.QTI21StatisticSearchParams;
 import org.olat.ims.qti21.model.statistics.AbstractTextEntryInteractionStatistics;
+import org.olat.ims.qti21.model.statistics.AssessmentItemStatistic;
 import org.olat.ims.qti21.model.statistics.ChoiceStatistics;
 import org.olat.ims.qti21.model.statistics.HotspotChoiceStatistics;
 import org.olat.ims.qti21.model.statistics.KPrimStatistics;
@@ -67,6 +68,9 @@ import uk.ac.ed.ph.jqtiplus.node.item.interaction.content.Hottext;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.HotspotChoice;
 import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.MapEntry;
 import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
+import uk.ac.ed.ph.jqtiplus.node.test.AssessmentItemRef;
+import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
+import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
 import uk.ac.ed.ph.jqtiplus.types.Identifier;
 import uk.ac.ed.ph.jqtiplus.utils.QueryUtils;
 import uk.ac.ed.ph.jqtiplus.value.BaseType;
@@ -637,6 +641,120 @@ public class QTI21StatisticsManagerImpl implements QTI21StatisticsManager {
 		return datas;
 	}
 	
+	@Override
+	public List<AssessmentItemStatistic> getStatisticPerItem(ResolvedAssessmentTest resolvedAssessmentTest, QTI21StatisticSearchParams searchParams, double numOfParticipants) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select isession.assessmentItemIdentifier, isession.score, isession.manualScore, count(*) from qtiassessmentitemsession isession")
+		  .append(" inner join isession.assessmentTestSession asession");
+		decorateRSet(sb, searchParams, true);
+		sb.append(" and isession.duration > 0")
+		  .append(" group by isession.assessmentItemIdentifier, isession.score, isession.manualScore");
+		
+		TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Object[].class);
+		decorateRSetQuery(query, searchParams);
+		List<Object[]> results = query.getResultList();
+		if(results.isEmpty()) {
+			return new ArrayList<>();
+		}
+		
+		Map<String,AssessmentItemRef> itemMap = new HashMap<>();
+		for(AssessmentItemRef itemRef:resolvedAssessmentTest.getAssessmentItemRefs()) {
+			itemMap.put(itemRef.getIdentifier().toString(), itemRef);
+		}
+
+		Map<String, AssessmentItemHelper> identifierToHelpers = new HashMap<>();
+		for(Object[] result:results) {
+			int pos = 0;
+			String identifier = PersistenceHelper.extractString(result, pos++);
+			BigDecimal score = (BigDecimal)result[pos++];
+			BigDecimal manualScore = (BigDecimal)result[pos++];
+			Long count = PersistenceHelper.extractLong(result, pos++);
+			if(score == null || identifier == null || count == null) {
+				continue;
+			}
+
+			AssessmentItemHelper helper = identifierToHelpers.get(identifier);
+			if(helper == null) {
+				AssessmentItemRef itemRef = itemMap.get(identifier);
+				if(itemRef == null) {
+					continue;
+				} 
+				ResolvedAssessmentItem item = resolvedAssessmentTest.getResolvedAssessmentItem(itemRef);
+				if(item == null) {
+					continue;
+				}
+				helper = new AssessmentItemHelper(item.getRootNodeLookup().extractIfSuccessful());
+				identifierToHelpers.put(identifier, helper);
+			}
+			
+			helper.addCount(count);
+			if(manualScore != null) {
+				helper.addTotalScore(count, manualScore);
+			} else {
+				helper.addTotalScore(count, score);
+			}
+
+			if(helper.getMaxScore() != null) {
+				double maxValue = helper.getMaxScore().doubleValue();
+				if(Math.abs(score.doubleValue() - maxValue) < 0.0001) {
+					helper.addCorrectAnswers(count);
+				}
+			}
+		}
+		
+		List<AssessmentItemStatistic> statistics = new ArrayList<>(identifierToHelpers.size());
+		for(AssessmentItemHelper helper:identifierToHelpers.values()) {
+			long numOfAnswersItem = helper.count;
+			long numOfCorrectAnswers = helper.countCorrectAnswers;
+			double average = (helper.totalScore / helper.count);
+			double averageParticipants = (helper.totalScore / numOfParticipants);
+			statistics.add(new AssessmentItemStatistic(helper.getAssessmentItem(), average, averageParticipants, numOfAnswersItem, numOfCorrectAnswers));
+		}
+		return statistics;
+	}
+	
+	public static class AssessmentItemHelper {
+		private long count = 0l;
+		private double totalScore = 0.0d;
+		private Double maxScore;
+		private long countCorrectAnswers = 0;
+		private final AssessmentItem assessmentItem;
+		
+		public AssessmentItemHelper(AssessmentItem assessmentItem) {
+			this.assessmentItem = assessmentItem;
+			if(assessmentItem != null) {
+				maxScore = QtiNodesExtractor.extractMaxScore(assessmentItem);
+			}
+		}
+		
+		public AssessmentItem getAssessmentItem() {
+			return assessmentItem;
+		}
+		
+		public Double getMaxScore() {
+			return maxScore;
+		}
+		
+		public void addTotalScore(Long numOfAnswers, BigDecimal score) {
+			if(numOfAnswers != null && score != null) {
+				totalScore += (numOfAnswers.doubleValue() * score.doubleValue());
+			}
+		}
+		
+		public void addCount(Long toAdd) {
+			if(toAdd != null) {
+				count += toAdd.longValue();
+			}
+		}
+		
+		public void addCorrectAnswers(Long toAdd) {
+			if(toAdd != null) {
+				countCorrectAnswers += toAdd.longValue();
+			}
+		}
+	}
+	
 	public static class RawData {
 		
 		private final Long itemSessionKey;
diff --git a/src/main/java/org/olat/ims/qti21/model/statistics/AssessmentItemStatistic.java b/src/main/java/org/olat/ims/qti21/model/statistics/AssessmentItemStatistic.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f30d05518793e1fca9ef84df9a4bb9a2e13b555
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/model/statistics/AssessmentItemStatistic.java
@@ -0,0 +1,76 @@
+/**
+ * <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.model.statistics;
+
+import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
+
+/**
+ * 
+ * Initial date: 9 mai 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentItemStatistic {
+	
+	private final AssessmentItem assessmentItem;
+	private final double averageScore;
+	private final double averageScoreAllParticipants;
+	private final long numOfAnswers;
+	private final long numOfCorrectAnswers;
+	
+	public AssessmentItemStatistic(AssessmentItem assessmentItem, double averageScore, double averageScoreAllParticipants,
+			long numOfAnswers, long numOfCorrectAnswers) {
+		this.assessmentItem = assessmentItem;
+		this.averageScore = averageScore;
+		this.averageScoreAllParticipants = averageScoreAllParticipants;
+		this.numOfAnswers = numOfAnswers;
+		this.numOfCorrectAnswers = numOfCorrectAnswers;
+	}
+	
+	public AssessmentItem getAssessmentItem() {
+		return assessmentItem;
+	}
+	
+	/**
+	 * Average build with the score and the number of answered questions.
+	 * It doesn't take not answered questions in the count.
+	 * @return
+	 */
+	public double getAverageScore() {
+		return averageScore;
+	}
+	
+	/**
+	 * Average build with the score and the number of participants to the test.
+	 * The average is built with the users which didn't answer the question.
+	 * @return
+	 */
+	public double getAverageScoreAllParticipants() {
+		return averageScoreAllParticipants;
+	}
+
+	public long getNumOfAnswers() {
+		return numOfAnswers;
+	}
+
+	public long getNumOfCorrectAnswers() {
+		return numOfCorrectAnswers;
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/model/statistics/NumericalInputInteractionStatistics.java b/src/main/java/org/olat/ims/qti21/model/statistics/NumericalInputInteractionStatistics.java
index 41573aa0c5e7e59f0ce61921cc856aca6f896579..900817488bf4b3827b9fe6927ac6dc5b73316fcc 100644
--- a/src/main/java/org/olat/ims/qti21/model/statistics/NumericalInputInteractionStatistics.java
+++ b/src/main/java/org/olat/ims/qti21/model/statistics/NumericalInputInteractionStatistics.java
@@ -67,14 +67,29 @@ public class NumericalInputInteractionStatistics extends AbstractTextEntryIntera
 		if(correctFloatResponse == null) return false;
 		
 		try {
-			double secondNumber = Double.parseDouble(value);
-			double firstNumber = correctFloatResponse.doubleValue();
-			double tolerance1 = lowerTolerance == null ? 0.0d : lowerTolerance.doubleValue();
-			double tolerance2 = upperTolerance == null ? 0.0d : upperTolerance.doubleValue();
-			return toleranceMode.isEqual(firstNumber, secondNumber, tolerance1, tolerance2, true, true);
-		} catch (NumberFormatException | NullPointerException e) {
+			double answer = Double.parseDouble(value);
+			return match(answer);
+		} catch (NumberFormatException  e) {
+			if(value.indexOf(',') >= 0) {//allow , instead of .
+                try {
+					double answer = Double.parseDouble(value.replace(',', '.'));
+					return match(answer);
+				} catch (final NumberFormatException e1) {
+					//format can happen
+				} catch (Exception e2) {
+					log.error("", e2);
+				}
+        	}
+			return false;
+		} catch (Exception  e) {
 			log.error("", e);
 			return false;
 		}
 	}
+	
+	private boolean match(double answer) {
+		double lTolerance = lowerTolerance == null ? 0.0d : lowerTolerance.doubleValue();
+		double uTolerance = upperTolerance == null ? 0.0d : upperTolerance.doubleValue();
+		return toleranceMode.isEqual(answer, correctFloatResponse.doubleValue(), lTolerance, uTolerance, true, true);
+	}
 }
diff --git a/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21AssessmentTestStatisticsController.java b/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21AssessmentTestStatisticsController.java
index 3f61d84f964d86793ce8c6024329abcecbae9704..f1899648fe76aadce348ac45cebacc8246fcafea 100644
--- a/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21AssessmentTestStatisticsController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21AssessmentTestStatisticsController.java
@@ -23,6 +23,8 @@ import static org.olat.ims.qti.statistics.ui.StatisticFormatter.duration;
 import static org.olat.ims.qti.statistics.ui.StatisticFormatter.format;
 import static org.olat.ims.qti.statistics.ui.StatisticFormatter.getModeString;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -30,6 +32,7 @@ import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.chart.BarSeries;
+import org.olat.core.gui.components.chart.BarSeries.Stringuified;
 import org.olat.core.gui.components.chart.StatisticsComponent;
 import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.components.link.LinkFactory;
@@ -54,8 +57,14 @@ import org.olat.course.nodes.QTICourseNode;
 import org.olat.course.nodes.iq.IQEditController;
 import org.olat.ims.qti.statistics.QTIType;
 import org.olat.ims.qti.statistics.model.StatisticAssessment;
+import org.olat.ims.qti.statistics.ui.QTI12AssessmentStatisticsController.ItemInfos;
+import org.olat.ims.qti21.QTI21StatisticsManager;
+import org.olat.ims.qti21.model.statistics.AssessmentItemStatistic;
 import org.olat.modules.assessment.ui.UserFilterController;
 import org.olat.modules.assessment.ui.event.UserFilterEvent;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
 
 /**
  * 
@@ -73,6 +82,9 @@ public class QTI21AssessmentTestStatisticsController extends BasicController imp
 	private QTIType type;
 	private QTICourseNode courseNode;
 	private final QTI21StatisticResourceResult resourceResult;
+	
+	@Autowired
+	private QTI21StatisticsManager qtiStatisticsManager;
 
 	public QTI21AssessmentTestStatisticsController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
 			QTI21StatisticResourceResult resourceResult, boolean withFilter, boolean printMode) {
@@ -137,6 +149,7 @@ public class QTI21AssessmentTestStatisticsController extends BasicController imp
 	private void updateData() {
 		StatisticAssessment stats = resourceResult.getQTIStatisticAssessment();
 		initScoreHistogram(stats);
+		initScoreStatisticPerItem(stats.getNumOfParticipants());
 		initDurationHistogram(stats);
 		initCourseNodeInformation(stats);
 	}
@@ -212,6 +225,39 @@ public class QTI21AssessmentTestStatisticsController extends BasicController imp
 		mainVC.put("durationHistogram", durationHistogramVC);
 	}
 	
+	private void initScoreStatisticPerItem(double numOfParticipants) {
+		BarSeries d1 = new BarSeries();
+		BarSeries d2 = new BarSeries();
+		
+		List<AssessmentItemStatistic> statisticItems = qtiStatisticsManager
+				.getStatisticPerItem(resourceResult.getResolvedAssessmentTest(), resourceResult.getSearchParams(), numOfParticipants);
+		
+		int i = 0;
+		List<ItemInfos> itemInfos = new ArrayList<>(statisticItems.size());
+		for (AssessmentItemStatistic statisticItem: statisticItems) {
+			AssessmentItem item = statisticItem.getAssessmentItem();
+			
+			String label = Integer.toString(++i);
+			String text = item.getTitle(); 
+			d1.add(statisticItem.getAverageScore(), label);
+			d2.add(statisticItem.getNumOfCorrectAnswers(), label);
+			itemInfos.add(new ItemInfos(label, text));
+		}
+		
+		mainVC.contextPut("itemInfoList", itemInfos);
+
+		VelocityContainer averageScorePeritemVC = createVelocityContainer("hbar_average_score_per_item");
+		Stringuified data1 = BarSeries.getDatasAndColors(Collections.singletonList(d1), "bar_default");
+		averageScorePeritemVC.contextPut("datas", data1);
+		mainVC.put("averageScorePerItemChart", averageScorePeritemVC);
+		
+		VelocityContainer percentRightAnswersPerItemVC = createVelocityContainer("hbar_right_answer_per_item");
+		Stringuified data2 = BarSeries.getDatasAndColors(Collections.singletonList(d2), "bar_green");
+		percentRightAnswersPerItemVC.contextPut("datas", data2);
+		percentRightAnswersPerItemVC.contextPut("numOfParticipants", Long.toString(Math.round(numOfParticipants)));
+		mainVC.put("percentRightAnswersPerItemChart", percentRightAnswersPerItemVC);
+	}
+	
 	@Override
 	public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
 		//
diff --git a/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21StatisticResourceResult.java b/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21StatisticResourceResult.java
index b5eff08a55b25cd0aca9f8a3d879dfd7f276921b..a66d7a8bdea1faecc1c2f1af9c8ace60dd9154ac 100644
--- a/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21StatisticResourceResult.java
+++ b/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21StatisticResourceResult.java
@@ -21,6 +21,7 @@ package org.olat.ims.qti21.ui.statistics;
 
 import java.io.File;
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.List;
 
 import org.olat.core.CoreSpringFactory;
@@ -115,6 +116,20 @@ public class QTI21StatisticResourceResult implements StatisticResourceResult {
 		return testEntry;
 	}
 	
+	public ResolvedAssessmentTest getResolvedAssessmentTest() {
+		return resolvedAssessmentTest;
+	}
+	
+	public List<AssessmentItem> getAssessmentItems() {
+		List<AssessmentItemRef> itemRefs = resolvedAssessmentTest.getAssessmentItemRefs();
+		List<AssessmentItem> items = new ArrayList<>(itemRefs.size());
+		for(AssessmentItemRef itemRef:itemRefs) {
+			AssessmentItem item = resolvedAssessmentTest.getResolvedAssessmentItem(itemRef).getRootNodeLookup().extractIfSuccessful();
+			items.add(item);
+		}
+		return items;
+	}
+	
 	public QTI21StatisticSearchParams getSearchParams() {
 		return searchParams;
 	}
diff --git a/src/main/java/org/olat/ims/qti21/ui/statistics/_content/hbar_average_score_per_item.html b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/hbar_average_score_per_item.html
new file mode 100644
index 0000000000000000000000000000000000000000..c8309dcfaaac7c3d8a98dfa98183ce3cdef06d49
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/hbar_average_score_per_item.html
@@ -0,0 +1,13 @@
+<div id="$r.getId('d3div')"><div id="$r.getId('d3holder')" class='d3chart' style='width:90%;'></div>
+<script type='text/javascript'>
+/* <![CDATA[ */
+jQuery(function () {
+	jQuery('#$r.getId("d3holder")').qtiStatistics('averageScorePerItem', {
+		values: [$datas.data],
+		barHeight: 20,
+		xBottomLegend: ' $r.translate("chart.answer.averageScoreQuestions.y")',
+		yLeftLegend: '$r.translate("chart.item")'
+	});
+});
+/* ]]> */</script>
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/statistics/_content/hbar_right_answer_per_item.html b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/hbar_right_answer_per_item.html
new file mode 100644
index 0000000000000000000000000000000000000000..349f6f4b29a1185ed3c1d03520d0b1908bbf7151
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/hbar_right_answer_per_item.html
@@ -0,0 +1,15 @@
+<div id="$r.getId('d3div')"><div id="$r.getId('d3holder')" class='d3chart' style='width:90%;'></div>
+<script type='text/javascript'>
+/* <![CDATA[ */
+jQuery(function () {
+	jQuery('#$r.getId("d3holder")').qtiStatistics('rightAnswerPerItem', {
+		values: [$datas.data],
+		barHeight: 20,
+		participants: $numOfParticipants,
+		xBottomLegend: '$r.translate("chart.percent.participants.num")',
+		xTopLegend: '$r.translate("chart.percent.participants")',
+		yLeftLegend: '$r.translate("chart.item")'
+	});
+});
+/* ]]> */</script>
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/statistics/_content/statistics_assessment_test.html b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/statistics_assessment_test.html
index 8fb5fd7bc5da67edb31c36e3f505408f16b5e4c8..1bef835532f73e54ef595207c2e542065307c66f 100644
--- a/src/main/java/org/olat/ims/qti21/ui/statistics/_content/statistics_assessment_test.html
+++ b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/statistics_assessment_test.html
@@ -4,6 +4,7 @@
 </div>
 #end
 
+<div class="o_qti_statistics">
 <div class="panel panel-default">
 	<div class="panel-heading"><h4>$r.translate("fig.title")</h4></div>	  	
 	<table class="table"><tbody>
@@ -44,4 +45,29 @@
 #end
 #if($r.available("durationHistogram") && $r.visible("durationHistogram"))
 	$r.render("durationHistogram")
-#end
\ No newline at end of file
+#end
+
+#if($r.available("averageScorePerItemChart"))
+<div class="o_print_break_avoid">
+	<h4>$r.translate("chart.averagescore.peritem")</h4>
+	$r.render("averageScorePerItemChart")
+	<ul>
+	#foreach($itemInfo in $itemInfoList)
+		<li><strong>${itemInfo.label}.</strong> $itemInfo.text</li>
+	#end
+	</ul>
+</div>
+#end
+
+#if($r.available("percentRightAnswersPerItemChart"))
+<div class="o_print_break_avoid">
+	<h4>$r.translate("chart.rightanswers.peritem")</h4>
+	$r.render("percentRightAnswersPerItemChart")
+	<ul>
+	#foreach($itemInfo in $itemInfoList)
+		<li><strong>${itemInfo.label}.</strong> $itemInfo.text</li>
+	#end
+	</ul>
+</div>
+#end
+</div>
diff --git a/src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_de.properties
index 12a26d71cf7ebcfd4253bef23d6a97d1dddfe690..2a26a53ac6fb6ddd74d5c7b844917445d2c7ca49 100644
--- a/src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_de.properties
@@ -13,6 +13,9 @@ chart.percent.participants.num=$org.olat.ims.qti.statistics.ui\:chart.percent.pa
 chart.points=$org.olat.ims.qti.statistics.ui\:chart.points
 chart.responses=$org.olat.ims.qti.statistics.ui\:chart.responses
 chart.score.histogramm=$org.olat.ims.qti.statistics.ui\:chart.score.histogramm
+chart.averagescore.peritem=$org.olat.ims.qti.statistics.ui\:chart.averagescore.peritem
+chart.rightanswers.peritem=$org.olat.ims.qti.statistics.ui\:chart.rightanswers.peritem
+chart.answer.averageScoreQuestions.y=$org.olat.ims.qti.statistics.ui\:chart.answer.averageScoreQuestions.y
 download.raw.data=$org.olat.ims.qti.statistics.ui\:download.raw.data
 fib.wrong.answer=$org.olat.ims.qti.statistics.ui\:fib.wrong.answer
 fig.averagedur=$org.olat.ims.qti.statistics.ui\:fig.averagedur
diff --git a/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java b/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java
index 39bd4273f9d2f478147e7526d4bf337a88612933..f5acbe70cfa1e4dd9572db66598954620c70fcb1 100644
--- a/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java
+++ b/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java
@@ -93,7 +93,7 @@ public class BinderSecurityCallbackFactory {
 	 * @return
 	 */
 	public static final BinderSecurityCallback getCallbackForBusinessGroup() {
-		return new BinderSecurityCallbackImpl(true, false, null);
+		return new BinderSecurityCallbackGroup(true, false, null);
 	}
 
 	private static class BinderSecurityCallbackForDeletedPages extends DefaultBinderSecurityCallback {
@@ -252,6 +252,18 @@ public class BinderSecurityCallbackFactory {
 		}
 	}
 	
+	private static class BinderSecurityCallbackGroup extends BinderSecurityCallbackImpl {
+		
+		public BinderSecurityCallbackGroup(boolean owner, boolean task, BinderDeliveryOptions deliveryOptions) {
+			super(owner, task, deliveryOptions);
+		}
+
+		@Override
+		public boolean canDeleteBinder(Binder binder) {
+			return false;
+		}
+	}
+	
 	private static class BinderSecurityCallbackImpl implements BinderSecurityCallback {
 		
 		/**