diff --git a/src/main/java/org/olat/course/config/ui/CourseScoreController.java b/src/main/java/org/olat/course/config/ui/CourseScoreController.java
index 925dd13e654928d4a8c1308690d3b90743994b6b..66d18906f8055fa92580cafa435bc25abe03d195 100644
--- a/src/main/java/org/olat/course/config/ui/CourseScoreController.java
+++ b/src/main/java/org/olat/course/config/ui/CourseScoreController.java
@@ -59,10 +59,12 @@ public class CourseScoreController extends FormBasicController {
 	private static final String[] UNTRANSLATED = { "" };
 
 	private SingleSelection scoreEl;
+	private MultipleSelectionElement passedManuallyEl;
 	private MultipleSelectionElement passedProgressEl;
 	private MultipleSelectionElement passedAllEl;
+	private MultipleSelectionElement passedNumberEl;
+	private TextElement passedNumberCutEl;
 	private MultipleSelectionElement passedPointsEl;
-	private MultipleSelectionElement passedManuallyEl;
 	private TextElement passedPointsCutEl;
 	
 	private final RepositoryEntry courseEntry;
@@ -133,7 +135,14 @@ public class CourseScoreController extends FormBasicController {
 		String scoreKey = moduleConfig.has(STCourseNode.CONFIG_SCORE_KEY)? moduleConfig.getStringValue(STCourseNode.CONFIG_SCORE_KEY): SCORE_VALUE_NONE;
 		scoreEl.select(scoreKey, true);
 		
-		// Passed
+		// Passed manually
+		passedManuallyEl = uifactory.addCheckboxesHorizontal("options.passed.manually", formLayout, ONE_OPTION, UNTRANSLATED);
+		passedManuallyEl.addActionListener(FormEvent.ONCHANGE);
+		boolean passedManually = moduleConfig.getBooleanSafe(STCourseNode.CONFIG_PASSED_MANUALLY);
+		passedManuallyEl.select(passedManuallyEl.getKey(0), passedManually);
+		passedManuallyEl.setEnabled(editable);
+		
+		// Passed evaluation
 		StaticTextElement passedIfEl = uifactory.addStaticTextElement("options.passed.if", null, formLayout);
 		passedIfEl.setHelpTextKey("options.passed.if.help", null);
 		
@@ -147,6 +156,20 @@ public class CourseScoreController extends FormBasicController {
 		passedAllEl.select(passedAllEl.getKey(0), passedAll);
 		passedAllEl.setEnabled(editable);
 		
+		passedNumberEl = uifactory.addCheckboxesHorizontal("options.passed.number", formLayout, ONE_OPTION, UNTRANSLATED);
+		passedNumberEl.addActionListener(FormEvent.ONCHANGE);
+		boolean passedNumber = moduleConfig.getBooleanSafe(STCourseNode.CONFIG_PASSED_NUMBER);
+		passedNumberEl.select(passedNumberEl.getKey(0), passedNumber);
+		passedNumberEl.setEnabled(editable);
+		
+		String passedNumberCut = moduleConfig.has(STCourseNode.CONFIG_PASSED_NUMBER_CUT)
+				? String.valueOf(moduleConfig.getIntegerSafe(STCourseNode.CONFIG_PASSED_NUMBER_CUT, 1))
+				: null;
+		passedNumberCutEl = uifactory.addTextElement("options.passed.number.cut", 10, passedNumberCut, formLayout);
+		passedNumberCutEl.setCheckVisibleLength(true);
+		passedNumberCutEl.setDisplaySize(10);
+		passedNumberEl.setEnabled(editable);
+		
 		passedPointsEl = uifactory.addCheckboxesHorizontal("options.passed.points", formLayout, ONE_OPTION, UNTRANSLATED);
 		passedPointsEl.addActionListener(FormEvent.ONCHANGE);
 		boolean passedPoints = moduleConfig.getBooleanSafe(STCourseNode.CONFIG_PASSED_POINTS);
@@ -161,12 +184,6 @@ public class CourseScoreController extends FormBasicController {
 		passedPointsCutEl.setDisplaySize(10);
 		passedPointsEl.setEnabled(editable);
 		
-		passedManuallyEl = uifactory.addCheckboxesHorizontal("options.passed.manually", formLayout, ONE_OPTION, UNTRANSLATED);
-		passedManuallyEl.addActionListener(FormEvent.ONCHANGE);
-		boolean passedManually = moduleConfig.getBooleanSafe(STCourseNode.CONFIG_PASSED_MANUALLY);
-		passedManuallyEl.select(passedManuallyEl.getKey(0), passedManually);
-		passedManuallyEl.setEnabled(editable);
-		
 		if (editable) {
 			FormLayoutContainer buttonCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
 			buttonCont.setRootForm(mainForm);
@@ -178,13 +195,18 @@ public class CourseScoreController extends FormBasicController {
 	}
 
 	private void updateUI() {
+		boolean passedNumber = passedNumberEl.isAtLeastSelected(1);
+		passedNumberCutEl.setVisible(passedNumber);
+		
 		boolean passedPoints = passedPointsEl.isAtLeastSelected(1);
 		passedPointsCutEl.setVisible(passedPoints);
 	}
 
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
-		if (source == passedPointsEl) {
+		if (source == passedNumberEl) {
+			updateUI();
+		} else if (source == passedPointsEl) {
 			updateUI();
 		}
 		super.formInnerEvent(ureq, source, event);
@@ -194,6 +216,7 @@ public class CourseScoreController extends FormBasicController {
 	protected boolean validateFormLogic(UserRequest ureq) {
 		boolean allOk = true;
 		
+		allOk &= validateInteger(passedNumberCutEl, 1, Integer.MAX_VALUE, true, "error.positiv.int");
 		allOk &= validateInteger(passedPointsCutEl, 1, Integer.MAX_VALUE, true, "error.positiv.int");
 		
 		return allOk & super.validateFormLogic(ureq);
@@ -250,6 +273,15 @@ public class CourseScoreController extends FormBasicController {
 			editorConfig.setStringValue(STCourseNode.CONFIG_SCORE_KEY, selectedScoreKey);
 		}
 		
+		boolean passedManually = passedManuallyEl.isAtLeastSelected(1);
+		if (passedManually) {
+			runConfig.setBooleanEntry(STCourseNode.CONFIG_PASSED_MANUALLY, true);
+			editorConfig.setBooleanEntry(STCourseNode.CONFIG_PASSED_MANUALLY, true);
+		} else {
+			runConfig.remove(STCourseNode.CONFIG_PASSED_MANUALLY);
+			editorConfig.remove(STCourseNode.CONFIG_PASSED_MANUALLY);
+		}
+		
 		boolean passedProgress = passedProgressEl.isAtLeastSelected(1);
 		if (passedProgress) {
 			runConfig.setBooleanEntry(STCourseNode.CONFIG_PASSED_PROGRESS, true);
@@ -268,6 +300,20 @@ public class CourseScoreController extends FormBasicController {
 			editorConfig.remove(STCourseNode.CONFIG_PASSED_ALL);
 		}
 		
+		boolean passedNumber = passedNumberEl.isAtLeastSelected(1);
+		if (passedNumber) {
+			int numberCut = Integer.parseInt(passedNumberCutEl.getValue());
+			runConfig.setBooleanEntry(STCourseNode.CONFIG_PASSED_NUMBER, true);
+			runConfig.setIntValue(STCourseNode.CONFIG_PASSED_NUMBER_CUT, numberCut);
+			editorConfig.setBooleanEntry(STCourseNode.CONFIG_PASSED_NUMBER, true);
+			editorConfig.setIntValue(STCourseNode.CONFIG_PASSED_NUMBER_CUT, numberCut);
+		} else {
+			runConfig.remove(STCourseNode.CONFIG_PASSED_NUMBER);
+			runConfig.remove(STCourseNode.CONFIG_PASSED_NUMBER_CUT);
+			editorConfig.remove(STCourseNode.CONFIG_PASSED_NUMBER);
+			editorConfig.remove(STCourseNode.CONFIG_PASSED_NUMBER_CUT);
+		}
+		
 		boolean passedPoints = passedPointsEl.isAtLeastSelected(1);
 		if (passedPoints) {
 			int pointsCut = Integer.parseInt(passedPointsCutEl.getValue());
@@ -282,15 +328,6 @@ public class CourseScoreController extends FormBasicController {
 			editorConfig.remove(STCourseNode.CONFIG_PASSED_POINTS_CUT);
 		}
 		
-		boolean passedManually = passedManuallyEl.isAtLeastSelected(1);
-		if (passedManually) {
-			runConfig.setBooleanEntry(STCourseNode.CONFIG_PASSED_MANUALLY, true);
-			editorConfig.setBooleanEntry(STCourseNode.CONFIG_PASSED_MANUALLY, true);
-		} else {
-			runConfig.remove(STCourseNode.CONFIG_PASSED_MANUALLY);
-			editorConfig.remove(STCourseNode.CONFIG_PASSED_MANUALLY);
-		}
-		
 		CourseFactory.saveCourse(courseEntry.getOlatResource().getResourceableId());
 		CourseFactory.closeCourseEditSession(course.getResourceableId(), true);
 		
diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
index 20708f53e46f5adc6acb981cb2aaa053687b4169..98cd915dda75bc99d6c7142d01df23a6eb51c2d8 100644
--- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
@@ -45,13 +45,15 @@ glossary.no.glossary=Kein Glossar gew\u00E4hlt
 glossary.title=Titel
 lock.failed=Die Kurseinstellungen werden seit {1} vom Benutzer {0} editiert.
 options.efficency.title=Leistungnachweis
-options.passed.all=... all Kursbausteine bestanden sind
+options.passed.all=Alle Kursbausteine bestanden
 options.passed.if=Bestanden, wenn ...
 options.passed.if.help=Der Teilnehmer muss mindestens eines der Kriterien erf\u00FCllen, um den Kurs zu bestehen.
 options.passed.manually=Coach kann "bestanden" manuell setzen
-options.passed.points=... Punkteschwelle erreicht ist
+options.passed.number=Anzahl Kursbausteine bestanden
+options.passed.number.cut=Anzahl Kursbausteine
+options.passed.points=Punkteschwelle erreicht
 options.passed.points.cut=Punkteschwelle
-options.passed.progress=... Lernfortschritt 100% ist
+options.passed.progress=Lernfortschritt 100%
 options.score.points=Punkte
 options.score.points.average=Durchschnitt
 options.score.points.none=Keine Punkte
diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties
index 4d0fc7edb137c0ecbddc8119b0515284db578c99..04039041552f24deed7e6704a6f959e846cf3a68 100644
--- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties
@@ -45,13 +45,15 @@ glossary.no.glossary=No glossary selected
 glossary.title=Title
 lock.failed=These course settings are edited since {1} by user {0}.
 options.efficency.title=Evidence of achievement
-options.passed.all=... all course elements are passed
+options.passed.all=All course elements passed
 options.passed.if=Passed if ...
 options.passed.if.help=The participant has to meet at least one criterion to pass the course.
 options.passed.manually=Coach can set "passed" manually
-options.passed.points=... number of points is reached
+options.passed.number=Number of course elements passed
+options.passed.number.cut=Number of course elements
+options.passed.points=Number of points reached
 options.passed.points.cut=Cut value
-options.passed.progress=... learning progess is 100%
+options.passed.progress=Learning progess 100%
 options.score.points=Points
 options.score.points.average=Average
 options.score.points.none=No points
diff --git a/src/main/java/org/olat/course/nodes/STCourseNode.java b/src/main/java/org/olat/course/nodes/STCourseNode.java
index bd0be8b85caf062d6c91bd80cf37aa38d8c173a7..936f25ea54a2216b00e6abd862e13eed12edc22e 100644
--- a/src/main/java/org/olat/course/nodes/STCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/STCourseNode.java
@@ -116,6 +116,8 @@ public class STCourseNode extends AbstractAccessableCourseNode {
 	public static final String CONFIG_SCORE_VALUE_AVG = "score.avg";
 	public static final String CONFIG_PASSED_PROGRESS = "passed.progress";
 	public static final String CONFIG_PASSED_ALL = "passed.all";
+	public static final String CONFIG_PASSED_NUMBER = "passed.number";
+	public static final String CONFIG_PASSED_NUMBER_CUT = "passed.number.cut";
 	public static final String CONFIG_PASSED_POINTS = "passed.points";
 	public static final String CONFIG_PASSED_POINTS_CUT = "passed.points.cut";
 	public static final String CONFIG_PASSED_MANUALLY = "passed.manually";
diff --git a/src/main/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluator.java b/src/main/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluator.java
index 7977a13b1238ae2861cfab64a75a8d7392b55f5a..3bd663879868abd4bc951050b0b25342ee52af3d 100644
--- a/src/main/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluator.java
+++ b/src/main/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluator.java
@@ -71,13 +71,22 @@ public class STRootPassedEvaluator implements RootPassedEvaluator {
 		if (config.getBooleanSafe(STCourseNode.CONFIG_PASSED_POINTS)) {
 			Float score = currentEvaluation.getScore();
 			if (score != null) {
-				int cutvalue = config.getIntegerSafe(STCourseNode.CONFIG_PASSED_POINTS_CUT, Integer.MAX_VALUE);
-				if (score.floatValue() >= cutvalue) {
+				int cutValue = config.getIntegerSafe(STCourseNode.CONFIG_PASSED_POINTS_CUT, Integer.MAX_VALUE);
+				if (score.floatValue() >= cutValue) {
 					return Boolean.TRUE;
 				}
 			}
 		}
 		
+		// Number passed
+		if (config.getBooleanSafe(STCourseNode.CONFIG_PASSED_NUMBER)) {
+			int cutValue = config.getIntegerSafe(STCourseNode.CONFIG_PASSED_NUMBER_CUT, Integer.MAX_VALUE);
+			Counts counts = passCounter.getCounts(courseNode, scoreAccounting);
+			if (counts.getPassed() >= cutValue) {
+				return Boolean.TRUE;
+			}
+		}
+		
 		// All passed
 		if (config.getBooleanSafe(STCourseNode.CONFIG_PASSED_ALL)) {
 			Counts counts = passCounter.getCounts(courseNode, scoreAccounting);
@@ -121,6 +130,9 @@ public class STRootPassedEvaluator implements RootPassedEvaluator {
 		if (config.has(STCourseNode.CONFIG_PASSED_ALL)) {
 			active++;
 		}
+		if (config.has(STCourseNode.CONFIG_PASSED_NUMBER)) {
+			active++;
+		}
 		if (config.has(STCourseNode.CONFIG_PASSED_POINTS)) {
 			active++;
 		}
diff --git a/src/test/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluatorTest.java b/src/test/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluatorTest.java
index 23a63d9772a9b99f8e4b45a12b0622fe9172a3df..77870d927e9c141811207a1cae2a4c306256062f 100644
--- a/src/test/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluatorTest.java
+++ b/src/test/java/org/olat/course/nodes/st/assessment/STRootPassedEvaluatorTest.java
@@ -239,6 +239,58 @@ public class STRootPassedEvaluatorTest {
 		assertThat(passed).isNull();
 	}
 	
+	@Test
+	public void shouldReturnTrueIfNumberPassed() {
+		AssessmentEvaluation currentEvaluation = new AssessmentEvaluation(Float.valueOf(20), null, null, null);
+		CourseNode courseNode = new STCourseNode();
+		courseNode.getModuleConfiguration().setBooleanEntry(STCourseNode.CONFIG_PASSED_NUMBER, true);
+		courseNode.getModuleConfiguration().setIntValue(STCourseNode.CONFIG_PASSED_NUMBER_CUT, 2);
+		ScoreAccounting scoreAccounting = new MappedScoreAccounting();
+		
+		Counts counts = new CountsImpl(4, 2, 1);
+		PassCounter passCounter = mock(PassCounter.class);
+		when(passCounter.getCounts(any(), any())).thenReturn(counts);
+		STRootPassedEvaluator sut = new STRootPassedEvaluator(passCounter);
+		Boolean passed = sut.getPassed(currentEvaluation, courseNode, scoreAccounting, dummyEntry);
+		
+		assertThat(passed).isTrue();
+	}
+	
+	@Test
+	public void shouldReturnNullIfNumberNotPassedAndOnlyCriterion() {
+		AssessmentEvaluation currentEvaluation = new AssessmentEvaluation(Float.valueOf(20), null, null, null);
+		CourseNode courseNode = new STCourseNode();
+		courseNode.getModuleConfiguration().setBooleanEntry(STCourseNode.CONFIG_PASSED_NUMBER, true);
+		courseNode.getModuleConfiguration().setIntValue(STCourseNode.CONFIG_PASSED_NUMBER_CUT, 2);
+		ScoreAccounting scoreAccounting = new MappedScoreAccounting();
+		
+		Counts counts = new CountsImpl(4, 1, 1);
+		PassCounter passCounter = mock(PassCounter.class);
+		when(passCounter.getCounts(any(), any())).thenReturn(counts);
+		STRootPassedEvaluator sut = new STRootPassedEvaluator(passCounter);
+		Boolean passed = sut.getPassed(currentEvaluation, courseNode, scoreAccounting, dummyEntry);
+		
+		assertThat(passed).isNull();
+	}
+	
+	@Test
+	public void shouldNotReturnNullIfNumberNotPassedAndMultipleCriterion() {
+		AssessmentEvaluation currentEvaluation = new AssessmentEvaluation(Float.valueOf(20), null, null, null);
+		CourseNode courseNode = new STCourseNode();
+		courseNode.getModuleConfiguration().setBooleanEntry(STCourseNode.CONFIG_PASSED_ALL, true);
+		courseNode.getModuleConfiguration().setBooleanEntry(STCourseNode.CONFIG_PASSED_NUMBER, true);
+		courseNode.getModuleConfiguration().setIntValue(STCourseNode.CONFIG_PASSED_NUMBER_CUT, 2);
+		ScoreAccounting scoreAccounting = new MappedScoreAccounting();
+		
+		Counts counts = new CountsImpl(4, 1, 1);
+		PassCounter passCounter = mock(PassCounter.class);
+		when(passCounter.getCounts(any(), any())).thenReturn(counts);
+		STRootPassedEvaluator sut = new STRootPassedEvaluator(passCounter);
+		Boolean passed = sut.getPassed(currentEvaluation, courseNode, scoreAccounting, dummyEntry);
+		
+		assertThat(passed).isNull();
+	}
+	
 	@Test
 	public void shouldReturnNullIfNotAllAssessed() {
 		AssessmentEvaluation currentEvaluation = new AssessmentEvaluation(Float.valueOf(20), null, null, null);