/** * <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.modules.forms.ui; import static org.olat.modules.forms.handler.EvaluationFormResource.FORM_XML_FILE; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.chart.RadarChartComponent.Format; import org.olat.core.gui.components.chart.RadarChartElement; import org.olat.core.gui.components.chart.RadarSeries; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; import org.olat.core.util.xml.XStreamHelper; import org.olat.fileresource.FileResourceManager; import org.olat.modules.forms.EvaluationFormManager; import org.olat.modules.forms.EvaluationFormResponse; import org.olat.modules.forms.EvaluationFormSession; import org.olat.modules.forms.EvaluationFormSessionStatus; import org.olat.modules.forms.model.xml.AbstractElement; import org.olat.modules.forms.model.xml.Form; import org.olat.modules.forms.model.xml.FormXStream; import org.olat.modules.forms.model.xml.Rubric; import org.olat.modules.forms.model.xml.Rubric.SliderType; import org.olat.modules.forms.model.xml.Slider; import org.olat.modules.forms.model.xml.TextInput; import org.olat.modules.forms.ui.component.SliderOverviewElement; import org.olat.modules.forms.ui.component.SliderPoint; import org.olat.modules.forms.ui.model.EvaluationFormElementWrapper; import org.olat.modules.forms.ui.model.Evaluator; import org.olat.modules.forms.ui.model.SliderWrapper; import org.olat.modules.forms.ui.model.TextInputWrapper; import org.olat.modules.portfolio.PageBody; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; /** * * Initial date: 19 déc. 2016<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class CompareEvaluationsFormController extends FormBasicController { private static final String[] colors = new String[]{ "#EDC951", "#CC333F", "#00A0B0", "#4E4E6C", "#8DC1A1", "#F7BC00", "#BB6511", "#B28092", "#003D40", "#FF69D1" }; private int count = 0; private final Form form; private PageBody anchor; private final List<Evaluator> evaluators; private EvaluationFormSession session; private final Map<String, List<EvaluationFormResponse>> identifierToResponses = new HashMap<>(); private final Map<Identity,String> evaluatorToColors = new HashMap<>(); private final Map<Identity,Evaluator> evaluatorToNumbers = new HashMap<>(); @Autowired private EvaluationFormManager evaluationFormManager; /** * The responses are saved and linked to the anchor. * * @param ureq * @param wControl * @param form * @param anchor The database object which hold the evaluation. */ public CompareEvaluationsFormController(UserRequest ureq, WindowControl wControl, List<Evaluator> evaluators, PageBody anchor, RepositoryEntry formEntry) { super(ureq, wControl, "run"); this.anchor = anchor; this.evaluators = evaluators; int colorCount = 0; for(Evaluator evaluator:evaluators) { int i = (colorCount++) % colors.length; evaluatorToColors.put(evaluator.getIdentity(), colors[i]); evaluatorToNumbers.put(evaluator.getIdentity(), evaluator); } File repositoryDir = new File(FileResourceManager.getInstance().getFileResourceRoot(formEntry.getOlatResource()), FileResourceManager.ZIPDIR); File formFile = new File(repositoryDir, FORM_XML_FILE); form = (Form)XStreamHelper.readObject(FormXStream.getXStream(), formFile); loadResponses(); initForm(ureq); } public EvaluationFormSession getSession() { return session; } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { updateElements(); } private void updateElements() { List<EvaluationFormElementWrapper> elementWrappers = new ArrayList<>(); for(AbstractElement element:form.getElements()) { appendsElement(element, elementWrappers); } flc.contextPut("elements", elementWrappers); } private void loadResponses() { flc.contextPut("messageNotDone", Boolean.FALSE); List<Identity> evaluatorIdentities = evaluators.stream().map(evaluator -> evaluator.getIdentity()).collect(Collectors.toList()); List<EvaluationFormResponse> responses = evaluationFormManager.getResponsesFromPortfolioEvaluation(evaluatorIdentities, anchor, EvaluationFormSessionStatus.done); for(EvaluationFormResponse response:responses) { List<EvaluationFormResponse> responseList = identifierToResponses.get(response.getResponseIdentifier()); if(responseList == null) { responseList = new ArrayList<>(); identifierToResponses.put(response.getResponseIdentifier(), responseList); } responseList.add(response); } } private void appendsElement(AbstractElement element, List<EvaluationFormElementWrapper> wrappers) { String type = element.getType(); switch(type) { case "formhtitle": case "formhr": case "formhtmlraw": wrappers.add(new EvaluationFormElementWrapper(element)); break; case "formrubric": Rubric rubric = (Rubric)element; EvaluationFormElementWrapper sliderWrapper; if(rubric.getSliders().size() > 2) { sliderWrapper = forgeRadarRubric((Rubric)element); } else { sliderWrapper = forgeRubric((Rubric)element); } if(sliderWrapper != null) { wrappers.add(sliderWrapper); } break; case "formtextinput": List<EvaluationFormElementWrapper> inputWrappers = forgeTextInput((TextInput)element); if(inputWrappers != null && inputWrappers.size() > 0) { wrappers.addAll(inputWrappers); } break; } } private List<EvaluationFormElementWrapper> forgeTextInput(TextInput element) { List<EvaluationFormResponse> responses = identifierToResponses.get(element.getId()); if (responses == null) { // in review - selbstreview ?? return new ArrayList<EvaluationFormElementWrapper>(); } List<EvaluationFormElementWrapper> inputWrappers = new ArrayList<>(responses.size()); for(EvaluationFormResponse response:responses) { if(StringHelper.containsNonWhitespace(response.getStringuifiedResponse())) { String initialValue = response.getStringuifiedResponse(); if(initialValue != null) { initialValue = Formatter.stripTabsAndReturns(initialValue).toString(); } Identity evaluator = response.getSession().getIdentity(); String legend = getLegend(evaluator); String color = evaluatorToColors.get(evaluator); TextInputWrapper textInputWrapper = new TextInputWrapper(legend, color, initialValue, null); EvaluationFormElementWrapper wrapper = new EvaluationFormElementWrapper(element); wrapper.setTextInputWrapper(textInputWrapper); inputWrappers.add(wrapper); } } return inputWrappers; } private EvaluationFormElementWrapper forgeRubric(Rubric element) { EvaluationFormElementWrapper wrapper = new EvaluationFormElementWrapper(element); wrapper.setSliderOverview(true); List<Slider> sliders = element.getSliders(); List<SliderWrapper> sliderWrappers = new ArrayList<>(sliders.size()); for(Slider slider:sliders) { String responseIdentifier = slider.getId(); List<EvaluationFormResponse> responses = identifierToResponses.get(responseIdentifier); SliderWrapper sliderWrapper = forgeSliderStats(slider, element, responses); sliderWrappers.add(sliderWrapper); } wrapper.setSliders(sliderWrappers); return wrapper; } private EvaluationFormElementWrapper forgeRadarRubric(Rubric element) { EvaluationFormElementWrapper wrapper = new EvaluationFormElementWrapper(element); wrapper.setRadarOverview(true); List<String> axisList = new ArrayList<>(); List<Slider> sliders = element.getSliders(); Map<EvaluationFormSession,RadarSeries> series = new HashMap<>(); for(Slider slider:sliders) { String axis; if(StringHelper.containsNonWhitespace(slider.getStartLabel())) { axis = slider.getStartLabel(); } else if(StringHelper.containsNonWhitespace(slider.getEndLabel())) { axis = slider.getEndLabel(); } else { axis = ""; } axisList.add(axis); String responseIdentifier = slider.getId(); List<EvaluationFormResponse> responses = identifierToResponses.get(responseIdentifier); if(responses != null && responses.size() > 0) { for(EvaluationFormResponse response:responses) { EvaluationFormSession responseSession = response.getSession(); if(!series.containsKey(responseSession)) { Identity identity = responseSession.getIdentity(); String legend = getLegend(identity); String color = evaluatorToColors.get(identity); series.put(responseSession, new RadarSeries(legend, color)); } if(response.getNumericalResponse() != null ) { double value = response.getNumericalResponse().doubleValue(); series.get(responseSession).addPoint(axis, value); } } } } String id = "radar_" + (count++); RadarChartElement radarEl = new RadarChartElement(id); radarEl.setSeries(new ArrayList<>(series.values())); radarEl.setShowLegend(true); radarEl.setAxis(axisList); if(element.getSliderType() == SliderType.discrete || element.getSliderType() == SliderType.discrete_slider) { radarEl.setLevels(element.getSteps()); radarEl.setMaxValue(element.getSteps()); radarEl.setFormat(Format.integer); } else if(element.getSliderType() == SliderType.continuous) { radarEl.setLevels(10); radarEl.setMaxValue(100); radarEl.setFormat(Format.integer); } wrapper.setRadarEl(radarEl); flc.add(id, radarEl); return wrapper; } private SliderWrapper forgeSliderStats(Slider slider, Rubric element, List<EvaluationFormResponse> responses) { String id = "overview_" + (count++); SliderOverviewElement overviewEl = new SliderOverviewElement(id); overviewEl.setMinValue(element.getStart()); overviewEl.setMaxValue(element.getEnd()); flc.add(id, overviewEl); List<SliderPoint> values = new ArrayList<>(); if(responses != null && responses.size() > 0) { for(EvaluationFormResponse response:responses) { if(response.getNumericalResponse() != null) { Identity evaluator = response.getSession().getIdentity(); String color = evaluatorToColors.get(evaluator); double value = response.getNumericalResponse().doubleValue(); values.add(new SliderPoint(color, value)); } } } overviewEl.setValues(values); return new SliderWrapper(slider, overviewEl); } private String getLegend(Identity identity) { String legend; if(evaluatorToNumbers.containsKey(identity)) { legend = evaluatorToNumbers.get(identity).getFullName(); } else { legend = "???"; } return legend; } @Override protected void propagateDirtinessToContainer(FormItem fiSrc, FormEvent fe) { //super.propagateDirtinessToContainer(fiSrc, fe); } @Override protected void formOK(UserRequest ureq) { // } @Override protected void doDispose() { // } }