Search in sources :

Example 1 with DecimalVariable

use of org.olat.ims.qti.container.DecimalVariable in project OpenOLAT by OpenOLAT.

the class ResultsBuilder method getResDoc.

/**
 * Method getResDoc.
 *
 * @param ai The assessment instance
 * @param locale The users locale
 * @param identity
 * @return Document The XML document
 */
public Document getResDoc(AssessmentInstance ai, Locale locale, Identity identity) {
    AssessmentContext ac = ai.getAssessmentContext();
    DocumentFactory df = DocumentFactory.getInstance();
    Document res_doc = df.createDocument();
    Element root = df.createElement("qti_result_report");
    res_doc.setRootElement(root);
    Element result = root.addElement("result");
    Element extension_result = result.addElement("extension_result");
    String baseUrl = ai.getResolver().getStaticsBaseURI() + "/";
    // extension_result.
    for (int i = 0; i < ac.getSectionContextCount(); i++) {
        SectionContext sectionCtx = ac.getSectionContext(i);
        for (int j = 0; j < sectionCtx.getItemContextCount(); j++) {
            // OO-148
            // on some occasions this did throw an IllegalAddException
            // because el_item had already a parent.
            // make a clone for adding to extension_result
            Element el_item = (Element) sectionCtx.getItemContext(j).getEl_item().clone();
            recurseMattextForMediaURLFiltering(baseUrl, el_item);
            extension_result.add(el_item);
        }
    }
    // add ims cp id for any media references
    addStaticsPath(extension_result, ai);
    // add assessment_result
    // Add User information
    Element context = result.addElement("context");
    User user = identity.getUser();
    String name = user.getProperty(UserConstants.FIRSTNAME, locale) + " " + user.getProperty(UserConstants.LASTNAME, locale);
    String instId = user.getProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, locale);
    String instName = user.getProperty(UserConstants.INSTITUTIONALNAME, locale);
    if (instId == null)
        instId = "N/A";
    context.addElement("name").addText(name);
    String institution;
    if (instName == null) {
        institution = "N/A";
    } else {
        institution = instName;
    }
    // Add institutional identifier (e.g. Matrikelnummer)
    Element generic_identifier = context.addElement("generic_identifier");
    generic_identifier.addElement("type_label").addText(institution);
    generic_identifier.addElement("identifier_string").addText(instId);
    // Add start and stop date formatted as datetime
    Element beginDate = context.addElement("date");
    beginDate.addElement("type_label").addText("Start");
    beginDate.addElement("datetime").addText(Formatter.formatDatetime(new Date(ac.getTimeOfStart())));
    Element stopDate = context.addElement("date");
    stopDate.addElement("type_label").addText("Stop");
    stopDate.addElement("datetime").addText(Formatter.formatDatetime(new Date(ac.getTimeOfStop())));
    Element ares = result.addElement("assessment_result");
    ares.addAttribute("ident_ref", ac.getIdent());
    if (ac.getTitle() != null) {
        ares.addAttribute("asi_title", ac.getTitle());
    }
    // process assessment score
    Element a_score = ares.addElement("outcomes").addElement("score");
    a_score.addAttribute("varname", "SCORE");
    String strVal = StringHelper.formatFloat(ac.getScore(), 2);
    a_score.addElement("score_value").addText(strVal);
    strVal = ac.getMaxScore() == -1.0f ? "N/A" : StringHelper.formatFloat(ac.getMaxScore(), 2);
    a_score.addElement("score_max").addText(strVal);
    strVal = ac.getCutvalue() == -1.0f ? "N/A" : StringHelper.formatFloat(ac.getCutvalue(), 2);
    a_score.addElement("score_cut").addText(strVal);
    addElementText(ares, "duration", QTIHelper.getISODuration(ac.getDuration()));
    addElementText(ares, "num_sections", "" + ac.getSectionContextCount());
    addElementText(ares, "num_sections_presented", "0");
    addElementText(ares, "num_items", "" + ac.getItemContextCount());
    addElementText(ares, "num_items_presented", "" + ac.getItemsPresentedCount());
    addElementText(ares, "num_items_attempted", "" + ac.getItemsAttemptedCount());
    // add section_result
    int secnt = ac.getSectionContextCount();
    for (int i = 0; i < secnt; i++) {
        SectionContext secc = ac.getSectionContext(i);
        Element secres = ares.addElement("section_result");
        secres.addAttribute("ident_ref", secc.getIdent());
        if (secc.getTitle() != null) {
            secres.addAttribute("asi_title", secc.getTitle());
        }
        addElementText(secres, "duration", QTIHelper.getISODuration(secc.getDuration()));
        addElementText(secres, "num_items", "" + secc.getItemContextCount());
        addElementText(secres, "num_items_presented", "" + secc.getItemsPresentedCount());
        addElementText(secres, "num_items_attempted", "" + secc.getItemsAttemptedCount());
        // process section score
        Element sec_score = secres.addElement("outcomes").addElement("score");
        sec_score.addAttribute("varname", "SCORE");
        strVal = secc.getScore() == -1.0f ? "N/A" : "" + StringHelper.formatFloat(secc.getScore(), 2);
        sec_score.addElement("score_value").addText(strVal);
        strVal = secc.getMaxScore() == -1.0f ? "N/A" : "" + StringHelper.formatFloat(secc.getMaxScore(), 2);
        sec_score.addElement("score_max").addText(strVal);
        strVal = secc.getCutValue() == -1 ? "N/A" : "" + secc.getCutValue();
        sec_score.addElement("score_cut").addText(strVal);
        // iterate over all items in this section context
        List<ItemContext> itemsc = secc.getSectionItemContexts();
        for (Iterator<ItemContext> it_it = itemsc.iterator(); it_it.hasNext(); ) {
            ItemContext itemc = it_it.next();
            Element itres = secres.addElement("item_result");
            itres.addAttribute("ident_ref", itemc.getIdent());
            itres.addAttribute("asi_title", itemc.getEl_item().attributeValue("title"));
            Element it_duration = itres.addElement("duration");
            it_duration.addText(QTIHelper.getISODuration(itemc.getTimeSpent()));
            // process item score
            DecimalVariable scoreVar = (DecimalVariable) (itemc.getVariables().getSCOREVariable());
            Element it_score = itres.addElement("outcomes").addElement("score");
            it_score.addAttribute("varname", "SCORE");
            it_score.addElement("score_value").addText(StringHelper.formatFloat(scoreVar.getTruncatedValue(), 2));
            strVal = scoreVar.hasMinValue() ? "" + scoreVar.getMinValue() : "0.0";
            it_score.addElement("score_min").addText(strVal);
            strVal = scoreVar.hasMaxValue() ? "" + scoreVar.getMaxValue() : "N/A";
            it_score.addElement("score_max").addText(strVal);
            strVal = scoreVar.hasCutValue() ? "" + scoreVar.getCutValue() : "N/A";
            it_score.addElement("score_cut").addText(strVal);
            Element el_item = itemc.getEl_item();
            Map<String, Element> res_responsehash = new HashMap<>(3);
            // iterate over all responses of this item
            List resps = el_item.selectNodes(".//response_lid|.//response_xy|.//response_str|.//response_num|.//response_grp");
            for (Iterator it_resp = resps.iterator(); it_resp.hasNext(); ) {
                Element resp = (Element) it_resp.next();
                String ident = resp.attributeValue("ident");
                String rcardinality = resp.attributeValue("rcardinality");
                String rtiming = resp.attributeValue("rtiming");
                // add new response
                Element res_response = itres.addElement("response");
                res_response.addAttribute("ident_ref", ident);
                // enable lookup of
                res_responsehash.put(ident, res_response);
                // @identref of <response>
                // (needed with <varequal>
                // elements
                // add new response_form
                // <response_lid ident="MR01" rcardinality="Multiple" rtiming="No">
                Element res_responseform = res_response.addElement("response_form");
                res_responseform.addAttribute("cardinality", rcardinality);
                res_responseform.addAttribute("timing", rtiming);
                String respName = resp.getName();
                String type = respName.substring(respName.indexOf("_") + 1);
                res_responseform.addAttribute("response_type", type);
                // add user answer
                ItemInput itemInp = itemc.getItemInput();
                Translator trans = Util.createPackageTranslator(QTIModule.class, locale);
                if (itemInp == null) {
                    // user did not answer this question at all
                    res_response.addElement("response_value").addText(trans.translate("ResBuilder.NoAnswer"));
                } else {
                    List<String> userAnswer = itemInp.getAsList(ident);
                    if (userAnswer == null) {
                        // user did not answer this question at
                        // all
                        res_response.addElement("response_value").addText(trans.translate("ResBuilder.NoAnswer"));
                    } else {
                        // simply click send)
                        for (Iterator<String> it_ans = userAnswer.iterator(); it_ans.hasNext(); ) {
                            res_response.addElement("response_value").addText(it_ans.next());
                        }
                    }
                }
            }
            /*
				 * The simple element correct_response can only list correct elements,
				 * that is, no "or" or "and" elements may be in the conditionvar.
				 * Pragmatic solution: if condition has ors or ands, then put whole
				 * conditionvar into <extension_response> (proprietary), and for easier
				 * cases (just "varequal" "not" elements) use correct_response.
				 */
            // keys: respIdents, values: HashSet
            Map<String, Set<String>> corr_answers = new HashMap<>();
            // of correct answers for this
            // respIdent
            List respconds = el_item.selectNodes(".//respcondition");
            for (Iterator it_respc = respconds.iterator(); it_respc.hasNext(); ) {
                Element el_respc = (Element) it_respc.next();
                // check for add/set in setvar elements (check for single instance
                // only -> spec allows for multiple instances)
                Element el_setvar = (Element) el_respc.selectSingleNode(".//setvar");
                if (el_setvar == null)
                    continue;
                if (el_setvar.attributeValue("action").equals("Add") || el_setvar.attributeValue("action").equals("Set")) {
                    // This resrocessing gives points -> assume correct answer
                    float numPoints = 0;
                    try {
                        numPoints = Float.parseFloat(el_setvar.getTextTrim());
                    } catch (NumberFormatException nfe) {
                    // 
                    }
                    if (numPoints <= 0)
                        continue;
                    Element conditionvar = (Element) el_respc.selectSingleNode(".//conditionvar");
                    // there is an evaluation defined (a "resprocessing" element exists)
                    // if (xpath(count(.//varequal) + count(.//not) = count(.//*)) is
                    // true, then there are only "not" and "varequal" elements
                    XPath xCanHandle = DocumentHelper.createXPath("count(.//varequal) + count(.//not) = count(.//*)");
                    boolean canHandle = xCanHandle.matches(conditionvar);
                    if (!canHandle) {
                        // maybe we have <condvar> <and> <...>, try again
                        Element el_and = (Element) conditionvar.selectSingleNode("and");
                        if (el_and != null) {
                            canHandle = xCanHandle.matches(el_and);
                            if (canHandle) {
                                // simultate the el_and to be the conditionvar
                                conditionvar = el_and;
                            }
                        } else {
                            // and finally, maybe we have an <or> element ..
                            Element el_or = (Element) conditionvar.selectSingleNode("or");
                            if (el_or != null) {
                                canHandle = xCanHandle.matches(el_or);
                                if (canHandle) {
                                    // simultate the el_and to be the conditionvar
                                    conditionvar = el_or;
                                }
                            }
                        }
                    }
                    if (!canHandle) {
                        // qti res 1.2.1 can't handle it
                        Element condcopy = conditionvar.createCopy();
                        itres.addElement("extension_item_result").add(condcopy);
                    } else {
                        /*
							 * easy case: get all varequal directly under the conditionvar
							 * element and assume the "not" elements do not contain "not"
							 * elements again... <!ELEMENT response (qti_comment? ,
							 * response_form? , num_attempts? , response_value* ,
							 * extension_response?)> <!ELEMENT response_form
							 * (correct_response* , extension_responseform?)> <!ELEMENT
							 * correct_response (#PCDATA)>
							 */
                        List vareqs = conditionvar.selectNodes("./varequal");
                        for (Iterator it_vareq = vareqs.iterator(); it_vareq.hasNext(); ) {
                            /*
								 * get the identifier of the response, so that we can attach the
								 * <correct_response> to the right <response> element quote: ims
								 * qti asi xml binding :3.6.23.1 <varequal> Element: respident
								 * (required). The identifier of the corresponding
								 * <response_lid>, <response_xy>, etc. element (this was
								 * assigned using its ident attribute).
								 */
                            Element vareq = (Element) it_vareq.next();
                            String respIdent = vareq.attributeValue("respident");
                            Set<String> respIdent_corr_answers = corr_answers.get(respIdent);
                            if (respIdent_corr_answers == null)
                                respIdent_corr_answers = new HashSet<String>(3);
                            respIdent_corr_answers.add(vareq.getText());
                            corr_answers.put(respIdent, respIdent_corr_answers);
                        }
                    // for varequal
                    }
                // else varequal
                }
            // add/set setvar
            }
            // for resprocessing
            Set<String> resp_ids = corr_answers.keySet();
            for (Iterator<String> idents = resp_ids.iterator(); idents.hasNext(); ) {
                String respIdent = idents.next();
                Set<String> respIdent_corr_answers = corr_answers.get(respIdent);
                Element res_response = res_responsehash.get(respIdent);
                Element res_respform = res_response.element("response_form");
                for (Iterator<String> iter = respIdent_corr_answers.iterator(); iter.hasNext(); ) {
                    String answer = iter.next();
                    res_respform.addElement("correct_response").addText(answer);
                }
            }
        }
    // for response_xy
    }
    return res_doc;
}
Also used : SectionContext(org.olat.ims.qti.container.SectionContext) User(org.olat.core.id.User) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) Element(org.dom4j.Element) Document(org.dom4j.Document) ItemInput(org.olat.ims.qti.container.ItemInput) DecimalVariable(org.olat.ims.qti.container.DecimalVariable) Translator(org.olat.core.gui.translator.Translator) Iterator(java.util.Iterator) List(java.util.List) HashSet(java.util.HashSet) XPath(org.dom4j.XPath) Date(java.util.Date) AssessmentContext(org.olat.ims.qti.container.AssessmentContext) ItemContext(org.olat.ims.qti.container.ItemContext) DocumentFactory(org.dom4j.DocumentFactory)

