Skip to content
Snippets Groups Projects
Commit 2c9fcd00 authored by srosse's avatar srosse
Browse files

OO-4161: additional option to relax access if results are visible

parent 2efa24e7
No related branches found
No related tags found
No related merge requests found
......@@ -36,7 +36,7 @@ import org.olat.core.util.StringHelper;
* @author Mike Stock Comment:
*/
public class Condition implements Serializable, Cloneable {
transient private String conditionId = null;
private transient String conditionId = null;
private String condition = null;
private boolean expertMode = false;
......@@ -60,6 +60,8 @@ public class Condition implements Serializable, Cloneable {
// true: only in assessment mode
private boolean assessmentMode;
private boolean assessmentModeViewResults;
private String easyModeAssessmentModeNodeId;
// This is the MapList in which the extended easy mode conditions are stored
private List<ExtendedCondition> attributeConditions = null;
......@@ -233,7 +235,7 @@ public class Condition implements Serializable, Cloneable {
String[] longStrArr = ids.split(",");
List<Long> keys = new ArrayList<>(longStrArr.length);
for(String longStr:longStrArr) {
keys.add(new Long(longStr.trim()));
keys.add(Long.valueOf(longStr.trim()));
}
return keys;
}
......@@ -262,6 +264,22 @@ public class Condition implements Serializable, Cloneable {
this.assessmentMode = assessmentMode;
}
public boolean isAssessmentModeViewResults() {
return assessmentModeViewResults;
}
public void setAssessmentModeViewResults(boolean viewResults) {
this.assessmentModeViewResults = viewResults;
}
public String getEasyModeAssessmentModeNodeId() {
return easyModeAssessmentModeNodeId;
}
public void setEasyModeAssessmentModeNodeId(String nodeId) {
this.easyModeAssessmentModeNodeId = nodeId;
}
/**
* @return true
*/
......@@ -311,7 +329,7 @@ public class Condition implements Serializable, Cloneable {
*/
public String getConditionFromEasyModeConfiguration() {
boolean needsAmpersand = false;
StringBuilder sb = new StringBuilder();
StringBuilder sb = new StringBuilder(512);
sb.append("( "); // BEGIN all enclosing bracket
......@@ -391,7 +409,12 @@ public class Condition implements Serializable, Cloneable {
}
if(isAssessmentMode()) {
if (needsAmpersand) sb.append(" & ");
sb.append(" isAssessmentMode(0)");
if(isAssessmentModeViewResults()) {
sb.append(" isAssessmentMode(\"").append(getEasyModeAssessmentModeNodeId()).append("\",true)");
} else {
sb.append(" isAssessmentMode(0)");
}
needsAmpersand = true;
}
if (isEasyModeCoachesAndAdmins()) {
......
......@@ -90,6 +90,7 @@ public class ConditionConfigEasyController extends FormBasicController implement
private List<CourseNode> nodeIdentList;
private MultipleSelectionElement coachExclusive;
private MultipleSelectionElement assessmentMode;
private MultipleSelectionElement assessmentModeResultVisible;
private JSDateChooser fromDate;
private JSDateChooser toDate;
private FormItemContainer dateSubContainer;
......@@ -189,7 +190,8 @@ public class ConditionConfigEasyController extends FormBasicController implement
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
// or blocked for learner
coachExclusive = uifactory.addCheckboxesHorizontal("coachExclusive", null, formLayout, new String[] { "ison" }, new String[] { translate("form.easy.coachExclusive") });
coachExclusive = uifactory.addCheckboxesHorizontal("coachExclusive", null, formLayout,
new String[] { "ison" }, new String[] { translate("form.easy.coachExclusive") });
coachExclusive.setElementCssClass("o_sel_condition_coach_exclusive");
coachExclusive.addActionListener(FormEvent.ONCLICK);
if(validatedCondition.isEasyModeCoachesAndAdmins()) {
......@@ -206,14 +208,23 @@ public class ConditionConfigEasyController extends FormBasicController implement
}
flc.contextPut("shibbolethEnabled", Boolean.valueOf(enableShibbolethEasyConfig));
assessmentMode = uifactory.addCheckboxesHorizontal("assessmentMode", null, formLayout, new String[] { "ison" }, new String[] { translate("form.easy.assessmentMode") });
assessmentMode = uifactory.addCheckboxesHorizontal("assessmentMode", null, formLayout,
new String[] { "ison" }, new String[] { translate("form.easy.assessmentMode") });
if(validatedCondition.isAssessmentMode()) {
assessmentMode.select("ison", true);
}
assessmentMode.addActionListener(FormEvent.ONCLICK);
assessmentMode.setVisible(assessmentModule.isAssessmentModeEnabled());
applyRulesForCoach = uifactory.addCheckboxesHorizontal("applyRulesForCoach", null, formLayout, new String[] { "ison" }, new String[] { translate("form.easy.applyRulesForCoach") });
assessmentModeResultVisible = uifactory.addCheckboxesHorizontal("assessmentModeResultVisible", null, formLayout,
new String[] { "ison" }, new String[] { translate("form.easy.assessmentMode.visible") });
if(validatedCondition.isAssessmentModeViewResults()) {
assessmentModeResultVisible.select("ison", true);
}
assessmentModeResultVisible.setVisible(assessmentModule.isAssessmentModeEnabled() && assessmentMode.isAtLeastSelected(1));
applyRulesForCoach = uifactory.addCheckboxesHorizontal("applyRulesForCoach", null, formLayout,
new String[] { "ison" }, new String[] { translate("form.easy.applyRulesForCoach") });
applyRulesForCoach.setVisible(isDateGroupAssessmentOrAttributeSwitchOnOrAssessmentModeOn());
// note that in the condition this rule is saved with the opposite meaning:
// true when coach and admins always have access, false when rule should apply also to them
......@@ -452,6 +463,8 @@ public class ConditionConfigEasyController extends FormBasicController implement
validatedCondition.setAttributeConditions(null);
validatedCondition.setAttributeConditionsConnectorIsAND(null);
validatedCondition.setAssessmentMode(false);
validatedCondition.setAssessmentModeViewResults(false);
validatedCondition.setEasyModeAssessmentModeNodeId(null);
validatedCondition.setEasyModeGroupAccessIdList(null);
validatedCondition.setEasyModeGroupAreaAccessIdList(null);
} else {
......@@ -540,6 +553,15 @@ public class ConditionConfigEasyController extends FormBasicController implement
// assessment mode
validatedCondition.setAssessmentMode(assessmentMode.isAtLeastSelected(1));
if(assessmentMode.isAtLeastSelected(1) && assessmentModeResultVisible.isAtLeastSelected(1)) {
validatedCondition.setAssessmentModeViewResults(true);
String currentNodeId = courseEditorEnv.getCurrentCourseNodeId();
validatedCondition.setEasyModeAssessmentModeNodeId(currentNodeId);
} else {
validatedCondition.setAssessmentModeViewResults(false);
validatedCondition.setEasyModeAssessmentModeNodeId(null);
}
}
// calculate expression from easy mode form
......@@ -883,6 +905,9 @@ public class ConditionConfigEasyController extends FormBasicController implement
//assessment switch only enabled if nodes to be selected
assessmentSwitch.setEnabled(!blockedForLearner && (!nodeIdentList.isEmpty() || isSelectedNodeDeleted()));
assessmentMode.setEnabled(!blockedForLearner);
assessmentModeResultVisible.setVisible(assessmentMode.isAtLeastSelected(1));
assessmentModeResultVisible.setEnabled(assessmentMode.isEnabled());
//default is a checked disabled apply rules for coach
if (attributeSwitch != null) {
......@@ -946,6 +971,7 @@ public class ConditionConfigEasyController extends FormBasicController implement
easyGroupList.setValue("");
easyGroupList.setUserObject(new ArrayList<Long>());
assessmentMode.uncheckAll();
assessmentModeResultVisible.uncheckAll();
// disable the shibboleth attributes switch and reset the row subform
if (attributeSwitch != null) {
......
......@@ -44,6 +44,9 @@
#end
$r.render("assessmentMode")
#if($r.visible("assessmentModeResultVisible"))
<div class="col-sm-offset-1">$r.render("assessmentModeResultVisible")</div>
#end
$r.render("applyRulesForCoach")
<div class="o_button_group">
$r.render("subm")
......
......@@ -71,6 +71,7 @@ form.easy.extCondConn.or=ODER
form.easy.group=Nur f\u00FCr die Lerngruppen
form.easy.groupSwitch=Gruppenabh\u00E4ngig
form.easy.assessmentMode=Nur in Pr\u00FCfungsmodus
form.easy.assessmentMode.visible=Sichtbar wenn Resultate ver\u00F6ffentlicht werden
form.easy.nodePassed=Kursbaustein
form.easy.nodePassed.deletedNode=Gel\u00F6schter Kursbaustein, bitte \u00E4ndern
form.easy.nodePassed.noNodes=Nicht m\u00F6glich - keine bewerteten Kursbausteine
......
......@@ -71,6 +71,7 @@ form.easy.extCondConn.or=OR
form.easy.group=Only for learning groups
form.easy.groupSwitch=Depending on group
form.easy.assessmentMode=Only in assessment mode
form.easy.assessmentMode.visible=Visible if the results are visible
form.easy.nodePassed=Course element
form.easy.nodePassed.deletedNode=Deleted course element, please modify.
form.easy.nodePassed.noNodes=Not possible, no assessed course element
......
......@@ -47,9 +47,6 @@ public class IsAssessmentModeFunction extends AbstractFunction {
super(userCourseEnv);
}
/**
* @see com.neemsoft.jmep.FunctionCB#call(java.lang.Object[])
*/
@Override
public Object call(Object[] inStack) {
/*
......@@ -57,6 +54,19 @@ public class IsAssessmentModeFunction extends AbstractFunction {
*/
CourseEditorEnv cev = getUserCourseEnv().getCourseEditorEnv();
if (cev != null) {
if(inStack != null && inStack.length == 2) {
if (!(inStack[0] instanceof String)) {
return handleException(new ArgumentParseException(ArgumentParseException.WRONG_ARGUMENT_FORMAT, name, "",
"error.argtype.coursnodeidexpeted", "solution.example.node.infunction"));
}
String nodeId = (String) inStack[0];
if (!cev.existsNode(nodeId)) {
return handleException( new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name, nodeId,
"error.notfound.coursenodeid", "solution.copypastenodeid"));
}
}
// return a valid value to continue with condition evaluation test
return defaultValue();
}
......@@ -70,19 +80,26 @@ public class IsAssessmentModeFunction extends AbstractFunction {
return ConditionInterpreter.INT_FALSE;
}
OLATResourceable lockedResource = chiefController.getLockResource();
if(lockedResource == null) {
return ConditionInterpreter.INT_FALSE;
boolean open = false;
if(inStack != null && inStack.length == 2) {
String nodeId = (String) inStack[0];
open = isAssessmentModeActive(lockedResource) ||
getUserCourseEnv().getScoreAccounting().evalUserVisibleOfCourseNode(nodeId);
} else {
open = isAssessmentModeActive(lockedResource);
}
return open ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
}
private boolean isAssessmentModeActive(OLATResourceable lockedResource) {
Long resourceableId = getUserCourseEnv().getCourseEnvironment().getCourseResourceableId();
if(lockedResource.getResourceableId().equals(resourceableId)) {
if(lockedResource != null && lockedResource.getResourceableId().equals(resourceableId)) {
RepositoryEntry entry = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager().getCourseEntry();
AssessmentModeManager assessmentModeMgr = CoreSpringFactory.getImpl(AssessmentModeManager.class);
boolean inAssessment = assessmentModeMgr.isInAssessmentMode(entry, new Date());
return inAssessment ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
} else {
return ConditionInterpreter.INT_FALSE;
return assessmentModeMgr.isInAssessmentMode(entry, new Date());
}
return false;
}
@Override
......
......@@ -217,7 +217,7 @@ public class ScoreAccounting {
AssessmentEntryStatus assessmentStatus = AssessmentEntryStatus.inProgress;
ConditionInterpreter ci = userCourseEnvironment.getConditionInterpreter();
if (cNode.hasScoreConfigured() && scoreExpressionStr != null) {
score = new Float(ci.evaluateCalculation(scoreExpressionStr));
score = Float.valueOf(ci.evaluateCalculation(scoreExpressionStr));
}
if (cNode.hasPassedConfigured() && passedExpressionStr != null) {
boolean hasPassed = ci.evaluateCondition(passedExpressionStr);
......@@ -403,15 +403,15 @@ public class ScoreAccounting {
if(se.getUserVisible() == null || se.getUserVisible().booleanValue()) {
score = se.getScore();
} else {
score = new Float(0.0f);
score = Float.valueOf(0.0f);
}
}
if (score == null) { // a child has no score yet
score = new Float(0.0f); // default to 0.0, so that the condition can be evaluated (zero points makes also the most sense for "no results yet", if to be expressed in a number)
score = Float.valueOf(0.0f); // default to 0.0, so that the condition can be evaluated (zero points makes also the most sense for "no results yet", if to be expressed in a number)
}
} else {
error = true;
score = new Float(0.0f);
score = Float.valueOf(0.0f);
}
return score;
......@@ -472,7 +472,7 @@ public class ScoreAccounting {
AssessableCourseNode acn = (AssessableCourseNode) foundNode;
ScoreEvaluation se = evalCourseNode(acn);
if (se == null) { // the node could not provide any sensible information on scoring. e.g. a STNode with no calculating rules
log.error("could not evaluate node '" + acn.getShortTitle() + "' (" + acn.getClass().getName() + "," + childId + ")");
log.error("could not evaluate node '{}' ({},{})", acn.getShortTitle(), acn.getClass().getName(), childId);
return Boolean.FALSE;
}
// check if the results are visible
......@@ -485,6 +485,26 @@ public class ScoreAccounting {
}
return passed;
}
public boolean evalUserVisibleOfCourseNode(String childId) {
CourseNode foundNode = findChildByID(childId);
if (foundNode == null) {
error = true;
return Boolean.FALSE;
}
if (!(foundNode instanceof AssessableCourseNode)) {
error = true;
return Boolean.FALSE;
}
AssessableCourseNode acn = (AssessableCourseNode) foundNode;
ScoreEvaluation se = evalCourseNode(acn);
if (se == null) { // the node could not provide any sensible information on scoring. e.g. a STNode with no calculating rules
log.error("could not evaluate node '{}' ({},{})", acn.getShortTitle(), acn.getClass().getName(), childId);
return Boolean.FALSE;
}
// check if the results are visible
return se.getUserVisible() != null && se.getUserVisible().booleanValue();
}
private CourseNode findChildByID(String id) {
return userCourseEnvironment.getCourseEnvironment().getRunStructure().getNode(id);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment