Something went wrong on our end
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
GTACourseNode.java 32.09 KiB
/**
* <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;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
import org.olat.basesecurity.IdentityRef;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.stack.BreadcrumbPanel;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.messages.MessageUIFactory;
import org.olat.core.gui.control.generic.tabbable.TabbableController;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.id.Roles;
import org.olat.core.logging.OLATRuntimeException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.ExportUtil;
import org.olat.core.util.FileUtils;
import org.olat.core.util.Formatter;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;
import org.olat.core.util.ZipUtil;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSItem;
import org.olat.core.util.vfs.restapi.SystemItemFilter;
import org.olat.course.CourseFactory;
import org.olat.course.ICourse;
import org.olat.course.archiver.ScoreAccountingHelper;
import org.olat.course.assessment.AssessmentManager;
import org.olat.course.auditing.UserNodeAuditManager;
import org.olat.course.editor.CourseEditorEnv;
import org.olat.course.editor.NodeEditController;
import org.olat.course.editor.PublishEvents;
import org.olat.course.editor.StatusDescription;
import org.olat.course.nodes.gta.GTAManager;
import org.olat.course.nodes.gta.GTAType;
import org.olat.course.nodes.gta.Task;
import org.olat.course.nodes.gta.TaskHelper;
import org.olat.course.nodes.gta.TaskList;
import org.olat.course.nodes.gta.ui.GTAAssessmentDetailsController;
import org.olat.course.nodes.gta.ui.GTAEditController;
import org.olat.course.nodes.gta.ui.GTAGroupAssessmentToolController;
import org.olat.course.nodes.gta.ui.GTARunController;
import org.olat.course.run.environment.CourseEnvironment;
import org.olat.course.run.navigation.NodeRunConstructionResult;
import org.olat.course.run.scoring.ScoreEvaluation;
import org.olat.course.run.userview.NodeEvaluation;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.group.BusinessGroup;
import org.olat.modules.ModuleConfiguration;
import org.olat.repository.RepositoryEntry;
import org.olat.resource.OLATResource;
import org.olat.user.UserManager;
/**
*
* Initial date: 23.02.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class GTACourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode {
private final static OLog log = Tracing.createLoggerFor(GTACourseNode.class);
private final static String PACKAGE_GTA = Util.getPackageName(GTAEditController.class);
private static final long serialVersionUID = 1L;
/**
* Setting for group or individual task
*/
public static final String GTASK_TYPE = "grouptask.type";
public static final String GTASK_GROUPS = "grouptask.groups";
public static final String GTASK_AREAS = "grouptask.areas";
public static final String GTASK_ASSIGNMENT = "grouptask.assignement";
public static final String GTASK_ASSIGNMENT_DEADLINE = "grouptask.assignment.deadline";
public static final String GTASK_SUBMIT = "grouptask.submit";
public static final String GTASK_SUBMIT_DEADLINE = "grouptask.submit.deadline";
public static final String GTASK_REVIEW_AND_CORRECTION = "grouptask.review.and.correction";
public static final String GTASK_REVISION_PERIOD = "grouptask.revision.period";
public static final String GTASK_SAMPLE_SOLUTION = "grouptask.solution";
public static final String GTASK_SAMPLE_SOLUTION_VISIBLE_AFTER = "grouptask.solution.visible.after";
public static final String GTASK_GRADING = "grouptask.grading";
public static final String GTASK_TASKS = "grouptask.tasks";
public static final String GTASK_ASSIGNEMENT_TYPE = "grouptask.assignement.type";
public static final String GTASK_ASSIGNEMENT_TYPE_AUTO = "auto";
public static final String GTASK_ASSIGNEMENT_TYPE_MANUAL = "manual";
public static final String GTASK_USERS_TEXT = "grouptask.users.text";
public static final String GTASK_PREVIEW = "grouptask.preview";
public static final String GTASK_SAMPLING = "grouptask.sampling";
public static final String GTASK_SAMPLING_REUSE = "reuse";
public static final String GTASK_SAMPLING_UNIQUE = "unique";
public static final String GTASK_EXTERNAL_EDITOR = "grouptask.external.editor";
public static final String GTASK_EMBBEDED_EDITOR = "grouptask.embbeded.editor";
public static final String GTASK_MAX_SUBMITTED_DOCS = "grouptask.max.submitted.docs";
public static final String GTASK_SUBMISSION_TEXT = "grouptask.submission.text";
public static final String GTASK_SUBMISSION_MAIL_CONFIRMATION = "grouptask.submission.mail.confirmation";
public static final String GTASK_SOLUTIONS = "grouptask.solutions";
private static final String TYPE = "gta";
public GTACourseNode() {
super(TYPE);
updateModuleConfigDefaults(true);
}
@Override
public boolean needsReferenceToARepositoryEntry() {
return false;
}
@Override
public RepositoryEntry getReferencedRepositoryEntry() {
return null;
}
@Override
public void updateModuleConfigDefaults(boolean isNewNode) {
if(isNewNode) {
//setup default configuration
ModuleConfiguration config = getModuleConfiguration();
//group task
config.setStringValue(GTASK_TYPE, GTAType.group.name());
//manual choice
config.setStringValue(GTASK_ASSIGNEMENT_TYPE, GTASK_ASSIGNEMENT_TYPE_MANUAL);
//all steps
config.setBooleanEntry(GTASK_ASSIGNMENT, true);
config.setBooleanEntry(GTASK_SUBMIT, true);
config.setBooleanEntry(GTASK_REVIEW_AND_CORRECTION, true);
config.setBooleanEntry(GTASK_REVISION_PERIOD, true);
config.setBooleanEntry(GTASK_SAMPLE_SOLUTION, true);
config.setBooleanEntry(GTASK_GRADING, true);
//editors
config.setBooleanEntry(GTACourseNode.GTASK_EXTERNAL_EDITOR, true);
config.setBooleanEntry(GTACourseNode.GTASK_EMBBEDED_EDITOR, true);
//reuse tasks
config.setStringValue(GTACourseNode.GTASK_SAMPLING, GTACourseNode.GTASK_SAMPLING_REUSE);
//configure grading
config.set(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD, Boolean.FALSE);
config.set(MSCourseNode.CONFIG_KEY_SCORE_MIN, new Float(0));
config.set(MSCourseNode.CONFIG_KEY_SCORE_MAX, new Float(0));
config.set(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD, Boolean.TRUE);
}
}
@Override
public StatusDescription isConfigValid() {
if (oneClickStatusCache != null && oneClickStatusCache.length > 0) {
return oneClickStatusCache[0];
}
List<StatusDescription> statusDescs = validateInternalConfiguration(null);
if(statusDescs.isEmpty()) {
statusDescs.add(StatusDescription.NOERROR);
}
oneClickStatusCache = StatusDescriptionHelper.sort(statusDescs);
return oneClickStatusCache[0];
}
@Override
public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
oneClickStatusCache = null;//delete the cache
List<StatusDescription> sds = isConfigValidWithTranslator(cev, PACKAGE_GTA, getConditionExpressions());
if(oneClickStatusCache != null && oneClickStatusCache.length > 0) {
//isConfigValidWithTranslator add first
sds.remove(oneClickStatusCache[0]);
}
sds.addAll(validateInternalConfiguration(cev));
oneClickStatusCache = StatusDescriptionHelper.sort(sds);
return oneClickStatusCache;
}
private List<StatusDescription> validateInternalConfiguration(CourseEditorEnv cev) {
List<StatusDescription> sdList = new ArrayList<>(5);
ModuleConfiguration config = getModuleConfiguration();
boolean hasScoring = config.getBooleanSafe(GTASK_GRADING);
if (hasScoring) {
if(!config.getBooleanSafe(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD)
&& !config.getBooleanSafe(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD)) {
addStatusErrorDescription("error.missing.score.config", GTAEditController.PANE_TAB_GRADING, sdList);
}
}
if(GTAType.group.name().equals(config.getStringValue(GTACourseNode.GTASK_TYPE))) {
List<Long> groupKeys = config.getList(GTACourseNode.GTASK_GROUPS, Long.class);
List<Long> areaKeys = config.getList(GTACourseNode.GTASK_AREAS, Long.class);
if(groupKeys.isEmpty() && areaKeys.isEmpty()) {
addStatusErrorDescription("error.missing.group", GTAEditController.PANE_TAB_GRADING, sdList);
}
}
//at least one step
if(!config.getBooleanSafe(GTACourseNode.GTASK_ASSIGNMENT) && !config.getBooleanSafe(GTACourseNode.GTASK_SUBMIT)
&& !config.getBooleanSafe(GTACourseNode.GTASK_REVIEW_AND_CORRECTION) && !config.getBooleanSafe(GTACourseNode.GTASK_REVISION_PERIOD)
&& !config.getBooleanSafe(GTACourseNode.GTASK_SAMPLE_SOLUTION) && !config.getBooleanSafe(GTACourseNode.GTASK_GRADING)) {
addStatusErrorDescription("error.select.atleastonestep", GTAEditController.PANE_TAB_WORKLOW, sdList);
}
if(cev != null) {
//check assignment
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
OLATResource courseOres = cev.getCourseGroupManager().getCourseResource();
ICourse course = CourseFactory.loadCourse(courseOres);
if(config.getBooleanSafe(GTACourseNode.GTASK_ASSIGNMENT)) {
File taskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), this);
if(!TaskHelper.hasDocuments(taskDirectory)) {
addStatusErrorDescription("error.missing.tasks", GTAEditController.PANE_TAB_ASSIGNMENT, sdList);
}
}
//check solutions
if(config.getBooleanSafe(GTACourseNode.GTASK_SAMPLE_SOLUTION)) {
File solutionDirectory = gtaManager.getSolutionsDirectory(course.getCourseEnvironment(), this);
if(!TaskHelper.hasDocuments(solutionDirectory)) {
addStatusErrorDescription("error.missing.solutions", GTAEditController.PANE_TAB_SOLUTIONS, sdList);
}
}
List<IdentityRef> participants = gtaManager.getDuplicatedMemberships(this);
if(participants.size() > 0) {
UserManager um = CoreSpringFactory.getImpl(UserManager.class);
StringBuilder sb = new StringBuilder();
for(IdentityRef participant:participants) {
String fullname = um.getUserDisplayName(participant.getKey());
if(sb.length() > 0) sb.append(", ");
sb.append(fullname);
}
String[] params = new String[] { getShortTitle(), sb.toString() };
StatusDescription sd = new StatusDescription(StatusDescription.WARNING, "error.duplicate.memberships", "error.duplicate.memberships", params, PACKAGE_GTA);
sd.setDescriptionForUnit(getIdent());
sd.setActivateableViewIdentifier(GTAEditController.PANE_TAB_WORKLOW);
sdList.add(sd);
}
}
return sdList;
}
private void addStatusErrorDescription(String key, String pane, List<StatusDescription> status) {
String[] params = new String[] { getShortTitle() };
StatusDescription sd = new StatusDescription(StatusDescription.ERROR, key, key, params, PACKAGE_GTA);
sd.setDescriptionForUnit(getIdent());
sd.setActivateableViewIdentifier(pane);
status.add(sd);
}
/**
*
* The files are exported in export/{node ident}/tasks and export/{node ident}/solutions
*
*/
@Override
public void exportNode(File fExportDirectory, ICourse course) {
File fNodeExportDir = new File(fExportDirectory, getIdent());
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
// export the tasks
File tasksExportDir = new File(fNodeExportDir, "tasks");
File taskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), this);
fNodeExportDir.mkdirs();
FileUtils.copyDirContentsToDir(taskDirectory, tasksExportDir, false, "export task course node");
//export the solutions
File fSolExportDir = new File(fNodeExportDir, "solutions");
File solutionsDirectory = gtaManager.getSolutionsDirectory(course.getCourseEnvironment(), this);
fSolExportDir.mkdirs();
FileUtils.copyDirContentsToDir(solutionsDirectory, fSolExportDir, false, "export task course node solutions");
}
@Override
public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale, boolean withReferences) {
File fNodeImportDir = new File(importDirectory, getIdent());
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
//import tasks
File tasksImportDir = new File(fNodeImportDir, "tasks");
File taskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), this);
FileUtils.copyDirContentsToDir(tasksImportDir, taskDirectory, false, "import task course node");
//import solutions
File fSolImportDir = new File(fNodeImportDir, "solutions");
File solutionsDirectory = gtaManager.getSolutionsDirectory(course.getCourseEnvironment(), this);
FileUtils.copyDirContentsToDir(fSolImportDir, solutionsDirectory, false, "import task course node solutions");
}
@Override
public CourseNode createInstanceForCopy(boolean isNewTitle, ICourse course) {
GTACourseNode cNode = (GTACourseNode)super.createInstanceForCopy(isNewTitle, course);
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
//copy tasks
File taskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), this);
File copyTaskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), cNode);
FileUtils.copyDirContentsToDir(taskDirectory, copyTaskDirectory, false, "copy task course node");
//copy solutions
File solutionsDirectory = gtaManager.getSolutionsDirectory(course.getCourseEnvironment(), this);
File copySolutionsDirectory = gtaManager.getSolutionsDirectory(course.getCourseEnvironment(), cNode);
FileUtils.copyDirContentsToDir(solutionsDirectory, copySolutionsDirectory, false, "copy task course node solutions");
return cNode;
}
@Override
public boolean archiveNodeData(Locale locale, ICourse course, ArchiveOptions options, ZipOutputStream exportStream, String charset) {
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
String dirName = "grouptask_"
+ StringHelper.transformDisplayNameToFileSystemName(getShortName())
+ "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis()));
TaskList taskList = gtaManager.getTaskList(course.getCourseEnvironment().getCourseGroupManager().getCourseEntry(), this);
//save assessment datas
List<Identity> users = null;
ModuleConfiguration config = getModuleConfiguration();
if(config.getBooleanSafe(GTASK_GRADING)) {
users = ScoreAccountingHelper.loadUsers(course.getCourseEnvironment(), options);
String courseTitle = course.getCourseTitle();
String fileName = ExportUtil.createFileNameWithTimeStamp(courseTitle, "xls");
List<AssessableCourseNode> nodes = Collections.<AssessableCourseNode>singletonList(this);
String s = ScoreAccountingHelper.createCourseResultsOverviewTable(users, nodes, course, locale);
// write course results overview table to filesystem
try {
exportStream.putNextEntry(new ZipEntry(dirName + "/" + fileName));
IOUtils.write(s, exportStream);
exportStream.closeEntry();
} catch (IOException e) {
log.error("", e);
}
}
//copy tasks
if(taskList != null) {
if(GTAType.group.name().equals(config.getStringValue(GTACourseNode.GTASK_TYPE))) {
List<BusinessGroup> selectedGroups;
if(options.getGroup() != null) {
selectedGroups = Collections.singletonList(options.getGroup());
} else {
selectedGroups = gtaManager.getBusinessGroups(this);
}
for(BusinessGroup businessGroup:selectedGroups) {
archiveNodeData(locale, course, businessGroup, taskList, dirName, exportStream);
}
} else {
if(users == null) {
users = ScoreAccountingHelper.loadUsers(course.getCourseEnvironment(), options);
}
Set<Identity> uniqueUsers = new HashSet<>(users);
for(Identity user: uniqueUsers) {
archiveNodeData(locale, course, user, taskList, dirName, exportStream);
}
}
}
//copy solutions
if(config.getBooleanSafe(GTACourseNode.GTASK_SAMPLE_SOLUTION)) {
VFSContainer solutions = gtaManager.getSolutionsContainer(course.getCourseEnvironment(), this);
if (solutions.exists()) {
String solutionDirName = dirName + "/solutions";
for(VFSItem solution:solutions.getItems(new SystemItemFilter())) {
ZipUtil.addToZip(solution, solutionDirName, exportStream);
}
}
}
return true;
}
private void archiveNodeData(Locale locale, ICourse course, Identity assessedIdentity, TaskList taskList, String dirName, ZipOutputStream exportStream) {
ModuleConfiguration config = getModuleConfiguration();
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
int flow = 0;//for beautiful ordering
String userDirName = dirName + "/"
+ StringHelper.transformDisplayNameToFileSystemName(assessedIdentity.getName())
+ "_" + assessedIdentity.getKey();
Task task = gtaManager.getTask(assessedIdentity, taskList);
if(task != null && config.getBooleanSafe(GTASK_ASSIGNMENT)) {
File taskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), this);
File taskFile = new File(taskDirectory, task.getTaskName());
if(taskFile.exists()) {
String path = userDirName + "/" + (++flow) + "_task/" + taskFile.getName();
ZipUtil.addFileToZip(path, taskFile, exportStream);
}
}
if(config.getBooleanSafe(GTASK_SUBMIT)) {
File submitDirectory = gtaManager.getSubmitDirectory(course.getCourseEnvironment(), this, assessedIdentity);
String submissionDirName = userDirName + "/" + (++flow) + "_submissions";
ZipUtil.addDirectoryToZip(submitDirectory.toPath(), submissionDirName, exportStream);
}
if(config.getBooleanSafe(GTACourseNode.GTASK_REVIEW_AND_CORRECTION)) {
File correctionsDir = gtaManager.getCorrectionDirectory(course.getCourseEnvironment(), this, assessedIdentity);
String correctionDirName = userDirName + "/" + (++flow) + "_corrections";
ZipUtil.addDirectoryToZip(correctionsDir.toPath(), correctionDirName, exportStream);
}
if(task != null && config.getBooleanSafe(GTACourseNode.GTASK_REVISION_PERIOD)) {
int numOfIteration = task.getRevisionLoop();
for(int i=1; i<=numOfIteration; i++) {
File revisionDirectory = gtaManager.getRevisedDocumentsDirectory(course.getCourseEnvironment(), this, i, assessedIdentity);
String revisionDirName = userDirName + "/" + (++flow) + "_revisions_" + i;
ZipUtil.addDirectoryToZip(revisionDirectory.toPath(), revisionDirName, exportStream);
File correctionDirectory = gtaManager.getRevisedDocumentsCorrectionsDirectory(course.getCourseEnvironment(), this, i, assessedIdentity);
String correctionDirName = userDirName + "/" + (++flow) + "_corrections_" + i;
ZipUtil.addDirectoryToZip(correctionDirectory.toPath(), correctionDirName, exportStream);
}
}
}
private void archiveNodeData(Locale locale, ICourse course, BusinessGroup businessGroup, TaskList taskList, String dirName, ZipOutputStream exportStream) {
ModuleConfiguration config = getModuleConfiguration();
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
int flow = 0;//for beautiful ordering
String groupDirName = dirName + "/"
+ StringHelper.transformDisplayNameToFileSystemName(businessGroup.getName())
+ "_" + businessGroup.getKey();
Task task = gtaManager.getTask(businessGroup, taskList);
if(task != null && config.getBooleanSafe(GTASK_ASSIGNMENT)) {
File taskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), this);
File taskFile = new File(taskDirectory, task.getTaskName());
if(taskFile.exists()) {
String path = groupDirName + "/" + (++flow) + "_task/" + taskFile.getName();
ZipUtil.addFileToZip(path, taskFile, exportStream);
}
}
if(config.getBooleanSafe(GTASK_SUBMIT)) {
File submitDirectory = gtaManager.getSubmitDirectory(course.getCourseEnvironment(), this, businessGroup);
String submissionDirName = groupDirName + "/" + (++flow) + "_submissions";
ZipUtil.addDirectoryToZip(submitDirectory.toPath(), submissionDirName, exportStream);
}
if(config.getBooleanSafe(GTACourseNode.GTASK_REVIEW_AND_CORRECTION)) {
File correctionsDir = gtaManager.getCorrectionDirectory(course.getCourseEnvironment(), this, businessGroup);
String correctionDirName = groupDirName + "/" + (++flow) + "_corrections";
ZipUtil.addDirectoryToZip(correctionsDir.toPath(), correctionDirName, exportStream);
}
if(task != null && config.getBooleanSafe(GTACourseNode.GTASK_REVISION_PERIOD)) {
int numOfIteration = task.getRevisionLoop();
for(int i=1; i<=numOfIteration; i++) {
File revisionDirectory = gtaManager.getRevisedDocumentsDirectory(course.getCourseEnvironment(), this, i, businessGroup);
String revisionDirName = groupDirName + "/" + (++flow) + "_revisions_" + i;
ZipUtil.addDirectoryToZip(revisionDirectory.toPath(), revisionDirName, exportStream);
File correctionDirectory = gtaManager.getRevisedDocumentsCorrectionsDirectory(course.getCourseEnvironment(), this, i, businessGroup);
String correctionDirName = groupDirName + "/" + (++flow) + "_corrections_" + i;
ZipUtil.addDirectoryToZip(correctionDirectory.toPath(), correctionDirName, exportStream);
}
}
}
@Override
public void cleanupOnDelete(ICourse course) {
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
//tasks
File taskDirectory = gtaManager.getTasksDirectory(course.getCourseEnvironment(), this);
FileUtils.deleteDirsAndFiles(taskDirectory, true, true);
//TODO the rest
//solutions
File solutionsDirectory = gtaManager.getSolutionsDirectory(course.getCourseEnvironment(), this);
FileUtils.deleteDirsAndFiles(solutionsDirectory, true, true);
}
@Override
public boolean hasStatusConfigured() {
return true; // Task Course node has always a status-field
}
@Override
public Float getMaxScoreConfiguration() {
if (!hasScoreConfigured()) {
throw new OLATRuntimeException(TACourseNode.class, "getMaxScore not defined when hasScore set to false", null);
}
return getModuleConfiguration().getFloatEntry(MSCourseNode.CONFIG_KEY_SCORE_MAX);
}
@Override
public Float getMinScoreConfiguration() {
if (!hasScoreConfigured()) {
throw new OLATRuntimeException(TACourseNode.class, "getMinScore not defined when hasScore set to false", null);
}
return getModuleConfiguration().getFloatEntry(MSCourseNode.CONFIG_KEY_SCORE_MIN);
}
@Override
public Float getCutValueConfiguration() {
if (!hasPassedConfigured()) {
throw new OLATRuntimeException(TACourseNode.class, "getCutValue not defined when hasPassed set to false", null);
}
return getModuleConfiguration().getFloatEntry(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
}
@Override
public boolean hasScoreConfigured() {
boolean hasGrading = getModuleConfiguration().getBooleanSafe(GTASK_GRADING);
if (hasGrading) {
Boolean score = (Boolean) getModuleConfiguration().get(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD);
if (score != null) {
return score.booleanValue();
}
}
return false;
}
@Override
public boolean hasPassedConfigured() {
boolean hasGrading = getModuleConfiguration().getBooleanSafe(GTASK_GRADING);
if (hasGrading) {
Boolean passed = (Boolean)getModuleConfiguration().get(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD);
if (passed != null) {
return passed.booleanValue();
}
}
return false;
}
@Override
public boolean hasCommentConfigured() {
boolean hasGrading = getModuleConfiguration().getBooleanSafe(GTASK_GRADING);
if (hasGrading) {
Boolean comment = (Boolean) getModuleConfiguration().get(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD);
if (comment != null) {
return comment.booleanValue();
}
}
return false;
}
@Override
public boolean hasAttemptsConfigured(){
return true;
}
@Override
public boolean hasDetails() {
ModuleConfiguration config = getModuleConfiguration();
return config.getBooleanSafe(GTASK_ASSIGNMENT)
|| config.getBooleanSafe(GTASK_SUBMIT)
|| config.getBooleanSafe(GTASK_REVIEW_AND_CORRECTION)
|| config.getBooleanSafe(GTASK_REVISION_PERIOD);
}
@Override
public boolean isEditableConfigured() {
return true;
}
@Override
public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
ICourse course, UserCourseEnvironment euce) {
GTAEditController editCtrl = new GTAEditController(ureq, wControl, this, course, euce);
CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, euce, editCtrl);
}
@Override
public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
UserCourseEnvironment userCourseEnv, NodeEvaluation ne, String nodecmd) {
Controller controller;
Roles roles = ureq.getUserSession().getRoles();
if (roles.isGuestOnly()) {
Translator trans = Util.createPackageTranslator(GTACourseNode.class, ureq.getLocale());
String title = trans.translate("guestnoaccess.title");
String message = trans.translate("guestnoaccess.message");
controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
} else {
controller = new GTARunController(ureq, wControl, this, userCourseEnv);
}
Controller ctrl = TitledWrapperHelper.getWrapper(ureq, wControl, controller, this, "o_gta_icon");
return new NodeRunConstructionResult(ctrl);
}
@Override
public void updateOnPublish(Locale locale, ICourse course, Identity publisher, PublishEvents publishEvents) {
RepositoryEntry re = course.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
CoreSpringFactory.getImpl(GTAManager.class).createIfNotExists(re, this);
super.updateOnPublish(locale, course, publisher, publishEvents);
}
@Override
public String getDetailsListViewHeaderKey() {
return "table.header.details.gta";
}
@Override
public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) {
GTAManager gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
Identity assessedIdentity = userCourseEnvironment.getIdentityEnvironment().getIdentity();
RepositoryEntry entry = userCourseEnvironment.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
List<Task> tasks = gtaManager.getTasks(assessedIdentity, entry, this);
String details;
if(tasks == null || tasks.isEmpty()) {
details = null;
} else {
StringBuilder sb = new StringBuilder();
for(Task task:tasks) {
if(sb.length() > 0) sb.append(", ");
if(sb.length() > 64) {
sb.append("...");
break;
}
sb.append(StringHelper.escapeHtml(task.getTaskName()));
}
details = sb.toString();
}
return details;
}
@Override
public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl,
BreadcrumbPanel stackPanel, UserCourseEnvironment userCourseEnvironment) {
return new GTAAssessmentDetailsController(ureq, wControl, userCourseEnvironment, this);
}
@Override
public List<Controller> createAssessmentTools(UserRequest ureq, WindowControl wControl,
TooledStackedPanel stackPanel, CourseEnvironment courseEnv, AssessmentToolOptions options) {
ModuleConfiguration config = getModuleConfiguration();
List<Controller> tools = new ArrayList<>(1);
if(options.getGroup() != null && GTAType.group.name().equals(config.getStringValue(GTACourseNode.GTASK_TYPE))
&& (config.getBooleanSafe(GTASK_ASSIGNMENT)
|| config.getBooleanSafe(GTASK_SUBMIT)
|| config.getBooleanSafe(GTASK_REVIEW_AND_CORRECTION)
|| config.getBooleanSafe(GTASK_REVISION_PERIOD))) {
Controller tool = new GTAGroupAssessmentToolController(ureq, wControl, courseEnv, options.getGroup(), this);
tools.add(tool);
}
return tools;
}
@Override
public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
Boolean passed = null;
Float score = null;
// only db lookup if configured, else return null
if (hasPassedConfigured()) {
passed = am.getNodePassed(this, assessedIdentity);
}
if (hasScoreConfigured()) {
score = am.getNodeScore(this, assessedIdentity);
}
return new ScoreEvaluation(score, passed);
}
@Override
public String getUserUserComment(UserCourseEnvironment userCourseEnv) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
return am.getNodeComment(this, userCourseEnv.getIdentityEnvironment().getIdentity());
}
@Override
public String getUserCoachComment(UserCourseEnvironment userCourseEnv) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
return am.getNodeCoachComment(this, userCourseEnv.getIdentityEnvironment().getIdentity());
}
@Override
public String getUserLog(UserCourseEnvironment userCourseEnv) {
UserNodeAuditManager am = userCourseEnv.getCourseEnvironment().getAuditManager();
return am.getUserNodeLog(this, userCourseEnv.getIdentityEnvironment().getIdentity());
}
@Override
public Integer getUserAttempts(UserCourseEnvironment userCourseEnv) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
return am.getNodeAttempts(this, assessedIdentity);
}
@Override
public void updateUserScoreEvaluation(ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnv,
Identity coachingIdentity, boolean incrementAttempts) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
am.saveScoreEvaluation(this, coachingIdentity, assessedIdentity, new ScoreEvaluation(scoreEvaluation.getScore(), scoreEvaluation.getPassed()), userCourseEnv, incrementAttempts);
}
@Override
public void updateUserUserComment(String userComment, UserCourseEnvironment userCourseEnv, Identity coachingIdentity) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
if (userComment != null) {
am.saveNodeComment(this, coachingIdentity, assessedIdentity, userComment);
}
}
@Override
public void incrementUserAttempts(UserCourseEnvironment userCourseEnv) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
am.incrementNodeAttempts(this, assessedIdentity, userCourseEnv);
}
@Override
public void updateUserAttempts(Integer userAttempts, UserCourseEnvironment userCourseEnv, Identity coachingIdentity) {
if (userAttempts != null) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
am.saveNodeAttempts(this, coachingIdentity, assessedIdentity, userAttempts);
}
}
@Override
public void updateUserCoachComment(String coachComment, UserCourseEnvironment userCourseEnv) {
AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
if (coachComment != null) {
am.saveNodeCoachComment(this, assessedIdentity, coachComment);
}
}
}