Example 2 with DecimalVariable

use of org.olat.ims.qti.container.DecimalVariable in project OpenOLAT by OpenOLAT.

the class QTIHelper method declareVariables.

/**
 */
public static Variables declareVariables(Element el_outcomes) {
    String varName;
    Variables variables = new Variables();
    if (el_outcomes == null)
        return variables;
    List decvars = el_outcomes.selectNodes("decvar");
    /*
		 * <decvar defaultval = "0" varname = "Var_SumofScores" vartype = "Integer"
		 * minvalue = "-10" maxvalue = "10" cutvalue = "0"/> <decvar minvalue = "0"
		 * maxvalue = "1" defaultval = "0"/>
		 */
    for (Iterator iter = decvars.iterator(); iter.hasNext(); ) {
        Element decvar = (Element) iter.next();
        // dtd CDATA 'SCORE'
        varName = decvar.attributeValue("varname");
        if (varName == null)
            varName = "SCORE";
        String varType = decvar.attributeValue("vartype");
        // default
        if (varType == null)
            varType = "Integer";
        Variable v = null;
        if (varType.equals("Integer") || varType.equals("Decimal")) {
            String def = decvar.attributeValue("defaultval");
            String min = decvar.attributeValue("minvalue");
            String max = decvar.attributeValue("maxvalue");
            String cut = decvar.attributeValue("cutvalue");
            v = new DecimalVariable(varName, max, min, cut, def);
            variables.setVariable(v);
        } else
            throw new RuntimeException("vartype " + varType + " not supported (declaration)");
    }
    return variables;
}
Also used : Variables(org.olat.ims.qti.container.Variables) Variable(org.olat.ims.qti.container.Variable) DecimalVariable(org.olat.ims.qti.container.DecimalVariable) Element(org.dom4j.Element) Iterator(java.util.Iterator) List(java.util.List) DecimalVariable(org.olat.ims.qti.container.DecimalVariable)

