diff --git a/src/main/java/org/olat/course/assessment/handler/AssessmentConfig.java b/src/main/java/org/olat/course/assessment/handler/AssessmentConfig.java
index 8394933494bdd76f23b2e22581c0e676421f0145..2f27a419447ddef4a1ab29f14ad7d58dbbdcb874 100644
--- a/src/main/java/org/olat/course/assessment/handler/AssessmentConfig.java
+++ b/src/main/java/org/olat/course/assessment/handler/AssessmentConfig.java
@@ -27,6 +27,12 @@ package org.olat.course.assessment.handler;
  */
 public interface AssessmentConfig {
 	
+	public enum Mode {
+		none,
+		setByNode,
+		evaluated
+	}
+	
 	/**
 	 * Real assessments are in efficiency statements and are shown in the assessment tool.
 	 * 
@@ -75,9 +81,9 @@ public interface AssessmentConfig {
 	public Float getCutValue();
 	
 	/**
-	 * @return True if this course node can produces a completion variable for the learner
+	 * @return if this course node can produces a completion variable for the learner
 	 */
-	public boolean hasCompletion();
+	public Mode getCompletionMode();
 	
 	/**
 	 * @return True if this course node produces an attempts variable for the learner
diff --git a/src/main/java/org/olat/course/assessment/handler/ModuleAssessmentConfig.java b/src/main/java/org/olat/course/assessment/handler/ModuleAssessmentConfig.java
index ce59e6d54cadce324622878f0a88670cf4a1107e..6ad1a4bd68d674747b6dec72fd5991e34fe0c1cc 100644
--- a/src/main/java/org/olat/course/assessment/handler/ModuleAssessmentConfig.java
+++ b/src/main/java/org/olat/course/assessment/handler/ModuleAssessmentConfig.java
@@ -87,8 +87,8 @@ public abstract class ModuleAssessmentConfig implements AssessmentConfig {
 	}
 	
 	@Override
-	public boolean hasCompletion() {
-		return false;
+	public Mode getCompletionMode() {
+		return Mode.none;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/assessment/handler/NonAssessmentConfig.java b/src/main/java/org/olat/course/assessment/handler/NonAssessmentConfig.java
index 4ab29e3fc64244201c3245ed09d84a301c6cbe9e..906b9d792308f0d2aa08259df133ed89eeee8174 100644
--- a/src/main/java/org/olat/course/assessment/handler/NonAssessmentConfig.java
+++ b/src/main/java/org/olat/course/assessment/handler/NonAssessmentConfig.java
@@ -78,8 +78,8 @@ public class NonAssessmentConfig implements AssessmentConfig {
 	}
 
 	@Override
-	public boolean hasCompletion() {
-		return false;
+	public Mode getCompletionMode() {
+		return Mode.none;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentHandlerRegistry.java b/src/main/java/org/olat/course/assessment/manager/AssessmentHandlerRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..60f3de0ec33d81b8afcec89ac3a0f69d7a3a74d2
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/manager/AssessmentHandlerRegistry.java
@@ -0,0 +1,72 @@
+/**
+ * <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.course.assessment.manager;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import org.olat.course.assessment.handler.AssessmentHandler;
+import org.olat.course.assessment.handler.NonAssessmentHandler;
+import org.olat.course.nodes.CourseNode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 
+ * Initial date: 23 Sep 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+class AssessmentHandlerRegistry {
+
+	private static final String NON_ASSESSMENT_TYPE = NonAssessmentHandler.NODE_TYPE;	
+	
+	@Autowired
+	private List<AssessmentHandler> loadedAssessmentHandlers;
+	private Map<String, AssessmentHandler> assessmentHandlers = new HashMap<>();
+	private AssessmentHandler nonAssessmentHandler;
+	
+	@PostConstruct
+	void initProviders() {
+		for (AssessmentHandler handler: loadedAssessmentHandlers) {
+			if (NON_ASSESSMENT_TYPE.equals(handler.acceptCourseNodeType())) {
+				nonAssessmentHandler = handler;
+			} else {
+				assessmentHandlers.put(handler.acceptCourseNodeType(), handler);
+			}
+		}
+	}
+
+	AssessmentHandler getAssessmentHandler(CourseNode courseNode) {
+		AssessmentHandler handler = null;
+		if (courseNode != null) {
+			handler = assessmentHandlers.get(courseNode.getType());
+		}
+		if (handler == null) {
+			handler = nonAssessmentHandler;
+		}
+		return handler;
+	}
+	
+}
diff --git a/src/main/java/org/olat/course/learningpath/LearningPathOnlyAssessmentConfig.java b/src/main/java/org/olat/course/learningpath/LearningPathOnlyAssessmentConfig.java
index 1dbd27a16a2501f3c7d3edf7effeac3de53ae60e..09ebb4a3fafa09d5ec2f4cfdcfadf056581d6f29 100644
--- a/src/main/java/org/olat/course/learningpath/LearningPathOnlyAssessmentConfig.java
+++ b/src/main/java/org/olat/course/learningpath/LearningPathOnlyAssessmentConfig.java
@@ -70,8 +70,8 @@ public class LearningPathOnlyAssessmentConfig implements AssessmentConfig {
 	}
 
 	@Override
-	public boolean hasCompletion() {
-		return false;
+	public Mode getCompletionMode() {
+		return Mode.none;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/basiclti/LTIAssessmentConfig.java b/src/main/java/org/olat/course/nodes/basiclti/LTIAssessmentConfig.java
index 61a0f43b09cf66d61e46fc3da73c156746b23135..95b2d8ff8088ea522a79bad6e6f09891d3d7e2a5 100644
--- a/src/main/java/org/olat/course/nodes/basiclti/LTIAssessmentConfig.java
+++ b/src/main/java/org/olat/course/nodes/basiclti/LTIAssessmentConfig.java
@@ -94,8 +94,8 @@ public class LTIAssessmentConfig implements AssessmentConfig {
 	}
 	
 	@Override
-	public boolean hasCompletion() {
-		return false;
+	public Mode getCompletionMode() {
+		return Mode.none;
 	}
 	
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java b/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
index 588ccecd7bf606f25ea3c487d78a8f44dfa4e97f..23ff75409d8f9554b009911b13e997690b45d367 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
@@ -53,6 +53,7 @@ import org.olat.course.archiver.ScoreAccountingHelper;
 import org.olat.course.assessment.AssessmentHelper;
 import org.olat.course.assessment.CourseAssessmentService;
 import org.olat.course.assessment.handler.AssessmentConfig;
+import org.olat.course.assessment.handler.AssessmentConfig.Mode;
 import org.olat.course.assessment.ui.tool.IdentityListCourseNodeController;
 import org.olat.course.assessment.ui.tool.IdentityListCourseNodeTableModel.IdentityCourseElementCols;
 import org.olat.course.assessment.ui.tool.IdentityListCourseNodeToolsController;
@@ -145,7 +146,7 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 		super.initStatusColumns(columnsModel);
 		IQTESTCourseNode testCourseNode = (IQTESTCourseNode)courseNode;
 		AssessmentConfig assessmentConfig = courseAssessmentService.getAssessmentConfig(courseNode);
-		if(testCourseNode != null && assessmentConfig.hasCompletion()) {
+		if(testCourseNode != null && Mode.setByNode.equals(assessmentConfig.getCompletionMode())) {
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.currentCompletion));
 		}
 		
@@ -374,7 +375,7 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 					(IQTESTCourseNode)courseNode, assessedIdentity, coachCourseEnv);
 		}
 		return  new IdentityListCourseNodeToolsController(ureq, getWindowControl(),
-				(IQTESTCourseNode)courseNode, assessedIdentity, coachCourseEnv);
+				courseNode, assessedIdentity, coachCourseEnv);
 	}
 	
 	private List<Identity> getIdentities() {
diff --git a/src/main/java/org/olat/course/nodes/iq/IQTESTAssessmentConfig.java b/src/main/java/org/olat/course/nodes/iq/IQTESTAssessmentConfig.java
index 82a742134a4239acca1d1ebb0204e596eb70be0b..733a31d2071aacb6bce1a8296fb4d6365880292b 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQTESTAssessmentConfig.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQTESTAssessmentConfig.java
@@ -146,8 +146,10 @@ public class IQTESTAssessmentConfig implements AssessmentConfig {
 	}
 	
 	@Override
-	public boolean hasCompletion() {
-		return IQEditController.CONFIG_VALUE_QTI21.equals(courseNode.getModuleConfiguration().get(IQEditController.CONFIG_KEY_TYPE_QTI));
+	public Mode getCompletionMode() {
+		return IQEditController.CONFIG_VALUE_QTI21.equals(courseNode.getModuleConfiguration().get(IQEditController.CONFIG_KEY_TYPE_QTI))
+				? Mode.setByNode
+				: Mode.none;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/scorm/ScormAssessmentConfig.java b/src/main/java/org/olat/course/nodes/scorm/ScormAssessmentConfig.java
index 8e1df9136432ef65676daaf3fcde6a149a4fc3f3..a55c9f4a35464c15160c91106cefbba4ff81f400 100644
--- a/src/main/java/org/olat/course/nodes/scorm/ScormAssessmentConfig.java
+++ b/src/main/java/org/olat/course/nodes/scorm/ScormAssessmentConfig.java
@@ -86,8 +86,8 @@ public class ScormAssessmentConfig implements AssessmentConfig {
 	}
 	
 	@Override
-	public boolean hasCompletion() {
-		return false;
+	public Mode getCompletionMode() {
+		return Mode.none;
 	}
 	
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/st/assessment/NumberOfNodesCompletionEvaluator.java b/src/main/java/org/olat/course/nodes/st/assessment/NumberOfNodesCompletionEvaluator.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e21359cf325e8297fbb6fefb07516fa8e5ed8cd
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/st/assessment/NumberOfNodesCompletionEvaluator.java
@@ -0,0 +1,110 @@
+/**
+ * <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.course.nodes.st.assessment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.olat.core.util.nodes.INode;
+import org.olat.course.assessment.CourseAssessmentService;
+import org.olat.course.assessment.handler.AssessmentConfig;
+import org.olat.course.assessment.handler.AssessmentConfig.Mode;
+import org.olat.course.config.CourseConfig;
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.run.scoring.AssessmentEvaluation;
+import org.olat.course.run.scoring.CompletionEvaluator;
+import org.olat.course.run.scoring.ScoreAccounting;
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
+import org.olat.modules.assessment.model.AssessmentObligation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 
+ * Initial date: 23 Sep 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+@Component
+public class NumberOfNodesCompletionEvaluator implements CompletionEvaluator {
+	
+	@Autowired
+	private CourseAssessmentService courseAssessmentService;
+	
+	@Override
+	public Double getCompletion(AssessmentEvaluation currentEvaluation, CourseNode courseNode,
+			CourseConfig courseConfig, ScoreAccounting scoreAccounting) {
+		
+		List<CourseNode> children = new ArrayList<>();
+		collectChildren(children, courseNode);
+		
+		int count = 0;
+		double completion = 0.0;
+		for (CourseNode child: children) {
+			AssessmentEvaluation assessmentEvaluation = scoreAccounting.evalCourseNode(child);
+			if (isMandatory(assessmentEvaluation)) {
+				AssessmentConfig assessmentConfig = courseAssessmentService.getAssessmentConfig(child);
+				if (Mode.setByNode.equals(assessmentConfig.getCompletionMode())) {
+					count++;
+					completion += assessmentEvaluation.getCompletion() != null
+							? assessmentEvaluation.getCompletion().doubleValue()
+							: 0.0;
+				} else if (Mode.none.equals(assessmentConfig.getCompletionMode())) {
+					count++;
+					completion += getCompletion(assessmentEvaluation);
+				}
+			}
+		}
+		
+		return count > 0? completion / count: null;
+	}
+
+	private void collectChildren(List<CourseNode> children, CourseNode courseNode) {
+		for (int i = 0; i < courseNode.getChildCount(); i++) {
+			INode child = courseNode.getChildAt(i);
+			if (child instanceof CourseNode) {
+				CourseNode childCourseNode = (CourseNode) child;
+				children.add(childCourseNode);
+				collectChildren(children, childCourseNode);
+			}
+		}
+	}
+
+	private boolean isMandatory(AssessmentEvaluation evaluation) {
+		return evaluation.getObligation() != null && AssessmentObligation.mandatory.equals(evaluation.getObligation());
+	}
+
+	private double getCompletion(AssessmentEvaluation evaluation) {
+		if (evaluation.getFullyAssessed() != null && evaluation.getFullyAssessed().booleanValue()) return 1.0;
+		
+		AssessmentEntryStatus assessmentStatus = evaluation.getAssessmentStatus();
+		if (assessmentStatus == null) return 0.0;
+		
+		switch (assessmentStatus) {
+		case notReady: return 0.0;
+		case notStarted: return 0.0;
+		case inProgress: return 0.5;
+		case inReview: return 0.75;
+		case done: return 1.0;
+		default: return 0.0;
+		}
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentConfig.java b/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentConfig.java
index 54c6840a200f0d4369a679d68c51f7849fa3c515..02e63938ecad9ce05abd6e063d95e7c44f7584dc 100644
--- a/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentConfig.java
+++ b/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentConfig.java
@@ -85,8 +85,8 @@ public class STAssessmentConfig implements AssessmentConfig {
 	}
 
 	@Override
-	public boolean hasCompletion() {
-		return false;
+	public Mode getCompletionMode() {
+		return Mode.evaluated;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java b/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java
index cbe18864dcc61cfc91d8d5812f0f3ed0de26233f..662be236cdae26f074c5e95465890ef17194b5a5 100644
--- a/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java
+++ b/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java
@@ -39,7 +39,6 @@ import org.olat.course.nodes.st.STIdentityListCourseNodeController;
 import org.olat.course.run.scoring.AccountingEvaluators;
 import org.olat.course.run.scoring.AccountingEvaluatorsBuilder;
 import org.olat.course.run.scoring.AssessmentEvaluation;
-import org.olat.course.run.scoring.DurationEvaluator;
 import org.olat.course.run.scoring.FullyAssessedEvaluator;
 import org.olat.course.run.scoring.LastModificationsEvaluator;
 import org.olat.course.run.scoring.PassedEvaluator;
@@ -52,6 +51,7 @@ import org.olat.modules.assessment.AssessmentEntry;
 import org.olat.modules.assessment.ui.AssessmentToolContainer;
 import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
 import org.olat.repository.RepositoryEntry;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -63,9 +63,9 @@ import org.springframework.stereotype.Service;
 @Service
 public class STAssessmentHandler implements AssessmentHandler {
 	
+	private static final CumulatingDurationEvaluator CUMULATION_DURATION_EVALUATOR = new CumulatingDurationEvaluator();
 	private static final ScoreEvaluator CONDITION_SCORE_EVALUATOR = new ConditionScoreEvaluator();
 	private static final PassedEvaluator CONDITION_PASSED_EVALUATOR = new ConditionPassedEvaluator();
-	private static final DurationEvaluator CUMMULATING_DURATION_EVALUATOR = new CumulatingDurationEvaluator();
 	private static final StatusEvaluator SCORE_STATUS_EVALUATOR = new ScoreStatusEvaluator();
 	private static final StatusEvaluator STATUS_LEARNING_PATH_STATUS_EVALUATOR = new STLinearStatusEvaluator();
 	private static final FullyAssessedEvaluator FULLY_ASSESSED_EVALUATOR = new STFullyAssessedEvaluator();
@@ -76,14 +76,9 @@ public class STAssessmentHandler implements AssessmentHandler {
 			.withStatusEvaluator(SCORE_STATUS_EVALUATOR)
 			.withLastModificationsEvaluator(LAST_MODIFICATION_EVALUATOR)
 			.build();
-	private static final AccountingEvaluators LEARNING_PATH_EVALUATORS = AccountingEvaluatorsBuilder.builder()
-			.withDurationEvaluator(CUMMULATING_DURATION_EVALUATOR)
-			.withScoreEvaluator(CONDITION_SCORE_EVALUATOR)
-			.withPassedEvaluator(CONDITION_PASSED_EVALUATOR)
-			.withStatusEvaluator(STATUS_LEARNING_PATH_STATUS_EVALUATOR)
-			.withFullyAssessedEvaluator(FULLY_ASSESSED_EVALUATOR)
-			.withLastModificationsEvaluator(LAST_MODIFICATION_EVALUATOR)
-			.build();
+	
+	@Autowired
+	private NumberOfNodesCompletionEvaluator numberOfNodesCompletionEvaluator;
 	
 	@Override
 	public String acceptCourseNodeType() {
@@ -109,7 +104,15 @@ public class STAssessmentHandler implements AssessmentHandler {
 	@Override
 	public AccountingEvaluators getEvaluators(CourseNode courseNode, NodeAccessType nodeAccessType) {
 		if (LearningPathNodeAccessProvider.TYPE.equals(nodeAccessType.getType())) {
-			return LEARNING_PATH_EVALUATORS;
+			return AccountingEvaluatorsBuilder.builder()
+					.withDurationEvaluator(CUMULATION_DURATION_EVALUATOR)
+					.withScoreEvaluator(CONDITION_SCORE_EVALUATOR)
+					.withPassedEvaluator(CONDITION_PASSED_EVALUATOR)
+					.withCompletionEvaluator(numberOfNodesCompletionEvaluator)
+					.withStatusEvaluator(STATUS_LEARNING_PATH_STATUS_EVALUATOR)
+					.withFullyAssessedEvaluator(FULLY_ASSESSED_EVALUATOR)
+					.withLastModificationsEvaluator(LAST_MODIFICATION_EVALUATOR)
+					.build();
 		}
 		return CONVENTIONAL_EVALUATORS;
 	}
diff --git a/src/main/java/org/olat/course/nodes/survey/SurveyAssessmentConfig.java b/src/main/java/org/olat/course/nodes/survey/SurveyAssessmentConfig.java
index 137aade66101d8328bacf04d7e6b0964edf3dfd1..79f40b503fbd8b1d526ea8be3820d49ead58ad5e 100644
--- a/src/main/java/org/olat/course/nodes/survey/SurveyAssessmentConfig.java
+++ b/src/main/java/org/olat/course/nodes/survey/SurveyAssessmentConfig.java
@@ -30,8 +30,8 @@ import org.olat.course.learningpath.LearningPathOnlyAssessmentConfig;
 public class SurveyAssessmentConfig extends LearningPathOnlyAssessmentConfig {
 
 	@Override
-	public boolean hasCompletion() {
-		return true;
+	public Mode getCompletionMode() {
+		return Mode.setByNode;
 	}
 
 }
diff --git a/src/main/java/org/olat/course/run/scoring/AccountingEvaluators.java b/src/main/java/org/olat/course/run/scoring/AccountingEvaluators.java
index 03e0ff00c0197cd9b8585772a68c7a703ea35747..ff2de92bdb49c9d8f59bbe48bab0c04de67fef7d 100644
--- a/src/main/java/org/olat/course/run/scoring/AccountingEvaluators.java
+++ b/src/main/java/org/olat/course/run/scoring/AccountingEvaluators.java
@@ -37,6 +37,8 @@ public interface AccountingEvaluators {
 
 	public LastModificationsEvaluator getLastModificationsEvaluator();
 
+	public CompletionEvaluator getCompletionEvaluator();
+
 	public StatusEvaluator getStatusEvaluator();
 
 	public FullyAssessedEvaluator getFullyAssessedEvaluator();
diff --git a/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsBuilder.java b/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsBuilder.java
index 0b63a5ac42aaa781625f9d5dd5a534c263130c58..93076e0edc24b48ec87758cf5bf99c6a63bb593a 100644
--- a/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsBuilder.java
+++ b/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsBuilder.java
@@ -32,6 +32,7 @@ public class AccountingEvaluatorsBuilder {
 			.withDurationEvaluator(AccountingEvaluatorsFactory.createNullDurationEvaluator())
 			.withScoreEvaluator(AccountingEvaluatorsFactory.createUnchangingScoreEvaluator())
 			.withPassedEvaluator(AccountingEvaluatorsFactory.createUnchangingPassedEvaluator())
+			.withCompletionEvaluator(AccountingEvaluatorsFactory.createUnchangingCompletionEvaluator())
 			.withStatusEvaluator(AccountingEvaluatorsFactory.createUnchangingStatusEvaluator())
 			.withFullyAssessedEvaluator(AccountingEvaluatorsFactory.createUnchangingFullyAssessedEvaluator())
 			.withLastModificationsEvaluator(AccountingEvaluatorsFactory.createUnchangingLastModificationsEvaluator())
@@ -41,6 +42,7 @@ public class AccountingEvaluatorsBuilder {
 	private DurationEvaluator durationEvaluator;
 	private ScoreEvaluator scoreEvaluator;
 	private PassedEvaluator passedEvaluator;
+	private CompletionEvaluator completionEvaluator;
 	private StatusEvaluator statusEvaluator;
 	private FullyAssessedEvaluator fullyAssessedEvaluator;
 	private LastModificationsEvaluator lastModificationsEvaluator;
@@ -69,6 +71,11 @@ public class AccountingEvaluatorsBuilder {
 		return this;
 	}
 	
+	public AccountingEvaluatorsBuilder withCompletionEvaluator(CompletionEvaluator completionEvaluator) {
+		this.completionEvaluator = completionEvaluator;
+		return this;
+	}
+	
 	public AccountingEvaluatorsBuilder withStatusEvaluator(StatusEvaluator statusEvaluator) {
 		this.statusEvaluator = statusEvaluator;
 		return this;
@@ -98,6 +105,9 @@ public class AccountingEvaluatorsBuilder {
 		impl.passedEvaluator = this.passedEvaluator != null
 				? this.passedEvaluator
 				: AccountingEvaluatorsFactory.createUnchangingPassedEvaluator();
+		impl.completionEvaluator = this.completionEvaluator != null
+				? this.completionEvaluator
+				: AccountingEvaluatorsFactory.createUnchangingCompletionEvaluator();
 		impl.statusEvaluator = this.statusEvaluator != null
 				? this.statusEvaluator
 				: AccountingEvaluatorsFactory.createUnchangingStatusEvaluator();
@@ -124,6 +134,7 @@ public class AccountingEvaluatorsBuilder {
 		private DurationEvaluator durationEvaluator;
 		private ScoreEvaluator scoreEvaluator;
 		private PassedEvaluator passedEvaluator;
+		private CompletionEvaluator completionEvaluator;
 		private StatusEvaluator statusEvaluator;
 		private FullyAssessedEvaluator fullyAssessedEvaluator;
 		private LastModificationsEvaluator lastModificationsEvaluator;
@@ -147,7 +158,12 @@ public class AccountingEvaluatorsBuilder {
 		public PassedEvaluator getPassedEvaluator() {
 			return passedEvaluator;
 		}
-
+		
+		@Override
+		public CompletionEvaluator getCompletionEvaluator() {
+			return completionEvaluator;
+		}
+		
 		@Override
 		public StatusEvaluator getStatusEvaluator() {
 			return statusEvaluator;
@@ -162,7 +178,7 @@ public class AccountingEvaluatorsBuilder {
 		public LastModificationsEvaluator getLastModificationsEvaluator() {
 			return lastModificationsEvaluator;
 		}
-		
+
 	}
 
 }
diff --git a/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsFactory.java b/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsFactory.java
index 6d2173313df9133d302e69396b47f9f70d02f937..25b521f67a06020d1d6496bb129c0fe3af183d53 100644
--- a/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsFactory.java
+++ b/src/main/java/org/olat/course/run/scoring/AccountingEvaluatorsFactory.java
@@ -22,6 +22,7 @@ package org.olat.course.run.scoring;
 import java.util.List;
 
 import org.olat.course.condition.interpreter.ConditionInterpreter;
+import org.olat.course.config.CourseConfig;
 import org.olat.course.nodes.CourseNode;
 import org.olat.modules.assessment.model.AssessmentEntryStatus;
 import org.olat.modules.assessment.model.AssessmentObligation;
@@ -39,6 +40,7 @@ class AccountingEvaluatorsFactory {
 	private static final DurationEvaluator NULL_DURATION_EVALUATOR = new NullDurationEvaluator();
 	private static final ScoreEvaluator UNCHANGING_SCORE_EVALUATOR = new UnchangingScoreEvaluator();
 	private static final PassedEvaluator UNCHANGING_PASSED_EVALUATOR = new UnchangingPassedEvaluator();
+	private static final CompletionEvaluator UNCHANGING_COMPLETION_EVALUATOR = new UnchangingCompletionEvaluator();
 	private static final StatusEvaluator UNCHANGING_STATUS_EVALUATOR = new UnchangingStatusEvaluator();
 	private static final FullyAssessedEvaluator UNCHANGING_FULLY_ASSESSED_EVALUATOR = new UnchangingFullyAssessedEvaluator();
 	private static final LastModificationsEvaluator UNCHANGING_LAST_MODIFICATIONS_EVALUATOR = new UnchangingLastModificationEvaluator();
@@ -58,6 +60,10 @@ class AccountingEvaluatorsFactory {
 		return UNCHANGING_PASSED_EVALUATOR;
 	}
 	
+	public static CompletionEvaluator createUnchangingCompletionEvaluator() {
+		return UNCHANGING_COMPLETION_EVALUATOR;
+	}
+	
 	static StatusEvaluator createUnchangingStatusEvaluator() {
 		return UNCHANGING_STATUS_EVALUATOR;
 	}
@@ -126,6 +132,16 @@ class AccountingEvaluatorsFactory {
 		}
 	}
 	
+	private static class UnchangingCompletionEvaluator implements CompletionEvaluator {
+
+		@Override
+		public Double getCompletion(AssessmentEvaluation currentEvaluation, CourseNode courseNode,
+				CourseConfig courseConfig, ScoreAccounting scoureAccounting) {
+			return currentEvaluation.getCompletion();
+		}
+		
+	}
+	
 	private static class UnchangingStatusEvaluator implements StatusEvaluator {
 
 		@Override
@@ -159,5 +175,5 @@ class AccountingEvaluatorsFactory {
 		}
 		
 	}
-	
+
 }
diff --git a/src/main/java/org/olat/course/run/scoring/AccountingResult.java b/src/main/java/org/olat/course/run/scoring/AccountingResult.java
index df8dacdf488027fcf662f0cdea8d270ac13da698..fba8d9b6f203646d58e1a2bc1422a7faa1a960b0 100644
--- a/src/main/java/org/olat/course/run/scoring/AccountingResult.java
+++ b/src/main/java/org/olat/course/run/scoring/AccountingResult.java
@@ -38,6 +38,7 @@ public class AccountingResult extends AssessmentEvaluation {
 	private AssessmentObligation evaluatedObligation;
 	private Float evaluatedScore;
 	private Boolean evaluatedPassed;
+	private Double evaluatedCompletion;
 	private AssessmentEntryStatus evaluatedStatus;
 	private Boolean evaluatedFullyAssessed;
 	private Date evaluatedLastUserModified;
@@ -50,6 +51,7 @@ public class AccountingResult extends AssessmentEvaluation {
 		this.evaluatedObligation = origin.getObligation();
 		this.evaluatedScore = origin.getScore();
 		this.evaluatedPassed = origin.getPassed();
+		this.evaluatedCompletion = origin.getCompletion();
 		this.evaluatedStatus = origin.getAssessmentStatus();
 		this.evaluatedFullyAssessed = origin.getFullyAssessed();
 		this.evaluatedLastUserModified = origin.getLastUserModified();
@@ -92,6 +94,15 @@ public class AccountingResult extends AssessmentEvaluation {
 		this.evaluatedPassed = passed;
 	}
 
+	@Override
+	public Double getCompletion() {
+		return evaluatedCompletion;
+	}
+
+	public void setCompletion(Double completion) {
+		this.evaluatedCompletion = completion;
+	}
+
 	@Override
 	public AssessmentEntryStatus getAssessmentStatus() {
 		return evaluatedStatus;
@@ -136,6 +147,7 @@ public class AccountingResult extends AssessmentEvaluation {
 				|| !Objects.equals(origin.getFullyAssessed(), evaluatedFullyAssessed)
 				|| !Objects.equals(origin.getLastUserModified(), evaluatedLastUserModified)
 				|| !Objects.equals(origin.getLastCoachModified(), evaluatedLastCoachModified)
+				|| !Objects.equals(origin.getCompletion(), evaluatedCompletion)
 				|| !Objects.equals(origin.getAssessmentStatus(), evaluatedStatus);
 	}
 
diff --git a/src/main/java/org/olat/course/run/scoring/AssessmentAccounting.java b/src/main/java/org/olat/course/run/scoring/AssessmentAccounting.java
index 4337bc690fddd746a403165a30ff3772975bcbd4..18092b15fc7a4b825e764bb1a1510aba0c69f433 100644
--- a/src/main/java/org/olat/course/run/scoring/AssessmentAccounting.java
+++ b/src/main/java/org/olat/course/run/scoring/AssessmentAccounting.java
@@ -157,9 +157,6 @@ public class AssessmentAccounting implements ScoreAccounting {
 			result.setDuration(duration);
 		}
 		
-		//TODO uh score 1:1 übernehmen (con / lp)
-		//TODO uh passed 1:1 übernehmen (con / lp)
-		//TODO uh status. con = passed. lp = childen fully assessed
 		ScoreEvaluator scoreEvaluator = evaluators.getScoreEvaluator();
 		Float score = scoreEvaluator.getScore(result, courseNode, userCourseEnvironment.getConditionInterpreter());
 		result.setScore(score);
@@ -196,6 +193,12 @@ public class AssessmentAccounting implements ScoreAccounting {
 		result.setLastUserModified(lastModifications.getLastUserModified());
 		result.setLastCoachModified(lastModifications.getLastCoachModified());
 		
+		CompletionEvaluator completionEvaluator = evaluators.getCompletionEvaluator();
+		Double completion = completionEvaluator.getCompletion(result, courseNode,
+				userCourseEnvironment.getCourseEnvironment().getCourseConfig(),
+				this);
+		result.setCompletion(completion);
+		
 		status = statusEvaluator.getStatus(result, children);
 		result.setStatus(status);
 		
@@ -220,6 +223,7 @@ public class AssessmentAccounting implements ScoreAccounting {
 		entry.setDuration(result.getDuration());
 		entry.setLastUserModified(result.getLastUserModified());
 		entry.setLastCoachModified(result.getLastCoachModified());
+		entry.setDuration(result.getDuration());
 		entry.setAssessmentStatus(result.getAssessmentStatus());
 		entry.setFullyAssessed(result.getFullyAssessed());
 		
diff --git a/src/main/java/org/olat/course/run/scoring/AssessmentEvaluation.java b/src/main/java/org/olat/course/run/scoring/AssessmentEvaluation.java
index 315e05f9106317f64e3561296aa51b34f77cfd34..9fed8b4b34820a493b93aef49abdd1c666d2d61c 100644
--- a/src/main/java/org/olat/course/run/scoring/AssessmentEvaluation.java
+++ b/src/main/java/org/olat/course/run/scoring/AssessmentEvaluation.java
@@ -22,6 +22,7 @@ package org.olat.course.run.scoring;
 import java.util.Date;
 
 import org.olat.course.assessment.handler.AssessmentConfig;
+import org.olat.course.assessment.handler.AssessmentConfig.Mode;
 import org.olat.modules.assessment.AssessmentEntry;
 import org.olat.modules.assessment.model.AssessmentEntryStatus;
 import org.olat.modules.assessment.model.AssessmentObligation;
@@ -171,7 +172,7 @@ public class AssessmentEvaluation extends ScoreEvaluation {
 		Double completion = null;
 		Double currentRunCompletion = null;
 		AssessmentRunStatus runStatus = null;
-		if(assessmentConfig.hasCompletion()) {
+		if(assessmentConfig.getCompletionMode() != null && !Mode.none.equals(assessmentConfig.getCompletionMode())) {
 			completion = entry.getCompletion();
 			currentRunCompletion = entry.getCurrentRunCompletion();
 			runStatus = entry.getCurrentRunStatus();
diff --git a/src/main/java/org/olat/course/run/scoring/CompletionEvaluator.java b/src/main/java/org/olat/course/run/scoring/CompletionEvaluator.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a642a80a37aa9be62590cda2b37853b3cd28846
--- /dev/null
+++ b/src/main/java/org/olat/course/run/scoring/CompletionEvaluator.java
@@ -0,0 +1,36 @@
+/**
+ * <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.course.run.scoring;
+
+import org.olat.course.config.CourseConfig;
+import org.olat.course.nodes.CourseNode;
+
+/**
+ * 
+ * Initial date: 22 Sep 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public interface CompletionEvaluator {
+
+	public Double getCompletion(AssessmentEvaluation currentEvaluation, CourseNode courseNode,
+			CourseConfig courseConfig, ScoreAccounting scoreAccounting);
+
+}
diff --git a/src/main/java/org/olat/course/run/scoring/ScoreAccounting.java b/src/main/java/org/olat/course/run/scoring/ScoreAccounting.java
index 5a0f2f9c0312f22380f0a16fbd4606b628b780be..f6bf1c2cc3484e93b6e7b9676f109c69aef77c97 100644
--- a/src/main/java/org/olat/course/run/scoring/ScoreAccounting.java
+++ b/src/main/java/org/olat/course/run/scoring/ScoreAccounting.java
@@ -45,9 +45,9 @@ public interface ScoreAccounting {
 
 	/**
 	 * Evaluates the course node or simply returns the evaluation from the cache.
-	 * @param cn
+	 * @param cncourseNode
 	 * @return ScoreEvaluation
 	 */
-	AssessmentEvaluation evalCourseNode(CourseNode cn);
+	AssessmentEvaluation evalCourseNode(CourseNode courseNode);
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/olat/course/assessment/MappedScoreAccounting.java b/src/test/java/org/olat/course/assessment/MappedScoreAccounting.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e28800d6c35fcba5aab6f063cab0a872d95051f
--- /dev/null
+++ b/src/test/java/org/olat/course/assessment/MappedScoreAccounting.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.course.assessment;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.run.scoring.AssessmentEvaluation;
+import org.olat.course.run.scoring.ScoreAccounting;
+
+/**
+ * 
+ * Initial date: 23 Sep 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class MappedScoreAccounting implements ScoreAccounting {
+	
+	private Map<CourseNode, AssessmentEvaluation> nodeToEvaluation = new HashMap<>();
+	
+	public void put(CourseNode courseNode, AssessmentEvaluation evaluation) {
+		nodeToEvaluation.put(courseNode, evaluation);
+	}
+
+	@Override
+	public void evaluateAll() {
+		//
+	}
+
+	@Override
+	public boolean evaluateAll(boolean update) {
+		return false;
+	}
+
+	@Override
+	public AssessmentEvaluation getScoreEvaluation(CourseNode courseNode) {
+		return nodeToEvaluation.get(courseNode);
+	}
+
+	@Override
+	public AssessmentEvaluation evalCourseNode(CourseNode courseNode) {
+		return nodeToEvaluation.get(courseNode);
+	}
+
+}
diff --git a/src/test/java/org/olat/course/nodes/st/assessment/NumberOfNodesCompletionEvaluatorTest.java b/src/test/java/org/olat/course/nodes/st/assessment/NumberOfNodesCompletionEvaluatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..61a3aeda27f6dc9e165bd35ffc8102f66be668f0
--- /dev/null
+++ b/src/test/java/org/olat/course/nodes/st/assessment/NumberOfNodesCompletionEvaluatorTest.java
@@ -0,0 +1,209 @@
+/**
+ * <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.course.nodes.st.assessment;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.offset;
+import static org.mockito.Mockito.when;
+import static org.olat.modules.assessment.model.AssessmentObligation.mandatory;
+import static org.olat.modules.assessment.model.AssessmentObligation.optional;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.olat.course.assessment.CourseAssessmentService;
+import org.olat.course.assessment.MappedScoreAccounting;
+import org.olat.course.assessment.handler.AssessmentConfig;
+import org.olat.course.assessment.handler.AssessmentConfig.Mode;
+import org.olat.course.nodes.Card2BrainCourseNode;
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.nodes.SPCourseNode;
+import org.olat.course.nodes.STCourseNode;
+import org.olat.course.run.scoring.AssessmentEvaluation;
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
+import org.olat.modules.assessment.model.AssessmentObligation;
+
+/**
+ * 
+ * Initial date: 23 Sep 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class NumberOfNodesCompletionEvaluatorTest {
+	
+	@Mock
+	private AssessmentConfig configSetByNode;
+	@Mock
+	private AssessmentConfig configEvaluated;
+	@Mock
+	private AssessmentConfig configNone;
+
+	@Mock
+	private CourseAssessmentService courseAssessmentService;
+	
+	@InjectMocks
+	private NumberOfNodesCompletionEvaluator sut;
+
+	
+	@Before
+	public void setUp() {
+		MockitoAnnotations.initMocks(this);
+		
+		when(configEvaluated.getCompletionMode()).thenReturn(Mode.evaluated);
+		when(configSetByNode.getCompletionMode()).thenReturn(Mode.setByNode);
+		when(configNone.getCompletionMode()).thenReturn(Mode.none);
+	}
+	
+	@Test
+	public void shouldReturnNullIfItHasNoChildren() {
+		MappedScoreAccounting scoreAccounting = new MappedScoreAccounting();
+		CourseNode parent = new STCourseNode();
+		
+		Double completion = sut.getCompletion(null, parent, null, scoreAccounting);
+		
+		assertThat(completion).isNull();
+	}
+
+	@Test
+	public void shouldGetAverageCompletionOfChildren() {
+		MappedScoreAccounting scoreAccounting = new MappedScoreAccounting();
+		
+		// Parent
+		CourseNode parent = new STCourseNode();
+		// Child: uncalculated 
+		CourseNode childUncalculated = new Card2BrainCourseNode();
+		parent.addChild(childUncalculated);
+		AssessmentEvaluation childUncalculatedEvaluation = createAssessmentEvaluation(mandatory, Double.valueOf(0.5), null, null);
+		scoreAccounting.put(childUncalculated, childUncalculatedEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childUncalculated)).thenReturn(configSetByNode);
+		// Child: Calculated
+		CourseNode childCalculated = new STCourseNode();
+		parent.addChild(childCalculated);
+		AssessmentEvaluation childCalculatedEvaluation = createAssessmentEvaluation(mandatory, Double.valueOf(0.1), null, null);
+		scoreAccounting.put(childCalculated, childCalculatedEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childCalculated)).thenReturn(configEvaluated);
+		
+		// Child level 2: calculated
+		CourseNode child2Uncalculated = new SPCourseNode();
+		parent.addChild(child2Uncalculated);
+		AssessmentEvaluation child2UncalculatedEvaluation = createAssessmentEvaluation(mandatory, Double.valueOf(1.0), null, null);
+		scoreAccounting.put(child2Uncalculated, child2UncalculatedEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(child2Uncalculated)).thenReturn(configSetByNode);
+		
+		Double completion = sut.getCompletion(null, parent, null, scoreAccounting);
+		
+		assertThat(completion).isEqualTo(0.75);
+	}
+	
+	@Test
+	public void shouldOnlyRespectMandatoryEvaluations() {
+		MappedScoreAccounting scoreAccounting = new MappedScoreAccounting();
+		
+		// Parent: calculated
+		CourseNode parent = new STCourseNode();
+		// Child: mandatory
+		CourseNode childMandatory = new Card2BrainCourseNode();
+		parent.addChild(childMandatory);
+		AssessmentEvaluation childMandatoryEvaluation = createAssessmentEvaluation(mandatory, Double.valueOf(0.5), null, null);
+		scoreAccounting.put(childMandatory, childMandatoryEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childMandatory)).thenReturn(configSetByNode);
+		// Child: optional
+		CourseNode childOptional = new Card2BrainCourseNode();
+		parent.addChild(childOptional);
+		AssessmentEvaluation childOptionalEvaluation = createAssessmentEvaluation(optional, Double.valueOf(0.6), null, null);
+		scoreAccounting.put(childOptional, childOptionalEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childOptional)).thenReturn(configSetByNode);
+		// Child: no obligation
+		CourseNode childNoObligation = new Card2BrainCourseNode();
+		parent.addChild(childNoObligation);
+		AssessmentEvaluation childNoObligationEvaluation = createAssessmentEvaluation(null, Double.valueOf(0.7), null, null);
+		scoreAccounting.put(childNoObligation, childNoObligationEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childNoObligation)).thenReturn(configSetByNode);
+		
+		Double completion = sut.getCompletion(null, parent, null, scoreAccounting);
+		
+		assertThat(completion).isEqualTo(0.5);
+	}
+	
+	@Test
+	public void shouldAssumeCompletionIfTheCourseNodeDoesNotSetIt() {
+		MappedScoreAccounting scoreAccounting = new MappedScoreAccounting();
+		
+		// Parent: calculated
+		CourseNode parent = new STCourseNode();
+		// Child: fully assessed
+		CourseNode childFullyAssessed = new Card2BrainCourseNode();
+		parent.addChild(childFullyAssessed);
+		AssessmentEvaluation childFullyAssessedEvaluation = createAssessmentEvaluation(mandatory, null, null, Boolean.TRUE);
+		scoreAccounting.put(childFullyAssessed, childFullyAssessedEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childFullyAssessed)).thenReturn(configNone);
+		// Child: no status
+		CourseNode childNoStatus = new Card2BrainCourseNode();
+		parent.addChild(childNoStatus);
+		AssessmentEvaluation childNoStatusEvaluation = createAssessmentEvaluation(mandatory, null, null, null);
+		scoreAccounting.put(childNoStatus, childNoStatusEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childNoStatus)).thenReturn(configNone);
+		// Child: notReady
+		CourseNode childNotReady = new Card2BrainCourseNode();
+		parent.addChild(childNotReady);
+		AssessmentEvaluation childNotReadyEvaluation = createAssessmentEvaluation(mandatory, null, AssessmentEntryStatus.notReady, null);
+		scoreAccounting.put(childNotReady, childNotReadyEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childNotReady)).thenReturn(configNone);
+		// Child: notStarted
+		CourseNode childNotStarted = new Card2BrainCourseNode();
+		parent.addChild(childNotStarted);
+		AssessmentEvaluation childNotStartedEvaluation = createAssessmentEvaluation(mandatory, null, AssessmentEntryStatus.notStarted, null);
+		scoreAccounting.put(childNotStarted, childNotStartedEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childNotStarted)).thenReturn(configNone);
+		// Child: inProgress
+		CourseNode childInProgress = new Card2BrainCourseNode();
+		parent.addChild(childInProgress);
+		AssessmentEvaluation childInProgressEvaluation = createAssessmentEvaluation(mandatory, null, AssessmentEntryStatus.inProgress, null);
+		scoreAccounting.put(childInProgress, childInProgressEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childInProgress)).thenReturn(configNone);
+		// Child: inReview
+		CourseNode childInReview = new Card2BrainCourseNode();
+		parent.addChild(childInReview);
+		AssessmentEvaluation childInReviewEvaluation = createAssessmentEvaluation(mandatory, null, AssessmentEntryStatus.inReview, null);
+		scoreAccounting.put(childInReview, childInReviewEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childInReview)).thenReturn(configNone);
+		// Child: done
+		CourseNode childDone = new Card2BrainCourseNode();
+		parent.addChild(childDone);
+		AssessmentEvaluation childDoneEvaluation = createAssessmentEvaluation(mandatory, null, AssessmentEntryStatus.done, null);
+		scoreAccounting.put(childDone, childDoneEvaluation);
+		when(courseAssessmentService.getAssessmentConfig(childDone)).thenReturn(configNone);
+		
+		Double completion = sut.getCompletion(null, parent, null, scoreAccounting);
+		
+		double expected = (1.0 + 0.0 + 0.0 + 0.0 + 0.5 + 0.75 + 1.0) / 7;
+		assertThat(completion).isEqualTo(expected, offset(0.001));
+		
+	}
+	
+	private AssessmentEvaluation createAssessmentEvaluation(AssessmentObligation obligation, Double completion,
+			AssessmentEntryStatus status, Boolean fullyAssessed) {
+		return new AssessmentEvaluation(null, null, null, completion, status, null, fullyAssessed, null, null, null,
+				null, null, 0, null, null, null, null, obligation, null);
+	}
+
+}
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 74b8f0d994932e6cab075c85c7b717f482609071..98f2751b226f3ead5533ed779e58f21edc66d9c4 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -460,6 +460,7 @@ import org.junit.runners.Suite;
 	org.olat.course.learningpath.evaluation.LinearAccessEvaluator.class,
 	org.olat.course.learningpath.manager.LearningPathNodeAccessProviderTest.class,
 	org.olat.course.nodes.st.assessment.CumulatingDurationEvaluatorTest.class,
+	org.olat.course.nodes.st.assessment.NumberOfNodesCompletionEvaluatorTest.class,
 	org.olat.course.nodes.st.assessment.STFullyAssessedEvaluatorTest.class,
 	org.olat.course.nodes.st.assessment.STLastModificationsEvaluatorTest.class,
 	org.olat.course.nodes.st.assessment.STLinearStatusEvaluatorTest.class,