diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java
index e18e67bb97585ae2f574f3c77791c492f9319c2f..31df0207c6059dbe1cd77507655c92c19cf57763 100644
--- a/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java
+++ b/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java
@@ -50,8 +50,8 @@ public class AssessmentToolManagerImpl implements AssessmentToolManager {
 		sb.append("select ident")
 		  .append(" from ").append(IdentityImpl.class.getName()).append(" as ident ")
 		  .append(" where exists (")
-		  .append("  select infos from usercourseinfos infos where infos.identity=ident")
-		  .append("     and infos.resource.key=:resourceKey")
+		  .append("  select infos from assessmententry infos where infos.identity=ident")
+		  .append("     and infos.repositoryEntry.key=:courseEntryKey")
 		  .append(" ) or exists (select rel from repoentrytogroup as rel, bgroup as baseGroup, bgroupmember as membership")
 		  .append("    where rel.entry.key=:courseEntryKey and rel.group=baseGroup and membership.group=baseGroup and membership.identity=ident")
 		  .append("      and membership.role='").append(GroupRoles.participant.name()).append("'")
@@ -60,7 +60,6 @@ public class AssessmentToolManagerImpl implements AssessmentToolManager {
 		List<Identity> list = dbInstance.getCurrentEntityManager()
 			.createQuery(sb.toString(), Identity.class)
 			.setParameter("courseEntryKey", params.getCourseEntry().getKey())
-			.setParameter("resourceKey", params.getCourseEntry().getOlatResource().getKey())
 			.getResultList();
 		return list;	
 	}
diff --git a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java
index e8d6d50cd47f43dee52b92431f5fa2934d855c63..e1ef5135e0229533b62993bbdd3276cf9b028274 100644
--- a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java
+++ b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java
@@ -206,23 +206,24 @@ public class CourseAssessmentManagerImpl implements AssessmentManager {
 		Boolean passed = scoreEvaluation.getPassed();
 		Long assessmentId = scoreEvaluation.getAssessmentID();
 
-		AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode);
+		AssessmentEntry assessmentEntry = getOrCreate(assessedIdentity, courseNode);
 		if(score == null) {
-			nodeAssessment.setScore(null);
+			assessmentEntry.setScore(null);
 		} else {
-			nodeAssessment.setScore(new BigDecimal(Float.toString(score)));
+			assessmentEntry.setScore(new BigDecimal(Float.toString(score)));
 		}
-		nodeAssessment.setPassed(passed);
-		nodeAssessment.setFullyAssessed(scoreEvaluation.getFullyAssessed());
-		nodeAssessment.setAssessmentId(assessmentId);
+		assessmentEntry.setPassed(passed);
+		assessmentEntry.setFullyAssessed(scoreEvaluation.getFullyAssessed());
+		assessmentEntry.setAssessmentId(assessmentId);
 		if(incrementUserAttempts) {
-			int attempts = nodeAssessment.getAttempts() == null ? 1 :nodeAssessment.getAttempts().intValue() + 1;
-			nodeAssessment.setAttempts(attempts);
+			int attempts = assessmentEntry.getAttempts() == null ? 1 :assessmentEntry.getAttempts().intValue() + 1;
+			assessmentEntry.setAttempts(attempts);
 		}
-		nodeAssessment = assessmentService.updateAssessmentEntry(nodeAssessment);
+		assessmentEntry = assessmentService.updateAssessmentEntry(assessmentEntry);
 		
 		
 		if(courseNode instanceof AssessableCourseNode) {
+			userCourseEnv.getScoreAccounting().scoreInfoChanged((AssessableCourseNode)courseNode, scoreEvaluation);
 			// Update users efficiency statement
 			efficiencyStatementManager.updateUserEfficiencyStatement(userCourseEnv);
 		}
diff --git a/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java b/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java
index efa1cc32aff0ea9e682a18513fc9ce1e7f5443d7..ee83cde87a8924afa21346a3584d2e4cc1686f06 100644
--- a/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java
+++ b/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java
@@ -54,7 +54,7 @@ import org.olat.ims.qti.statistics.model.StatisticAssessment;
 import org.olat.ims.qti.statistics.ui.QTI12AssessmentStatisticsController;
 import org.olat.ims.qti.statistics.ui.QTI12ItemStatisticsController;
 import org.olat.ims.qti.statistics.ui.QTI21OnyxAssessmentStatisticsController;
-import org.olat.ims.qti21.statistics.ui.QTI21AssessmentTestStatisticsController;
+import org.olat.ims.qti21.ui.statistics.QTI21AssessmentTestStatisticsController;
 import org.olat.repository.RepositoryEntry;
 
 import de.bps.onyx.plugin.OnyxModule;
diff --git a/src/main/java/org/olat/ims/qti21/QTI21Service.java b/src/main/java/org/olat/ims/qti21/QTI21Service.java
index 276a673f928797fa9cd32e26c0cd15d6c251a416..5970e910f212acaa4110ed5d6525da17f6d3999b 100644
--- a/src/main/java/org/olat/ims/qti21/QTI21Service.java
+++ b/src/main/java/org/olat/ims/qti21/QTI21Service.java
@@ -74,7 +74,7 @@ public interface QTI21Service {
 	 */
 	public List<UserTestSession> getUserTestSessions(RepositoryEntryRef courseEntry, String subIdent, IdentityRef identity);
 	
-	public void recordTestAssessmentResult(UserTestSession candidateSession, AssessmentResult assessmentResult);
+	public UserTestSession recordTestAssessmentResult(UserTestSession candidateSession, AssessmentResult assessmentResult);
 	
 	public UserTestSession finishTestSession(UserTestSession candidateSession, AssessmentResult assessmentResul, Date timestamp);
 	
diff --git a/src/main/java/org/olat/ims/qti21/QTI21StatisticsManager.java b/src/main/java/org/olat/ims/qti21/QTI21StatisticsManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..2cdcb128ce4c3121852cb350a09c01228fb19682
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/QTI21StatisticsManager.java
@@ -0,0 +1,56 @@
+/**
+ * OLAT - Online Learning and Training<br>
+ * http://www.olat.org
+ * <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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <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>
+ * Copyright (c) frentix GmbH<br>
+ * http://www.frentix.com<br>
+ * <p>
+ */
+package org.olat.ims.qti21;
+
+import org.olat.ims.qti.statistics.model.StatisticAssessment;
+import org.olat.ims.qti21.model.QTI21StatisticSearchParams;
+
+/**
+ * 
+ * Initial date: 24.07.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public interface QTI21StatisticsManager {
+
+	/*
+	 * minimal number of results we need for a test, or for a question..
+	 * 
+	 * (if number of participants in test is smaller, don't show test) (if
+	 * results for a specific question is smaller, don't display question)
+	 */
+	public static final int MIN_RESULTS_TEST = 2;
+	public static final int MIN_RESULTS_QUESTION = 1;
+	
+
+	public static final int AVG_NUM_OF_SCORE_BUCKETS = 10;
+
+	/**
+	 * Return the statistics of a test in a course
+	 * @param courseResID
+	 * @param resSubPath
+	 * @return
+	 */
+	public StatisticAssessment getAssessmentStatistics(QTI21StatisticSearchParams searchParams);
+	
+	
+
+}
diff --git a/src/main/java/org/olat/ims/qti21/UserTestSession.java b/src/main/java/org/olat/ims/qti21/UserTestSession.java
index 68d44b072c0dc0e3507b57a9e5c36843351177f7..39cac51deec2060db987b54c472db168dcd44d6c 100644
--- a/src/main/java/org/olat/ims/qti21/UserTestSession.java
+++ b/src/main/java/org/olat/ims/qti21/UserTestSession.java
@@ -19,6 +19,7 @@
  */
 package org.olat.ims.qti21;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 import org.olat.core.id.CreateInfo;
@@ -42,6 +43,14 @@ public interface UserTestSession extends CreateInfo, ModifiedInfo {
 	
 	public void setTerminationTime(Date timestamp);
 	
+	public Boolean getPassed();
+
+	public void setPassed(Boolean passed);
+
+	public BigDecimal getScore();
+
+	public void setScore(BigDecimal score);
+	
 	public boolean isExploded();
 	
 	public String getStorage();
diff --git a/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java b/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java
index 52145ee18e7b494b43c99b52ebafa526f5d05aca..b1a4741ab921affbd648d4eb38d34e0dcec08436 100644
--- a/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java
+++ b/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java
@@ -23,6 +23,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.math.BigDecimal;
 import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -45,6 +46,7 @@ import org.olat.core.logging.Tracing;
 import org.olat.core.util.FileUtils;
 import org.olat.fileresource.types.ImsQTI21Resource;
 import org.olat.fileresource.types.ImsQTI21Resource.PathResourceLocator;
+import org.olat.ims.qti21.QTI21Constants;
 import org.olat.ims.qti21.QTI21ContentPackage;
 import org.olat.ims.qti21.QTI21Module;
 import org.olat.ims.qti21.QTI21Service;
@@ -80,6 +82,9 @@ import uk.ac.ed.ph.jqtiplus.state.TestPlanNodeKey;
 import uk.ac.ed.ph.jqtiplus.state.TestSessionState;
 import uk.ac.ed.ph.jqtiplus.state.marshalling.ItemSessionStateXmlMarshaller;
 import uk.ac.ed.ph.jqtiplus.state.marshalling.TestSessionStateXmlMarshaller;
+import uk.ac.ed.ph.jqtiplus.types.Identifier;
+import uk.ac.ed.ph.jqtiplus.value.BooleanValue;
+import uk.ac.ed.ph.jqtiplus.value.NumberValue;
 import uk.ac.ed.ph.jqtiplus.value.RecordValue;
 import uk.ac.ed.ph.jqtiplus.value.SingleValue;
 import uk.ac.ed.ph.jqtiplus.value.Value;
@@ -222,12 +227,13 @@ public class QTI21ServiceImpl implements QTI21Service {
 	}
 
 	@Override
-	public void recordTestAssessmentResult(UserTestSession candidateSession, AssessmentResult assessmentResult) {
+	public UserTestSession recordTestAssessmentResult(UserTestSession candidateSession, AssessmentResult assessmentResult) {
 		// First record full result XML to filesystem
         storeAssessmentResultFile(candidateSession, assessmentResult);
 
         // Then record test outcome variables to DB
         recordOutcomeVariables(candidateSession, assessmentResult.getTestResult());
+        return testSessionDao.update(candidateSession);
 	}
 
 	@Override
@@ -247,9 +253,25 @@ public class QTI21ServiceImpl implements QTI21Service {
 	
     private void recordOutcomeVariables(UserTestSession candidateSession, AbstractResult resultNode) {
         for (final ItemVariable itemVariable : resultNode.getItemVariables()) {
-            if (itemVariable instanceof OutcomeVariable
-                    || QtiConstants.VARIABLE_DURATION_IDENTIFIER.equals(itemVariable.getIdentifier())) {
-                log.audit(candidateSession.getKey() + " :: " + itemVariable.getIdentifier() + " - " + stringifyQtiValue(itemVariable.getComputedValue()));
+            if (itemVariable instanceof OutcomeVariable) {
+                
+                OutcomeVariable outcomeVariable = (OutcomeVariable)itemVariable;
+            	Identifier identifier = outcomeVariable.getIdentifier();
+            	if(QtiConstants.VARIABLE_DURATION_IDENTIFIER.equals(identifier)) {
+            		log.audit(candidateSession.getKey() + " :: " + itemVariable.getIdentifier() + " - " + stringifyQtiValue(itemVariable.getComputedValue()));
+            	} else  if(QTI21Constants.SCORE_IDENTIFIER.equals(identifier)) {
+            		Value value = itemVariable.getComputedValue();
+            		if(value instanceof NumberValue) {
+            			double score = ((NumberValue)value).doubleValue();
+            			candidateSession.setScore(new BigDecimal(Double.toString(score)));
+            		}
+            	} else if(QTI21Constants.PASS_IDENTIFIER.equals(identifier)) {
+            		Value value = itemVariable.getComputedValue();
+            		if(value instanceof BooleanValue) {
+            			boolean pass = ((BooleanValue)value).booleanValue();
+            			candidateSession.setPassed(pass);
+            		}
+            	}
             }
         }
     }
diff --git a/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..de8f3c2d4a0e01d4e6c0ee5bc452f0a487422b22
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
@@ -0,0 +1,141 @@
+/**
+ * OLAT - Online Learning and Training<br>
+ * http://www.olat.org
+ * <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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <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>
+ * Copyright (c) frentix GmbH<br>
+ * http://www.frentix.com<br>
+ * <p>
+ */
+package org.olat.ims.qti21.manager;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import javax.persistence.TypedQuery;
+
+import org.olat.core.commons.persistence.DB;
+import org.olat.ims.qti.statistics.manager.Statistics;
+import org.olat.ims.qti.statistics.model.StatisticAssessment;
+import org.olat.ims.qti21.QTI21StatisticsManager;
+import org.olat.ims.qti21.model.QTI21StatisticSearchParams;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 
+ * Initial date: 24.07.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class QTI21StatisticsManagerImpl implements QTI21StatisticsManager {
+	
+	@Autowired
+	private DB dbInstance;
+	
+	private StringBuilder decorateRSet(StringBuilder sb, QTI21StatisticSearchParams searchParams) {
+		sb.append(" where asession.repositoryEntry.key=:repositoryEntryKey")
+		  .append(" and asession.lastModified = (select max(a2session.lastModified) from qtiassessmentsession a2session")
+		  .append("   where a2session.identity=asession.identity and a2session.repositoryEntry=asession.repositoryEntry")
+		  .append(" )");
+		
+		if(searchParams.getLimitToGroups() != null && searchParams.getLimitToGroups().size() > 0) {
+			sb.append(" and asession.identity.key in ( select membership.identity.key from bgroupmember membership ")
+			  .append("   where membership.group in (:baseGroups)")
+			  .append(" )");
+		}
+		
+		if(searchParams.isMayViewAllUsersAssessments()) {
+			sb.append(" and asession.identity.key in (select data.identity.key from assessmententry data ")
+			  .append("   where data.repositoryEntry=asession.repositoryEntry")
+			  .append(" )");
+		}
+		return sb;
+	}
+	
+	private void decorateRSetQuery(TypedQuery<?> query, QTI21StatisticSearchParams searchParams) {
+		query.setParameter("repositoryEntryKey", searchParams.getEntry().getKey());
+		if(searchParams.getLimitToGroups() != null && searchParams.getLimitToGroups().size() > 0) {
+			query.setParameter("baseGroups", searchParams.getLimitToGroups());
+		}
+	}
+
+	@Override
+	public StatisticAssessment getAssessmentStatistics(QTI21StatisticSearchParams searchParams) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select asession.score, asession.passed from qtiassessmentsession asession ");
+		decorateRSet(sb, searchParams);
+		sb.append(" order by asession.key asc");
+
+		TypedQuery<Object[]> rawDataQuery = dbInstance.getCurrentEntityManager()
+			.createQuery(sb.toString(), Object[].class);
+		decorateRSetQuery(rawDataQuery, searchParams);
+		List<Object[]> rawDatas =	rawDataQuery.getResultList();
+		
+		int numOfPassed = 0;
+		int numOfFailed = 0;
+		double totalDuration = 0.0;
+		double maxScore = 0.0;
+		double minScore = Double.MAX_VALUE;
+		double[] scores = new double[rawDatas.size()];
+		
+
+		int dataPos = 0;
+		for(Object[] rawData:rawDatas) {
+			Boolean passed = (Boolean)rawData[1];
+			if(passed != null) {
+				if(passed.booleanValue()) {
+					numOfPassed++;
+				} else {
+					numOfFailed++;
+				}
+			}
+			
+			BigDecimal score = (BigDecimal)rawData[0];
+			if(score != null) {
+				double scored = score.doubleValue();
+				scores[dataPos] = scored;
+				maxScore = Math.max(maxScore, scored);
+				minScore = Math.min(minScore, scored);
+			}
+			
+			dataPos++;
+		}
+		if (rawDatas.size() == 0) {
+			minScore = 0;
+		}
+		
+		Statistics statisticsHelper = new Statistics(scores);		
+
+		int numOfParticipants = rawDatas.size();
+		StatisticAssessment stats = new StatisticAssessment();
+		stats.setNumOfParticipants(numOfParticipants);
+		stats.setNumOfPassed(numOfPassed);
+		stats.setNumOfFailed(numOfFailed);
+		long averageDuration = Math.round(totalDuration / numOfParticipants);
+		stats.setAverageDuration(averageDuration);
+		stats.setAverage(statisticsHelper.getMean());
+		double range = maxScore - minScore;
+		stats.setRange(range);
+		stats.setMaxScore(maxScore);
+		stats.setMinScore(minScore);
+		stats.setStandardDeviation(statisticsHelper.getStdDev());
+		stats.setMedian(statisticsHelper.median());
+		stats.setMode(statisticsHelper.mode());
+		stats.setScores(scores);
+		return stats;
+	}
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/model/QTI21StatisticSearchParams.java b/src/main/java/org/olat/ims/qti21/model/QTI21StatisticSearchParams.java
new file mode 100644
index 0000000000000000000000000000000000000000..683ff1e3afcaf8e319e833f1e3f618891d2f9c4f
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/model/QTI21StatisticSearchParams.java
@@ -0,0 +1,63 @@
+/**
+ * <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;
+
+import java.util.List;
+
+import org.olat.basesecurity.Group;
+import org.olat.repository.RepositoryEntry;
+
+/**
+ * 
+ * Initial date: 24.07.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21StatisticSearchParams {
+	
+	private final RepositoryEntry entry;
+
+	private List<Group> limitToGroups;
+	private boolean mayViewAllUsersAssessments;
+	
+	public QTI21StatisticSearchParams(RepositoryEntry entry) {
+		this.entry = entry;
+	}
+
+	public RepositoryEntry getEntry() {
+		return entry;
+	}
+
+	public List<Group> getLimitToGroups() {
+		return limitToGroups;
+	}
+	
+	public void setLimitToGroups(List<Group> limitToGroups) {
+		this.limitToGroups = limitToGroups;
+	}
+	
+	public boolean isMayViewAllUsersAssessments() {
+		return mayViewAllUsersAssessments;
+	}
+	
+	public void setMayViewAllUsersAssessments(boolean mayViewAllUsersAssessments) {
+		this.mayViewAllUsersAssessments = mayViewAllUsersAssessments;
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java b/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java
index 163d4011120c2fbdc367ec6a51c6cfb2b4e83b9b..92284440b412e191098a7907b770efa1d5f99e74 100644
--- a/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java
+++ b/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java
@@ -19,6 +19,7 @@
  */
 package org.olat.ims.qti21.model.jpa;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 import javax.persistence.Column;
@@ -132,6 +133,12 @@ public class UserTestSessionImpl implements UserTestSession, Persistable {
     @Temporal(TemporalType.TIMESTAMP)
     @Column(name="q_termination_time", nullable=true, insertable=true, updatable=true)
     private Date terminationTime;
+    
+    @Column(name="q_passed", nullable=true, insertable=true, updatable=true)
+    private Boolean passed;
+
+    @Column(name="q_score", nullable=true, insertable=true, updatable=true)
+    private BigDecimal score;
 
     /**
      * Flag to indicate if this session blew up while running, either because
@@ -248,6 +255,22 @@ public class UserTestSessionImpl implements UserTestSession, Persistable {
 		this.terminationTime = terminationTime;
 	}
 
+	public Boolean getPassed() {
+		return passed;
+	}
+
+	public void setPassed(Boolean passed) {
+		this.passed = passed;
+	}
+
+	public BigDecimal getScore() {
+		return score;
+	}
+
+	public void setScore(BigDecimal score) {
+		this.score = score;
+	}
+
 	@Override
 	public int hashCode() {
 		return key == null ? -86534687 : key.hashCode();
diff --git a/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java b/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java
index ddab048826701753e9b8a6cfa3574702a1ba8999..6ef22732deb8ba0ea91fea87da981ef9dbcabbe0 100644
--- a/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java
+++ b/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java
@@ -68,6 +68,7 @@ import org.olat.ims.qti21.model.xml.ManifestPackage;
 import org.olat.ims.qti21.model.xml.OnyxToQtiWorksHandler;
 import org.olat.ims.qti21.ui.AssessmentTestDisplayController;
 import org.olat.ims.qti21.ui.InMemoryOutcomesListener;
+import org.olat.ims.qti21.ui.QTI21RuntimeController;
 import org.olat.ims.qti21.ui.editor.AssessmentTestComposerController;
 import org.olat.imscp.xml.manifest.ManifestType;
 import org.olat.repository.RepositoryEntry;
@@ -75,7 +76,6 @@ import org.olat.repository.RepositoryService;
 import org.olat.repository.handlers.EditionSupport;
 import org.olat.repository.handlers.FileHandler;
 import org.olat.repository.model.RepositoryEntrySecurity;
-import org.olat.repository.ui.RepositoryEntryRuntimeController;
 import org.olat.repository.ui.RepositoryEntryRuntimeController.RuntimeControllerCreator;
 import org.olat.resource.OLATResource;
 import org.olat.resource.OLATResourceManager;
@@ -295,7 +295,7 @@ public class QTI21AssessmentTestHandler extends FileHandler {
 	@Override
 	public MainLayoutController createLaunchController(RepositoryEntry re, RepositoryEntrySecurity reSecurity,
 			UserRequest ureq, WindowControl wControl) {
-		return new RepositoryEntryRuntimeController(ureq, wControl, re, reSecurity,
+		return new QTI21RuntimeController(ureq, wControl, re, reSecurity,
 				new RuntimeControllerCreator() {
 					@Override
 					public Controller create(UserRequest uureq, WindowControl wwControl, TooledStackedPanel toolbarPanel,
diff --git a/src/main/java/org/olat/ims/qti21/ui/QTI21RuntimeController.java b/src/main/java/org/olat/ims/qti21/ui/QTI21RuntimeController.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9b13f633216e5bb2c266341717b9227b21ab3e4
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/QTI21RuntimeController.java
@@ -0,0 +1,136 @@
+/**
+ * <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;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.dropdown.Dropdown;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.ims.qti21.ui.statistics.QTI21AssessmentTestStatisticsController;
+import org.olat.modules.assessment.ui.AssessmentOverviewController;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryManagedFlag;
+import org.olat.repository.model.RepositoryEntrySecurity;
+import org.olat.repository.ui.RepositoryEntryRuntimeController;
+import org.olat.util.logging.activity.LoggingResourceable;
+
+/**
+ * 
+ * Initial date: 23.07.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21RuntimeController extends RepositoryEntryRuntimeController  {
+	
+	private Link assessmentLink, testStatisticLink;
+	
+	private AssessmentOverviewController assessmentToolCtrl;
+	private QTI21AssessmentTestStatisticsController statsToolCtr;
+
+	
+	public QTI21RuntimeController(UserRequest ureq, WindowControl wControl,
+			RepositoryEntry re, RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator) {
+		super(ureq, wControl, re, reSecurity, runtimeControllerCreator);
+	}
+	
+	@Override
+	protected void initRuntimeTools(Dropdown toolsDropdown) {
+		
+		if (reSecurity.isEntryAdmin()) {
+			boolean managed = RepositoryEntryManagedFlag.isManaged(getRepositoryEntry(), RepositoryEntryManagedFlag.editcontent);
+			editLink = LinkFactory.createToolLink("edit.cmd", translate("details.openeditor"), this, "o_sel_repository_editor");
+			editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_edit");
+			editLink.setEnabled(!managed);
+			toolsDropdown.addComponent(editLink);
+			
+			membersLink = LinkFactory.createToolLink("members", translate("details.members"), this, "o_sel_repo_members");
+			membersLink.setIconLeftCSS("o_icon o_icon-fw o_icon_membersmanagement");
+			toolsDropdown.addComponent(membersLink);
+		}
+		
+		if (reSecurity.isEntryAdmin() || reSecurity.isCourseCoach() || reSecurity.isGroupCoach()) {
+			assessmentLink = LinkFactory.createToolLink("assessment", translate("command.openassessment"), this, "o_icon_assessment_tool");
+			assessmentLink.setElementCssClass("o_sel_course_assessment_tool");
+			toolsDropdown.addComponent(assessmentLink);
+
+			testStatisticLink = LinkFactory.createToolLink("qtistatistic", translate("command.openteststatistic"), this, "o_icon_statistics_tool");
+			toolsDropdown.addComponent(testStatisticLink);
+		}
+		
+		if (reSecurity.isEntryAdmin()) {
+			RepositoryEntry re = getRepositoryEntry();
+			ordersLink = LinkFactory.createToolLink("bookings", translate("details.orders"), this, "o_sel_repo_booking");
+			ordersLink.setIconLeftCSS("o_icon o_icon-fw o_icon_booking");
+			boolean booking = acService.isResourceAccessControled(re.getOlatResource(), null);
+			ordersLink.setEnabled(booking);
+			toolsDropdown.addComponent(ordersLink);	
+		}
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if(testStatisticLink == source) {
+			doAssessmentTestStatistics(ureq);
+		} else if(assessmentLink == source) {
+			doAssessmentTool(ureq);
+		} 
+		super.event(ureq, source, event);
+	}
+	
+	private Activateable2 doAssessmentTestStatistics(UserRequest ureq) {
+		OLATResourceable ores = OresHelper.createOLATResourceableType("TestStatistics");
+		ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
+		WindowControl swControl = addToHistory(ureq, ores, null);
+		
+		if (reSecurity.isEntryAdmin() || reSecurity.isCourseCoach() || reSecurity.isGroupCoach()) {
+			QTI21AssessmentTestStatisticsController ctrl = new QTI21AssessmentTestStatisticsController(ureq, swControl, getRepositoryEntry(), false);
+			listenTo(ctrl);
+			statsToolCtr = pushController(ureq, "Statistics", ctrl);
+			currentToolCtr = statsToolCtr;
+			setActiveTool(testStatisticLink);
+			return statsToolCtr;
+		}
+		return null;
+	}
+	
+	private Activateable2 doAssessmentTool(UserRequest ureq) {
+		OLATResourceable ores = OresHelper.createOLATResourceableType("TestStatistics");
+		ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
+		WindowControl swControl = addToHistory(ureq, ores, null);
+		
+		if (reSecurity.isEntryAdmin() || reSecurity.isCourseCoach() || reSecurity.isGroupCoach()) {
+			AssessmentOverviewController ctrl = new AssessmentOverviewController(ureq, swControl, toolbarPanel,
+					getRepositoryEntry(), null);
+			listenTo(ctrl);
+			assessmentToolCtrl = pushController(ureq, "Statistics", ctrl);
+			currentToolCtr = assessmentToolCtrl;
+			setActiveTool(assessmentLink);
+			return assessmentToolCtrl;
+		}
+		return null;
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties
index c56716958f85247f5fa2fd7f8e9684f02af6588b..73e18748b9f7921bd3fc566999693a8691c848be 100644
--- a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties
@@ -3,6 +3,8 @@ form.metadata.title=Title
 assessment.test.config=&lt;assessmentTest&gt; Konfiguration
 assessment.testpart.config=&lt;testPart&gt; Konfiguration
 assessment.section.config=&lt;assessmentSection&gt; Konfiguration
+command.openassessment=Bewertungswerkzeug
+command.openteststatistic=Test statistics
 item.session.control.allow.comment=Kommentar erlauben
 serialize=Serialize
 serialize.error=Unerwarte Fehler während Speicherung von Datei
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties
index 7aa187ce5f70426a547dcd06389300ba5248e59e..8c3354023743f0f895c1671561617a32bdf04ee5 100644
--- a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties
@@ -1,2 +1,4 @@
 #Sat Jan 22 17:01:28 CET 2011
-serialize=Serialize
\ No newline at end of file
+serialize=Serialize
+command.openassessment=Assessment tool
+command.openteststatistic=Test statistics
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/QTI21AssessmentTestStatisticsController.java b/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21AssessmentTestStatisticsController.java
similarity index 73%
rename from src/main/java/org/olat/ims/qti21/statistics/ui/QTI21AssessmentTestStatisticsController.java
rename to src/main/java/org/olat/ims/qti21/ui/statistics/QTI21AssessmentTestStatisticsController.java
index ea39aa70f509bfd0ab00665520e1902d94cfac78..bf10065b8d910807aea57e831df87d3e2caea0e5 100644
--- a/src/main/java/org/olat/ims/qti21/statistics/ui/QTI21AssessmentTestStatisticsController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/statistics/QTI21AssessmentTestStatisticsController.java
@@ -17,12 +17,14 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.ims.qti21.statistics.ui;
+package org.olat.ims.qti21.ui.statistics;
 
 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.List;
+
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.chart.BarSeries;
@@ -31,25 +33,32 @@ import org.olat.core.gui.components.velocity.VelocityContainer;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.id.context.StateEntry;
 import org.olat.ims.qti.statistics.QTIStatisticResourceResult;
+import org.olat.ims.qti.statistics.QTIType;
 import org.olat.ims.qti.statistics.model.StatisticAssessment;
+import org.olat.ims.qti21.QTI21StatisticsManager;
+import org.olat.ims.qti21.model.QTI21StatisticSearchParams;
+import org.olat.repository.RepositoryEntry;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class QTI21AssessmentTestStatisticsController extends BasicController {
+public class QTI21AssessmentTestStatisticsController extends BasicController implements Activateable2 {
 	
 	private final VelocityContainer mainVC;
 	
-	private final QTIStatisticResourceResult resourceResult;
+	@Autowired
+	private QTI21StatisticsManager statisticsManager;
 
 	public QTI21AssessmentTestStatisticsController(UserRequest ureq, WindowControl wControl,
 			QTIStatisticResourceResult resourceResult, boolean printMode) {
 		super(ureq, wControl);
-		
-		this.resourceResult = resourceResult;
 
 		mainVC = createVelocityContainer("statistics_assessment_test");
 		mainVC.put("loadd3js", new StatisticsComponent("d3loader"));
@@ -62,6 +71,22 @@ public class QTI21AssessmentTestStatisticsController extends BasicController {
 		initCourseNodeInformation(stats);
 	}
 	
+	public QTI21AssessmentTestStatisticsController(UserRequest ureq, WindowControl wControl,
+			RepositoryEntry entry, boolean printMode) {
+		super(ureq, wControl);
+
+		mainVC = createVelocityContainer("statistics_assessment_test");
+		mainVC.put("loadd3js", new StatisticsComponent("d3loader"));
+		mainVC.contextPut("printMode", new Boolean(printMode));
+		putInitialPanel(mainVC);
+		
+		QTI21StatisticSearchParams searchParams = new QTI21StatisticSearchParams(entry);
+		StatisticAssessment stats = statisticsManager.getAssessmentStatistics(searchParams);
+		initScoreHistogram(stats);
+		//initDurationHistogram(stats);
+		initCourseNodeInformation(stats);
+	}
+	
 	@Override
 	protected void doDispose() {
 		//
@@ -70,7 +95,7 @@ public class QTI21AssessmentTestStatisticsController extends BasicController {
 	private void initCourseNodeInformation(StatisticAssessment stats) {
 		mainVC.contextPut("numOfParticipants", stats.getNumOfParticipants());
 	
-		mainVC.contextPut("type", resourceResult.getType());
+		mainVC.contextPut("type", QTIType.qtiworks);
 		mainVC.contextPut("numOfPassed", stats.getNumOfPassed());
 		mainVC.contextPut("numOfFailed", stats.getNumOfFailed());
 
@@ -98,6 +123,11 @@ public class QTI21AssessmentTestStatisticsController extends BasicController {
 		mainVC.put("durationHistogram", durationHistogramVC);
 	}
 	
+	@Override
+	public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
+		//
+	}
+
 	@Override
 	protected void event(UserRequest ureq, Component source, Event event) {
 		//
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_duration.html b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/histogram_duration.html
similarity index 100%
rename from src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_duration.html
rename to src/main/java/org/olat/ims/qti21/ui/statistics/_content/histogram_duration.html
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_score.html b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/histogram_score.html
similarity index 100%
rename from src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_score.html
rename to src/main/java/org/olat/ims/qti21/ui/statistics/_content/histogram_score.html
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_content/statistics_assessment_test.html b/src/main/java/org/olat/ims/qti21/ui/statistics/_content/statistics_assessment_test.html
similarity index 100%
rename from src/main/java/org/olat/ims/qti21/statistics/ui/_content/statistics_assessment_test.html
rename to src/main/java/org/olat/ims/qti21/ui/statistics/_content/statistics_assessment_test.html
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_de.properties
similarity index 100%
rename from src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_de.properties
rename to src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_de.properties
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_en.properties
similarity index 100%
rename from src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_en.properties
rename to src/main/java/org/olat/ims/qti21/ui/statistics/_i18n/LocalStrings_en.properties
diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java
index ea26650e4e97fab98c219ff235931281c7bf93a9..b39b3ab6a20c0b968d97b48c62be241a1199be21 100644
--- a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java
+++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java
@@ -103,7 +103,7 @@ public class AssessmentEntryDAO {
 		if(referenceSoftKey != null) {
 			sb.append(" and referenceEntry.softkey=:softkey");
 		} else {
-			sb.append(" and referenceEntry.softkey is null");
+			sb.append(" and data.referenceEntry is null");
 		}
 
 		TypedQuery<AssessmentEntry> query = dbInstance.getCurrentEntityManager()
diff --git a/src/main/java/org/olat/modules/assessment/ui/AssessedIdentityListController.java b/src/main/java/org/olat/modules/assessment/ui/AssessedIdentityListController.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fcb010329971c30b53d595062a2a43fa0cb84f1
--- /dev/null
+++ b/src/main/java/org/olat/modules/assessment/ui/AssessedIdentityListController.java
@@ -0,0 +1,279 @@
+/**
+ * <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.modules.assessment.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.basesecurity.BaseSecurityModule;
+import org.olat.core.commons.persistence.SortKey;
+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.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+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.elements.table.DefaultFlexiColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnDef;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel;
+import org.olat.core.gui.components.stack.TooledStackedPanel;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.id.Identity;
+import org.olat.core.util.Util;
+import org.olat.core.util.coordinate.CoordinatorManager;
+import org.olat.core.util.event.GenericEventListener;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
+import org.olat.course.assessment.AssessedIdentitiesTableDataModel;
+import org.olat.course.assessment.AssessmentMainController;
+import org.olat.course.assessment.AssessmentToolManager;
+import org.olat.course.assessment.IAssessmentCallback;
+import org.olat.course.assessment.IdentityAssessmentEditController;
+import org.olat.course.assessment.model.SearchAssessedIdentityParams;
+import org.olat.course.certificate.CertificateEvent;
+import org.olat.course.certificate.CertificateLight;
+import org.olat.course.certificate.CertificatesManager;
+import org.olat.course.certificate.ui.DownloadCertificateCellRenderer;
+import org.olat.repository.RepositoryEntry;
+import org.olat.user.UserManager;
+import org.olat.user.propertyhandlers.UserPropertyHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 21.07.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessedIdentityListController extends FormBasicController implements GenericEventListener {
+	
+	public static final int USER_PROPS_OFFSET = 500;
+	public static final String usageIdentifyer = AssessedIdentitiesTableDataModel.usageIdentifyer;
+
+	private FlexiTableElement tableEl;
+	private AssessedUserTableModel usersTableModel;
+	private final List<UserPropertyHandler> userPropertyHandlers;
+	private final TooledStackedPanel stackPanel;
+
+	private RepositoryEntry entry;
+	private final boolean isAdministrativeUser;
+	private final IAssessmentCallback assessmentCallback;
+	
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
+	private BaseSecurityModule securityModule;
+	@Autowired
+	private CertificatesManager certificatesManager;
+	@Autowired
+	private AssessmentToolManager assessmentToolManager;
+
+	
+	public AssessedIdentityListController(UserRequest ureq, WindowControl wControl,
+			TooledStackedPanel stackPanel, RepositoryEntry entry, IAssessmentCallback assessmentCallback) {
+		super(ureq, wControl, "identities");
+		setTranslator(Util.createPackageTranslator(AssessmentMainController.class, getLocale(), getTranslator()));
+		setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
+
+		this.stackPanel = stackPanel;
+		this.entry = entry;
+		this.assessmentCallback = assessmentCallback;
+		isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
+		userPropertyHandlers = UserManager.getInstance().getUserPropertyHandlersFor(usageIdentifyer, isAdministrativeUser);
+		
+		initForm(ureq);
+		updateModel();
+		
+		// Register for assessment changed events
+		CoordinatorManager.getInstance().getCoordinator().getEventBus()
+				.registerFor(this, getIdentity(), CertificatesManager.ORES_CERTIFICATE_EVENT);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		//add the table
+		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(UserCols.username, "select"));
+		
+		int colIndex = USER_PROPS_OFFSET;
+		for (int i = 0; i < userPropertyHandlers.size(); i++) {
+			UserPropertyHandler userPropertyHandler	= userPropertyHandlers.get(i);
+			boolean visible = UserManager.getInstance().isMandatoryUserProperty(usageIdentifyer , userPropertyHandler);
+			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex++, "select", false, null));
+		}
+		
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(UserCols.certificate, new DownloadCertificateCellRenderer()));
+
+		usersTableModel = new AssessedUserTableModel(columnsModel); 
+		tableEl = uifactory.addTableElement(getWindowControl(), "identities", usersTableModel, getTranslator(), formLayout);
+		tableEl.setExportEnabled(true);
+	}
+	
+	private void updateModel() {
+		SearchAssessedIdentityParams params = new SearchAssessedIdentityParams(entry);
+		params.setWithCertificates(true);
+		List<Identity> assessedIdentities = assessmentToolManager.getAssessedIdentities(params);
+		List<AssessedIdentityRow> rows = new ArrayList<>(assessedIdentities.size());
+		for(Identity assessedIdentity:assessedIdentities) {
+			rows.add(new AssessedIdentityRow(assessedIdentity, userPropertyHandlers, getLocale()));
+		}
+		usersTableModel.setObjects(rows);
+		
+		ConcurrentMap<Long, CertificateLight> certificates =  new ConcurrentHashMap<>();
+		List<CertificateLight> certificateList = certificatesManager.getLastCertificates(entry.getOlatResource());
+		for(CertificateLight certificate:certificateList) {
+			CertificateLight currentCertificate = certificates.get(certificate.getIdentityKey());
+			if(currentCertificate == null || currentCertificate.getCreationDate().before(certificate.getCreationDate())) {
+				certificates.put(certificate.getIdentityKey(), certificate);
+			}
+		}
+		usersTableModel.setCertificates(certificates);
+	}
+	
+	private void updateCertificate(Long certificateKey) {
+		CertificateLight certificate = certificatesManager.getCertificateLightById(certificateKey);
+		usersTableModel.putCertificate(certificate);
+		tableEl.getComponent().setDirty(true);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	public void event(Event event) {
+		if(event instanceof CertificateEvent) {
+			CertificateEvent ce = (CertificateEvent)event;
+			if(entry.getOlatResource().getKey().equals(ce.getResourceKey())) {
+				updateCertificate(ce.getCertificateKey());
+			}
+		}
+	}
+	
+	@Override
+	protected void formOK(UserRequest ureq) {
+		//
+	}
+	
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(tableEl == source) {
+			if(event instanceof SelectionEvent) {
+				SelectionEvent se = (SelectionEvent)event;
+				String cmd = se.getCommand();
+				AssessedIdentityRow selectedRow = usersTableModel.getObject(se.getIndex());
+				if("select".equals(cmd)) {
+					doSelectUser(ureq, selectedRow);
+				}
+			}
+		} else if(source instanceof FormLink) {
+			FormLink link = (FormLink)source;
+			if("download-cert".equals(link.getCmd())) {
+				
+			}
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+	
+	private void doSelectUser(UserRequest ureq, AssessedIdentityRow row) {
+		ICourse course = CourseFactory.loadCourse(entry.getOlatResource());
+		Identity assessedIdentity = securityManager.loadIdentityByKey(row.getIdentityKey());
+		IdentityAssessmentEditController userController = new IdentityAssessmentEditController(getWindowControl(), ureq,
+				stackPanel, assessedIdentity, course, true, false, true);
+		listenTo(userController);
+		String fullname = userManager.getUserDisplayName(assessedIdentity);
+		stackPanel.pushController(fullname, userController);
+	}
+
+	public static class AssessedUserTableModel extends DefaultFlexiTableDataModel<AssessedIdentityRow> implements SortableFlexiTableDataModel<AssessedIdentityRow> {
+
+		private ConcurrentMap<Long, CertificateLight> certificates;
+
+		public AssessedUserTableModel(FlexiTableColumnModel columnModel) {
+			super(columnModel);
+		}
+		
+		public void setCertificates(ConcurrentMap<Long, CertificateLight> certificates) {
+			this.certificates = certificates;
+		}
+		
+		public void putCertificate(CertificateLight certificate) {
+			if(certificates != null) {
+				certificates.put(certificate.getIdentityKey(), certificate);
+			}
+		}
+		
+		@Override
+		public void sort(SortKey sortKey) {
+			//
+		}
+		
+		@Override
+		public Object getValueAt(int row, int col) {
+			AssessedIdentityRow identityRow = getObject(row);
+			return getValueAt(identityRow, col);
+		}
+
+		@Override
+		public Object getValueAt(AssessedIdentityRow row, int col) {
+			if(col >= 0 && col < UserCols.values().length) {
+				switch(UserCols.values()[col]) {
+					case username: return row.getIdentityName();
+					case certificate: return certificates.get(row.getIdentityKey());
+				}
+			}
+			int propPos = col - USER_PROPS_OFFSET;
+			return row.getIdentityProp(propPos);
+		}
+
+		@Override
+		public DefaultFlexiTableDataModel<AssessedIdentityRow> createCopyWithEmptyList() {
+			return new AssessedUserTableModel(getTableColumnModel());
+		}
+	}
+
+	public enum UserCols implements FlexiColumnDef {
+		username("table.header.name"),
+		certificate("table.header.certificate");
+		
+		private final String i18nKey;
+		
+		private UserCols(String i18nKey) {
+			this.i18nKey = i18nKey;
+		}
+		
+		public String i18nHeaderKey() {
+			return i18nKey;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/modules/assessment/ui/AssessedIdentityRow.java b/src/main/java/org/olat/modules/assessment/ui/AssessedIdentityRow.java
new file mode 100644
index 0000000000000000000000000000000000000000..58661ada047c8823891bea2c1efd5c65d063bb7c
--- /dev/null
+++ b/src/main/java/org/olat/modules/assessment/ui/AssessedIdentityRow.java
@@ -0,0 +1,44 @@
+/**
+ * <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.modules.assessment.ui;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.olat.core.id.Identity;
+import org.olat.user.UserPropertiesRow;
+import org.olat.user.propertyhandlers.UserPropertyHandler;
+
+/**
+ * 
+ * Initial date: 21.07.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessedIdentityRow extends UserPropertiesRow {
+	
+	
+	public AssessedIdentityRow(Identity identity, List<UserPropertyHandler> userPropertyHandlers, Locale locale) {
+		super(identity, userPropertyHandlers, locale);
+	}
+
+
+
+}
diff --git a/src/main/java/org/olat/modules/assessment/ui/AssessmentOverviewController.java b/src/main/java/org/olat/modules/assessment/ui/AssessmentOverviewController.java
new file mode 100644
index 0000000000000000000000000000000000000000..17ebf1ef3270fc0fccc48b614220229a2a0293bf
--- /dev/null
+++ b/src/main/java/org/olat/modules/assessment/ui/AssessmentOverviewController.java
@@ -0,0 +1,143 @@
+/**
+ * <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.modules.assessment.ui;
+
+import java.util.List;
+
+import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.panel.Panel;
+import org.olat.core.gui.components.stack.TooledStackedPanel;
+import org.olat.core.gui.components.tree.GenericTreeModel;
+import org.olat.core.gui.components.tree.GenericTreeNode;
+import org.olat.core.gui.components.tree.MenuTree;
+import org.olat.core.gui.components.tree.TreeModel;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.MainLayoutBasicController;
+import org.olat.core.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.id.context.StateEntry;
+import org.olat.core.util.Util;
+import org.olat.course.assessment.AssessmentMainController;
+import org.olat.course.assessment.IAssessmentCallback;
+import org.olat.repository.RepositoryEntry;
+
+/**
+ * 
+ * Initial date: 21.07.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentOverviewController extends MainLayoutBasicController implements Activateable2 {
+	
+	private MenuTree menuTree;
+	private final Panel mainPanel;
+	private TooledStackedPanel stackPanel;
+	
+	private RepositoryEntry entry;
+	private IAssessmentCallback assessmentCallback;
+	
+	public AssessmentOverviewController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
+			RepositoryEntry entry, IAssessmentCallback assessmentCallback) {
+		super(ureq, wControl);
+		setTranslator(Util.createPackageTranslator(AssessmentMainController.class, getLocale(), getTranslator()));
+		this.entry = entry;
+		this.stackPanel = stackPanel;
+		this.assessmentCallback = assessmentCallback;
+
+		mainPanel = new Panel("assessmentToolv2");
+		
+		// Navigation menu
+		menuTree = new MenuTree("menuTree");
+		TreeModel tm = buildTreeModel();
+		menuTree.setTreeModel(tm);
+		menuTree.setSelectedNodeId(tm.getRootNode().getIdent());
+		menuTree.addListener(this);
+
+		LayoutMain3ColsController columLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), menuTree, mainPanel, "course" + entry.getResourceableId());
+		listenTo(columLayoutCtr); // cleanup on dispose
+		putInitialPanel(columLayoutCtr.getInitialComponent());
+	}
+	
+	private TreeModel buildTreeModel() {
+		GenericTreeNode root, gtn;
+
+		GenericTreeModel gtm = new GenericTreeModel();
+		root = new GenericTreeNode();
+		root.setTitle(translate("menu.index"));
+		root.setUserObject("index");
+		root.setAltText(translate("menu.index.alt"));
+		gtm.setRootNode(root);
+
+		gtn = new GenericTreeNode();
+		gtn.setTitle(translate("menu.userfocus"));
+		gtn.setUserObject("users");
+		gtn.setAltText(translate("menu.userfocus.alt"));
+		gtn.setCssClass("o_sel_assessment_tool_users");
+		root.addChild(gtn);
+
+		return gtm;
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
+		//
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if (source == menuTree) {
+			if (event.getCommand().equals(MenuTree.COMMAND_TREENODE_CLICKED)) {
+				Object uo = menuTree.getSelectedNode().getUserObject();
+				if("groups".equals(uo)) {
+					doSelectGroupView();
+				} else if("courseNodes".equals(uo)) {
+					doSelectCourseNodesView();
+				} else if("users".equals(uo)) {
+					doSelectUsersView(ureq);
+				}
+			}
+		}
+	}
+	
+	private void doSelectGroupView() {
+		
+	}
+
+	private void doSelectCourseNodesView() {
+		
+	}
+	
+	private void doSelectUsersView(UserRequest ureq) {
+		AssessedIdentityListController listController = new AssessedIdentityListController(ureq, getWindowControl(), stackPanel,
+				entry, assessmentCallback);
+		listenTo(listController);
+		mainPanel.setContent(listController.getInitialComponent());
+	}
+	
+
+}
diff --git a/src/main/java/org/olat/modules/assessment/ui/_content/identities.html b/src/main/java/org/olat/modules/assessment/ui/_content/identities.html
new file mode 100644
index 0000000000000000000000000000000000000000..42a472edfd4b53b23f921ce1e1734d813c08e393
--- /dev/null
+++ b/src/main/java/org/olat/modules/assessment/ui/_content/identities.html
@@ -0,0 +1 @@
+$r.render("identities")
\ No newline at end of file
diff --git a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java
index dbf051d677ecf40307ecf058841aea7f54b82d6b..2d8de3e06376d2121a5233cc7af806a4f55565eb 100644
--- a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java
+++ b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java
@@ -288,6 +288,25 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController
 	}
 	
 	protected void initToolbar(Dropdown toolsDropdown, Dropdown settingsDropdown) {
+		initRuntimeTools(toolsDropdown);
+		initSettingsTools(settingsDropdown);
+		initEditionTools(settingsDropdown);
+
+		detailsLink = LinkFactory.createToolLink("details", translate("details.header"), this, "o_sel_repo_details");
+		detailsLink.setIconLeftCSS("o_icon o_icon-fw o_icon_details");
+		detailsLink.setElementCssClass("o_sel_author_details");
+		detailsLink.setVisible(showInfos);
+		toolbarPanel.addTool(detailsLink);
+		
+		boolean marked = markManager.isMarked(re, getIdentity(), null);
+		String css = marked ? Mark.MARK_CSS_ICON : Mark.MARK_ADD_CSS_ICON;
+		bookmarkLink = LinkFactory.createToolLink("bookmark", translate("details.bookmark.label"), this, css);
+		bookmarkLink.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
+		bookmarkLink.setVisible(allowBookmark);
+		toolbarPanel.addTool(bookmarkLink, Align.right);
+	}
+	
+	protected void initRuntimeTools(Dropdown toolsDropdown) {
 		if (reSecurity.isEntryAdmin()) {
 			//tools
 			if(handler.supportsEdit(re.getOlatResource()) == EditionSupport.yes) {
@@ -308,22 +327,6 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController
 			ordersLink.setEnabled(booking);
 			toolsDropdown.addComponent(ordersLink);	
 		}
-		
-		initSettingsTools(settingsDropdown);
-		initEditionTools(settingsDropdown);
-
-		detailsLink = LinkFactory.createToolLink("details", translate("details.header"), this, "o_sel_repo_details");
-		detailsLink.setIconLeftCSS("o_icon o_icon-fw o_icon_details");
-		detailsLink.setElementCssClass("o_sel_author_details");
-		detailsLink.setVisible(showInfos);
-		toolbarPanel.addTool(detailsLink);
-		
-		boolean marked = markManager.isMarked(re, getIdentity(), null);
-		String css = marked ? Mark.MARK_CSS_ICON : Mark.MARK_ADD_CSS_ICON;
-		bookmarkLink = LinkFactory.createToolLink("bookmark", translate("details.bookmark.label"), this, css);
-		bookmarkLink.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
-		bookmarkLink.setVisible(allowBookmark);
-		toolbarPanel.addTool(bookmarkLink, Align.right);
 	}
 	
 	protected void initSettingsTools(Dropdown settingsDropdown) {
diff --git a/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql b/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql
index e53734ee89a5d429f35b9f00227e406ba9110133..b242685640fd1ddbd38c98841f65ab8b53e00cdc 100644
--- a/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql
+++ b/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql
@@ -12,7 +12,7 @@ create table o_as_entry (
    a_coach_comment text,
    fk_entry bigint not null,
    a_subident varchar(64),
-   fk_reference_entry bigint not null,
+   fk_reference_entry bigint,
    fk_identity bigint not null,
    primary key (id),
    unique (fk_identity, fk_entry, a_subident)
@@ -34,6 +34,8 @@ create table o_qti_assessment_session (
    q_author_mode bit not null default 0,
    q_finish_time datetime,
    q_termination_time datetime,
+   q_score float(65,30) default null,
+   q_passed bit default null, 
    q_storage varchar(32),
    fk_reference_entry bigint not null,
    fk_entry bigint,
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index 497e85e3bcfd4bdcbdb4004536da40f62c1a5056..b9b28f6a4a03ed221fd469b19b41f56e70acc2da 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -1078,7 +1078,7 @@ create table o_as_entry (
    a_coach_comment text,
    fk_entry bigint not null,
    a_subident varchar(64),
-   fk_reference_entry bigint not null,
+   fk_reference_entry bigint,
    fk_identity bigint not null,
    primary key (id),
    unique (fk_identity, fk_entry, a_subident)
@@ -1220,6 +1220,8 @@ create table o_qti_assessment_session (
    q_author_mode bit not null default 0,
    q_finish_time datetime,
    q_termination_time datetime,
+   q_score float(65,30) default null,
+   q_passed bit default null, 
    q_storage varchar(32),
    fk_reference_entry bigint not null,
    fk_entry bigint,
diff --git a/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql b/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql
index 6e76bea71363662e1dfb571877ab3f079bde77f2..282cb2c2a1cfc14db8b7ea561efaeaaf6ee959e4 100644
--- a/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql
+++ b/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql
@@ -12,7 +12,7 @@ create table o_as_entry (
    a_coach_comment text,
    fk_entry int8 not null,
    a_subident varchar(64),
-   fk_reference_entry int8 not null,
+   fk_reference_entry int8,
    fk_identity int8 not null,
    primary key (id),
    unique(fk_identity, fk_entry, a_subident)
@@ -36,6 +36,8 @@ create table o_qti_assessment_session (
    q_author_mode bool default false,
    q_finish_time timestamp,
    q_termination_time timestamp,
+   q_score decimal default null,
+   q_passed bool default null,
    q_storage varchar(32),
    fk_reference_entry int8 not null,
    fk_entry int8,
diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql
index edb770723b1162ab77806966b7885e1944ad303c..c02e6d65d047566b7875d56ef4b18ecee45e0185 100644
--- a/src/main/resources/database/postgresql/setupDatabase.sql
+++ b/src/main/resources/database/postgresql/setupDatabase.sql
@@ -1079,7 +1079,7 @@ create table o_as_entry (
    a_coach_comment text,
    fk_entry int8 not null,
    a_subident varchar(64),
-   fk_reference_entry int8 not null,
+   fk_reference_entry int8,
    fk_identity int8 not null,
    primary key (id),
    unique(fk_identity, fk_entry, a_subident)
@@ -1221,6 +1221,8 @@ create table o_qti_assessment_session (
    q_author_mode bool default false,
    q_finish_time timestamp,
    q_termination_time timestamp,
+   q_score decimal default null,
+   q_passed bool default null,
    q_storage varchar(32),
    fk_reference_entry int8 not null,
    fk_entry int8,