Example 3 with DecimalVariable

use of org.olat.ims.qti.container.DecimalVariable in project openolat by klemens.

the class QTIHelper method declareVariables.

/**
 */
public static Variables declareVariables(Element el_outcomes) {
    String varName;
    Variables variables = new Variables();
    if (el_outcomes == null)
        return variables;
    List decvars = el_outcomes.selectNodes("decvar");
    /*
		 * <decvar defaultval = "0" varname = "Var_SumofScores" vartype = "Integer"
		 * minvalue = "-10" maxvalue = "10" cutvalue = "0"/> <decvar minvalue = "0"
		 * maxvalue = "1" defaultval = "0"/>
		 */
    for (Iterator iter = decvars.iterator(); iter.hasNext(); ) {
        Element decvar = (Element) iter.next();
        // dtd CDATA 'SCORE'
        varName = decvar.attributeValue("varname");
        if (varName == null)
            varName = "SCORE";
        String varType = decvar.attributeValue("vartype");
        // default
        if (varType == null)
            varType = "Integer";
        Variable v = null;
        if (varType.equals("Integer") || varType.equals("Decimal")) {
            String def = decvar.attributeValue("defaultval");
            String min = decvar.attributeValue("minvalue");
            String max = decvar.attributeValue("maxvalue");
            String cut = decvar.attributeValue("cutvalue");
            v = new DecimalVariable(varName, max, min, cut, def);
            variables.setVariable(v);
        } else
            throw new RuntimeException("vartype " + varType + " not supported (declaration)");
    }
    return variables;
}
Also used : Variables(org.olat.ims.qti.container.Variables) Variable(org.olat.ims.qti.container.Variable) DecimalVariable(org.olat.ims.qti.container.DecimalVariable) Element(org.dom4j.Element) Iterator(java.util.Iterator) List(java.util.List) DecimalVariable(org.olat.ims.qti.container.DecimalVariable)

