diff --git a/src/main/java/org/olat/course/nodes/st/assessment/ScoreStatusEvaluator.java b/src/main/java/org/olat/course/nodes/st/assessment/ScoreStatusEvaluator.java index 0c2e446bf881a64d0cf5c4ff36be7c7b1c4a2017..5e5689724c463ab04ec28e93a7e9fb4631fe75e9 100644 --- a/src/main/java/org/olat/course/nodes/st/assessment/ScoreStatusEvaluator.java +++ b/src/main/java/org/olat/course/nodes/st/assessment/ScoreStatusEvaluator.java @@ -37,6 +37,12 @@ public class ScoreStatusEvaluator implements StatusEvaluator { @Override public AssessmentEntryStatus getStatus(AssessmentEvaluation currentEvaluation, Blocker blocker) { + return currentEvaluation.getAssessmentStatus(); + } + + @Override + public AssessmentEntryStatus getStatus(AssessmentEvaluation currentEvaluation, + List<AssessmentEvaluation> children) { if (currentEvaluation.getPassed() != null && currentEvaluation.getPassed().booleanValue()) { return AssessmentEntryStatus.done; } else if (currentEvaluation.getScore() != null || currentEvaluation.getCompletion() != null) { @@ -45,10 +51,4 @@ public class ScoreStatusEvaluator implements StatusEvaluator { return AssessmentEntryStatus.notStarted; } - @Override - public AssessmentEntryStatus getStatus(AssessmentEvaluation currentEvaluation, - List<AssessmentEvaluation> children) { - return currentEvaluation.getAssessmentStatus(); - } - } 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 0ba567cfb1d6c896f173b29cb7433762996ad683..3be378c573dd56ab3ce94223dc5de1100c74a284 100644 --- a/src/main/java/org/olat/course/run/scoring/AssessmentAccounting.java +++ b/src/main/java/org/olat/course/run/scoring/AssessmentAccounting.java @@ -174,12 +174,6 @@ public class AssessmentAccounting implements ScoreAccounting { result.setDuration(duration); } - PassedEvaluator passedEvaluator = evaluators.getPassedEvaluator(); - Boolean passed = passedEvaluator.getPassed(result, courseNode, - userCourseEnvironment.getCourseEnvironment().getCourseGroupManager().getCourseEntry(), - userCourseEnvironment.getConditionInterpreter()); - result.setPassed(passed); - StatusEvaluator statusEvaluator = evaluators.getStatusEvaluator(); AssessmentEntryStatus status = statusEvaluator.getStatus(result, blocker); result.setStatus(status); @@ -216,6 +210,12 @@ public class AssessmentAccounting implements ScoreAccounting { obligation = obligationEvaluator.getObligation(result, children); result.setObligation(obligation); + PassedEvaluator passedEvaluator = evaluators.getPassedEvaluator(); + Boolean passed = passedEvaluator.getPassed(result, courseNode, + userCourseEnvironment.getCourseEnvironment().getCourseGroupManager().getCourseEntry(), + userCourseEnvironment.getConditionInterpreter()); + result.setPassed(passed); + FullyAssessedEvaluator fullyAssessedEvaluator = evaluators.getFullyAssessedEvaluator(); Boolean fullyAssessed = fullyAssessedEvaluator.getFullyAssessed(result, children, blocker); result.setFullyAssessed(fullyAssessed); diff --git a/src/test/java/org/olat/course/condition/GetPassedTest.java b/src/test/java/org/olat/course/condition/GetPassedTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cadbf8822e0c926f9076a8746f05a0afe37682f1 --- /dev/null +++ b/src/test/java/org/olat/course/condition/GetPassedTest.java @@ -0,0 +1,170 @@ +/** + * <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.condition; + +import org.assertj.core.api.SoftAssertions; +import org.junit.Test; +import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.course.Structure; +import org.olat.course.nodes.CheckListCourseNode; +import org.olat.course.nodes.CourseNode; +import org.olat.course.nodes.MSCourseNode; +import org.olat.course.nodes.SPCourseNode; +import org.olat.course.nodes.STCourseNode; +import org.olat.course.run.environment.CourseEnvironment; +import org.olat.course.run.scoring.ScoreAccounting; +import org.olat.course.run.userview.UserCourseEnvironmentImpl; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.AssessmentService; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryStatusEnum; +import org.olat.test.JunitTestHelper; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 30 May 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class GetPassedTest extends OlatTestCase { + + @Autowired + private DB dbInstance; + @Autowired + private AssessmentService assessmentService; + + /** + * Course (passed if ST1 and ST2 passed) + * - SP + * - ST1 (passed if ST11 passed) + * - ST11 (passed if CHECKLIST passed) + * - CHECKLIST + * - ST2 (passed if MS passed) + * - MS + */ + @Test + public void shouldGetPassedHierarchically() { + // Create course + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("author"); + RepositoryEntry courseEntry = JunitTestHelper.deployEmptyCourse(author, "Get Passed Hierarchically", + RepositoryEntryStatusEnum.published, true, false); + ICourse course = CourseFactory.loadCourse(courseEntry); + course.getCourseConfig().setNodeAccessType(ConditionNodeAccessProvider.TYPE); + CourseEnvironment courseEnv = course.getCourseEnvironment(); + + // Make the course runtime structure + Structure runStructure = courseEnv.getRunStructure(); + STCourseNode root = (STCourseNode)runStructure.getRootNode(); + root.getModuleConfiguration().setStringValue(STCourseNode.CONFIG_LP_SEQUENCE_KEY, + STCourseNode.CONFIG_LP_SEQUENCE_VALUE_SEQUENTIAL); + SPCourseNode sp_0_1 = new SPCourseNode(); + root.addChild(sp_0_1); + // Structure 1 + STCourseNode st_1 = new STCourseNode(); + root.addChild(st_1); + STCourseNode st_1_1 = new STCourseNode(); + st_1_1.getScoreCalculator().setExpertMode(true); + st_1.addChild(st_1_1); + CheckListCourseNode cl_1_1_1 = new CheckListCourseNode(); + cl_1_1_1.getModuleConfiguration().setBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD, true); + st_1_1.addChild(cl_1_1_1); + // Structure 2 + STCourseNode st_2 = new STCourseNode(); + st_2.getModuleConfiguration().setStringValue(STCourseNode.CONFIG_LP_SEQUENCE_KEY, + STCourseNode.CONFIG_LP_SEQUENCE_VALUE_WITHOUT); + root.addChild(st_2); + MSCourseNode ms_2_1 = new MSCourseNode(); + ms_2_1.getModuleConfiguration().setBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD, true); + st_2.addChild(ms_2_1); + + // Init the passed rules + st_2.getScoreCalculator().setPassedExpression("(getPassed(\"" + ms_2_1.getIdent() +"\"))"); + st_1_1.getScoreCalculator().setPassedExpression("(getPassed(\"" + cl_1_1_1.getIdent() +"\"))"); + st_1.getScoreCalculator().setPassedExpression("(getPassed(\"" + st_1_1.getIdent() +"\"))"); + root.getScoreCalculator().setPassedExpression("(getPassed(\"" + st_1.getIdent() +"\") & getPassed(\"" + st_2.getIdent() + "\"))"); + + // Add a participant to the course + Identity participant = JunitTestHelper.createAndPersistIdentityAsUser("participant"); + IdentityEnvironment identityEnv = new IdentityEnvironment(); + identityEnv.setIdentity(participant); + UserCourseEnvironmentImpl userCourseEnv = new UserCourseEnvironmentImpl(identityEnv, courseEnv); + userCourseEnv.setUserRoles(false, false, true); + dbInstance.commitAndCloseSession(); + + // Init the AssessmentAccounting + ScoreAccounting scoreAccounting = userCourseEnv.getScoreAccounting(); + scoreAccounting.evaluateAll(true); + dbInstance.commitAndCloseSession(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(scoreAccounting.evalCourseNode(root).getPassed()).as("root").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(sp_0_1).getPassed()).as("sp_0_1").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(st_1).getPassed()).as("st_1").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(st_1_1).getPassed()).as("sp_1_1").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(cl_1_1_1).getPassed()).as("cl_1_1_1").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(st_2).getPassed()).as("st_2").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(ms_2_1).getPassed()).as("ms_2_1").isNull(); + softly.assertAll(); + + // The participant passes cl_1_1_1 + setPassed(participant, courseEntry, cl_1_1_1); + scoreAccounting.evaluateAll(true); + dbInstance.commitAndCloseSession(); + + softly = new SoftAssertions(); + softly.assertThat(scoreAccounting.evalCourseNode(root).getPassed()).as("root").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(sp_0_1).getPassed()).as("sp_0_1").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(st_1).getPassed()).as("st_1").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(st_1_1).getPassed()).as("sp_1_1").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(cl_1_1_1).getPassed()).as("cl_1_1_1").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(st_2).getPassed()).as("st_2").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(ms_2_1).getPassed()).as("ms_2_1").isNull(); + softly.assertAll(); + + // The participant passes ms_2_1 + setPassed(participant, courseEntry, ms_2_1); + scoreAccounting.evaluateAll(true); + dbInstance.commitAndCloseSession(); + + softly = new SoftAssertions(); + softly.assertThat(scoreAccounting.evalCourseNode(root).getPassed()).as("root").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(sp_0_1).getPassed()).as("sp_0_1").isNull(); + softly.assertThat(scoreAccounting.evalCourseNode(st_1).getPassed()).as("st_1").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(st_1_1).getPassed()).as("sp_1_1").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(cl_1_1_1).getPassed()).as("cl_1_1_1").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(st_2).getPassed()).as("st_2").isTrue(); + softly.assertThat(scoreAccounting.evalCourseNode(ms_2_1).getPassed()).as("ms_2_1").isTrue(); + softly.assertAll(); + } + + private void setPassed(Identity identity, RepositoryEntry entry, CourseNode courseNode) { + AssessmentEntry assessmentEntry = assessmentService.loadAssessmentEntry(identity, entry, courseNode.getIdent()); + assessmentEntry.setPassed(Boolean.TRUE); + assessmentService.updateAssessmentEntry(assessmentEntry); + dbInstance.commitAndCloseSession(); + } + +} diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index 5e880f0b8357cbacbdaa609bc75000532c2116bb..f41a49b23ede4dbee6b80786532dfdaa9411ba5b 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -174,6 +174,7 @@ import org.junit.runners.Suite; org.olat.instantMessaging.InstantMessageServiceTest.class, org.olat.course.archiver.FormatConfigHelperTest.class, org.olat.course.condition.ConditionTest.class, + org.olat.course.condition.GetPassedTest.class, org.olat.course.condition.KeyAndNameConverterTest.class, org.olat.course.disclaimer.CourseDisclaimerManagerTest.class, org.olat.course.highscore.HighScoreManagerTest.class,