Example 4 with DecimalVariable

use of org.olat.ims.qti.container.DecimalVariable in project openolat by klemens.

the class ResultsBuilder method getResDoc.

/**
 * Method getResDoc.
 *
 * @param ai The assessment instance
 * @param locale The users locale
 * @param identity
 * @return Document The XML document
 */
public Document getResDoc(AssessmentInstance ai, Locale locale, Identity identity) {
    AssessmentContext ac = ai.getAssessmentContext();
    DocumentFactory df = DocumentFactory.getInstance();
    Document res_doc = df.createDocument();
    Element root = df.createElement("qti_result_report");
    res_doc.setRootElement(root);
    Element result = root.addElement("result");
    Element extension_result = result.addElement("extension_result");
    String baseUrl = ai.getResolver().getStaticsBaseURI() + "/";
    // extension_result.
    for (int i = 0; i < ac.getSectionContextCount(); i++) {
        SectionContext sectionCtx = ac.getSectionContext(i);
        for (int j = 0; j < sectionCtx.getItemContextCount(); j++) {
            // OO-148
            // on some occasions this did throw an IllegalAddException
            // because el_item had already a parent.
            // make a clone for adding to extension_result
            Element el_item = (Element) sectionCtx.getItemContext(j).getEl_item().clone();
            recurseMattextForMediaURLFiltering(baseUrl, el_item);
            extension_result.add(el_item);
        }
    }
    // add ims cp id for any media references
    addStaticsPath(extension_result, ai);
    // add assessment_result
    // Add User information
    Element context = result.addElement("context");
    User user = identity.getUser();
    String name = user.getProperty(UserConstants.FIRSTNAME, locale) + " " + user.getProperty(UserConstants.LASTNAME, locale);
    String instId = user.getProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, locale);
    String instName = user.getProperty(UserConstants.INSTITUTIONALNAME, locale);
    if (instId == null)
        instId = "N/A";
    context.addElement("name").addText(name);
    String institution;
    if (instName == null) {
        institution = "N/A";
    } else {
        institution = instName;
    }
    // Add institutional identifier (e.g. Matrikelnummer)
    Element generic_identifier = context.addElement("generic_identifier");
    generic_identifier.addElement("type_label").addText(institution);
    generic_identifier.addElement("identifier_string").addText(instId);
    // Add start and stop date formatted as datetime
    Element beginDate = context.addElement("date");
    beginDate.addElement("type_label").addText("Start");
    beginDate.addElement("datetime").addText(Formatter.formatDatetime(new Date(ac.getTimeOfStart())));
    Element stopDate = context.addElement("date");
    stopDate.addElement("type_label").addText("Stop");
    stopDate.addElement("datetime").addText(Formatter.formatDatetime(new Date(ac.getTimeOfStop())));
    Element ares = result.addElement("assessment_result");
    ares.addAttribute("ident_ref", ac.getIdent());
    if (ac.getTitle() != null) {
        ares.addAttribute("asi_title", ac.getTitle());
    }
    // process assessment score
    Element a_score = ares.addElement("outcomes").addElement("score");
    a_score.addAttribute("varname", "SCORE");
    String strVal = StringHelper.formatFloat(ac.getScore(), 2);
    a_score.addElement("score_value").addText(strVal);
    strVal = ac.getMaxScore() == -1.0f ? "N/A" : StringHelper.formatFloat(ac.getMaxScore(), 2);
    a_score.addElement("score_max").addText(strVal);
    strVal = ac.getCutvalue() == -1.0f ? "N/A" : StringHelper.formatFloat(ac.getCutvalue(), 2);
    a_score.addElement("score_cut").addText(strVal);
    addElementText(ares, "duration", QTIHelper.getISODuration(ac.getDuration()));
    addElementText(ares, "num_sections", "" + ac.getSectionContextCount());
    addElementText(ares, "num_sections_presented", "0");
    addElementText(ares, "num_items", "" + ac.getItemContextCount());
    addElementText(ares, "num_items_presented", "" + ac.getItemsPresentedCount());
    addElementText(ares, "num_items_attempted", "" + ac.getItemsAttemptedCount());
    // add section_result
    int secnt = ac.getSectionContextCount();
    for (int i = 0; i < secnt; i++) {
        SectionContext secc = ac.getSectionContext(i);
        Element secres = ares.addElement("section_result");
        secres.addAttribute("ident_ref", secc.getIdent());
        if (secc.getTitle() != null) {
            secres.addAttribute("asi_title", secc.getTitle());
        }
        addElementText(secres, "duration", QTIHelper.getISODuration(secc.getDuration()));
        addElementText(secres, "num_items", "" + secc.getItemContextCount());
        addElementText(secres, "num_items_presented", "" + secc.getItemsPresentedCount());
        addElementText(secres, "num_items_attempted", "" + secc.getItemsAttemptedCount());
        // process section score
        Element sec_score = secres.addElement("outcomes").addElement("score");
        sec_score.addAttribute("varname", "SCORE");
        strVal = secc.getScore() == -1.0f ? "N/A" : "" + StringHelper.formatFloat(secc.getScore(), 2);
        sec_score.addElement("score_value").addText(strVal);
        strVal = secc.getMaxScore() == -1.0f ? "N/A" : "" + StringHelper.formatFloat(secc.getMaxScore(), 2);
        sec_score.addElement("score_max").addText(strVal);
        strVal = secc.getCutValue() == -1 ? "N/A" : "" + secc.getCutValue();
        sec_score.addElement("score_cut").addText(strVal);
        // iterate over all items in this section context
        List<ItemContext> itemsc = secc.getSectionItemContexts();
        for (Iterator<ItemContext> it_it = itemsc.iterator(); it_it.hasNext(); ) {
            ItemContext itemc = it_it.next();
            Element itres = secres.addElement("item_result");
            itres.addAttribute("ident_ref", itemc.getIdent());
            itres.addAttribute("asi_title", itemc.getEl_item().attributeValue("title"));
            Element it_duration = itres.addElement("duration");
            it_duration.addText(QTIHelper.getISODuration(itemc.getTimeSpent()));
            // process item score
            DecimalVariable scoreVar = (DecimalVariable) (itemc.getVariables().getSCOREVariable());
            Element it_score = itres.addElement("outcomes").addElement("score");
            it_score.addAttribute("varname", "SCORE");
            it_score.addElement("score_value").addText(StringHelper.formatFloat(scoreVar.getTruncatedValue(), 2));
            strVal = scoreVar.hasMinValue() ? "" + scoreVar.getMinValue() : "0.0";
            it_score.addElement("score_min").addText(strVal);
            strVal = scoreVar.hasMaxValue() ? "" + scoreVar.getMaxValue() : "N/A";
            it_score.addElement("score_max").addText(strVal);
            strVal = scoreVar.hasCutValue() ? "" + scoreVar.getCutValue() : "N/A";
            it_score.addElement("score_cut").addText(strVal);
            Element el_item = itemc.getEl_item();
            Map<String, Element> res_responsehash = new HashMap<>(3);
            // iterate over all responses of this item
            List resps = el_item.selectNodes(".//response_lid|.//response_xy|.//response_str|.//response_num|.//response_grp");
            for (Iterator it_resp = resps.iterator(); it_resp.hasNext(); ) {
                Element resp = (Element) it_resp.next();
                String ident = resp.attributeValue("ident");
                String rcardinality = resp.attributeValue("rcardinality");
                String rtiming = resp.attributeValue("rtiming");
                // add new response
                Element res_response = itres.addElement("response");
                res_response.addAttribute("ident_ref", ident);
                // enable lookup of
                res_responsehash.put(ident, res_response);
                // @identref of <response>
                // (needed with <varequal>
                // elements
                // add new response_form
                // <response_lid ident="MR01" rcardinality="Multiple" rtiming="No">
                Element res_responseform = res_response.addElement("response_form");
                res_responseform.addAttribute("cardinality", rcardinality);
                res_responseform.addAttribute("timing", rtiming);
                String respName = resp.getName();
                String type = respName.substring(respName.indexOf("_") + 1);
                res_responseform.addAttribute("response_type", type);
                // add user answer
                ItemInput itemInp = itemc.getItemInput();
                Translator trans = Util.createPackageTranslator(QTIModule.class, locale);
                if (itemInp == null) {
                    // user did not answer this question at all
                    res_response.addElement("response_value").addText(trans.translate("ResBuilder.NoAnswer"));
                } else {
                    List<String> userAnswer = itemInp.getAsList(ident);
                    if (userAnswer == null) {
                        // user did not answer this question at
                        // all
                        res_response.addElement("response_value").addText(trans.translate("ResBuilder.NoAnswer"));
                    } else {
                        // simply click send)
                        for (Iterator<String> it_ans = userAnswer.iterator(); it_ans.hasNext(); ) {
                            res_response.addElement("response_value").addText(it_ans.next());
                        }
                    }
                }
            }
            /*
				 * The simple element correct_response can only list correct elements,
				 * that is, no "or" or "and" elements may be in the conditionvar.
				 * Pragmatic solution: if condition has ors or ands, then put whole
				 * conditionvar into <extension_response> (proprietary), and for easier
				 * cases (just "varequal" "not" elements) use correct_response.
				 */
            // keys: respIdents, values: HashSet
            Map<String, Set<String>> corr_answers = new HashMap<>();
            // of correct answers for this
            // respIdent
            List respconds = el_item.selectNodes(".//respcondition");
            for (Iterator it_respc = respconds.iterator(); it_respc.hasNext(); ) {
                Element el_respc = (Element) it_respc.next();
                // check for add/set in setvar elements (check for single instance
                // only -> spec allows for multiple instances)
                Element el_setvar = (Element) el_respc.selectSingleNode(".//setvar");
                if (el_setvar == null)
                    continue;
                if (el_setvar.attributeValue("action").equals("Add") || el_setvar.attributeValue("action").equals("Set")) {
                    // This resrocessing gives points -> assume correct answer
                    float numPoints = 0;
                    try {
                        numPoints = Float.parseFloat(el_setvar.getTextTrim());
                    } catch (NumberFormatException nfe) {
                    // 
                    }
                    if (numPoints <= 0)
                        continue;
                    Element conditionvar = (Element) el_respc.selectSingleNode(".//conditionvar");
                    // there is an evaluation defined (a "resprocessing" element exists)
                    // if (xpath(count(.//varequal) + count(.//not) = count(.//*)) is
                    // true, then there are only "not" and "varequal" elements
                    XPath xCanHandle = DocumentHelper.createXPath("count(.//varequal) + count(.//not) = count(.//*)");
                    boolean canHandle = xCanHandle.matches(conditionvar);
                    if (!canHandle) {
                        // maybe we have <condvar> <and> <...>, try again
                        Element el_and = (Element) conditionvar.selectSingleNode("and");
                        if (el_and != null) {
                            canHandle = xCanHandle.matches(el_and);
                            if (canHandle) {
                                // simultate the el_and to be the conditionvar
                                conditionvar = el_and;
                            }
                        } else {
                            // and finally, maybe we have an <or> element ..
                            Element el_or = (Element) conditionvar.selectSingleNode("or");
                            if (el_or != null) {
                                canHandle = xCanHandle.matches(el_or);
                                if (canHandle) {
                                    // simultate the el_and to be the conditionvar
                                    conditionvar = el_or;
                                }
                            }
                        }
                    }
                    if (!canHandle) {
                        // qti res 1.2.1 can't handle it
                        Element condcopy = conditionvar.createCopy();
                        itres.addElement("extension_item_result").add(condcopy);
                    } else {
                        /*
							 * easy case: get all varequal directly under the conditionvar
							 * element and assume the "not" elements do not contain "not"
							 * elements again... <!ELEMENT response (qti_comment? ,
							 * response_form? , num_attempts? , response_value* ,
							 * extension_response?)> <!ELEMENT response_form
							 * (correct_response* , extension_responseform?)> <!ELEMENT
							 * correct_response (#PCDATA)>
							 */
                        List vareqs = conditionvar.selectNodes("./varequal");
                        for (Iterator it_vareq = vareqs.iterator(); it_vareq.hasNext(); ) {
                            /*
								 * get the identifier of the response, so that we can attach the
								 * <correct_response> to the right <response> element quote: ims
								 * qti asi xml binding :3.6.23.1 <varequal> Element: respident
								 * (required). The identifier of the corresponding
								 * <response_lid>, <response_xy>, etc. element (this was
								 * assigned using its ident attribute).
								 */
                            Element vareq = (Element) it_vareq.next();
                            String respIdent = vareq.attributeValue("respident");
                            Set<String> respIdent_corr_answers = corr_answers.get(respIdent);
                            if (respIdent_corr_answers == null)
                                respIdent_corr_answers = new HashSet<String>(3);
                            respIdent_corr_answers.add(vareq.getText());
                            corr_answers.put(respIdent, respIdent_corr_answers);
                        }
                    // for varequal
                    }
                // else varequal
                }
            // add/set setvar
            }
            // for resprocessing
            Set<String> resp_ids = corr_answers.keySet();
            for (Iterator<String> idents = resp_ids.iterator(); idents.hasNext(); ) {
                String respIdent = idents.next();
                Set<String> respIdent_corr_answers = corr_answers.get(respIdent);
                Element res_response = res_responsehash.get(respIdent);
                Element res_respform = res_response.element("response_form");
                for (Iterator<String> iter = respIdent_corr_answers.iterator(); iter.hasNext(); ) {
                    String answer = iter.next();
                    res_respform.addElement("correct_response").addText(answer);
                }
            }
        }
    // for response_xy
    }
    return res_doc;
}
Also used : SectionContext(org.olat.ims.qti.container.SectionContext) User(org.olat.core.id.User) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) Element(org.dom4j.Element) Document(org.dom4j.Document) ItemInput(org.olat.ims.qti.container.ItemInput) DecimalVariable(org.olat.ims.qti.container.DecimalVariable) Translator(org.olat.core.gui.translator.Translator) Iterator(java.util.Iterator) List(java.util.List) HashSet(java.util.HashSet) XPath(org.dom4j.XPath) Date(java.util.Date) AssessmentContext(org.olat.ims.qti.container.AssessmentContext) ItemContext(org.olat.ims.qti.container.ItemContext) DocumentFactory(org.dom4j.DocumentFactory)

Aggregations

Iterator (java.util.Iterator)4 List (java.util.List)4 Element (org.dom4j.Element)4 DecimalVariable (org.olat.ims.qti.container.DecimalVariable)4 Date (java.util.Date)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Set (java.util.Set)2 Document (org.dom4j.Document)2 DocumentFactory (org.dom4j.DocumentFactory)2 XPath (org.dom4j.XPath)2 Translator (org.olat.core.gui.translator.Translator)2 User (org.olat.core.id.User)2 AssessmentContext (org.olat.ims.qti.container.AssessmentContext)2 ItemContext (org.olat.ims.qti.container.ItemContext)2 ItemInput (org.olat.ims.qti.container.ItemInput)2 SectionContext (org.olat.ims.qti.container.SectionContext)2 Variable (org.olat.ims.qti.container.Variable)2 Variables (org.olat.ims.qti.container.Variables)2