The complete source code of the corrector

package net.mumie.corrector;

import net.mumie.mathletfactory.math.number.MDouble;
import net.mumie.mathletfactory.math.number.MInteger;
import net.mumie.mathletfactory.math.number.MOpNumber;
import net.mumie.mathletfactory.math.util.MString;
import net.mumie.mathletfactory.util.exercise.CorrectorHelper;
import net.mumie.mathletfactory.util.xml.MathMLSerializable;
import net.mumie.mathletfactory.util.xml.marking.SubtaskNode;
import net.mumie.srv.datasheet.Datasheet;
import net.mumie.srv.problem.CorrectionException;
import net.mumie.srv.problem.Corrector;

/**
 * No Description
 * 
 * @author unknown
 * @mm.type java_class
 * @mm.category corrector
 * @mm.section content/s3m2/sample/problems/advanced_dynamic_problems/correctors
 * @mm.copyright no copyright
 * @mm.buildClasspath mumie_mathletfactory_base.jar
 * @mm.buildClasspath mumie-srv-for-mmcdk.jar
 * @mm.buildClasspath mumie-srv-datasheet.jar
 * @mm.docstatus
 * @mm.status devel_ok
 * @mm.description No Description
 * @mm.rating none
 */
public class QuadraticFunctionsCorrector implements Corrector {

  CorrectorHelper helper;// provides methods to read and modify the datasheet
  // problem objects
  MInteger x1, x2, d;
  MOpNumber polynomial;
  // answer objects
  MInteger numberOfRoots;
  MDouble root1, root2, answer;

  @Override
  public void correct(Datasheet inputDatasheet, Datasheet outputDatasheet)
      throws CorrectionException {

    helper = new CorrectorHelper(inputDatasheet, outputDatasheet);// create the helper
    // input datasheet contains the problem and the answer
    // output datasheet contains the correction

    SubtaskNode subtask1 = helper.getMarkingDocBuilder().addSubtaskNode();// create and add a subtask node to the correction
    SubtaskNode subtask2 = helper.getMarkingDocBuilder().addSubtaskNode();// create and add a subtask node to the correction
    // load the problem
    x1 = new MInteger();
    x2 = new MInteger();
    d = new MInteger();
    polynomial = new MOpNumber();

    helper.loadElement("user/problem/x1", x1);
    helper.loadElement("user/problem/x2", x2);
    helper.loadElement("user/problem/d", d);
    helper.loadElement("user/problem/polynomial", polynomial);

    // load and correct subtask1
    numberOfRoots = new MInteger();
    root1 = new MDouble();
    root2 = new MDouble();
    boolean edited = false;// initialize edited flag to false
    if (helper.userElementExists(1, "numOfRoots")) {// answer exists?
      helper.loadUserElement(1, "numOfRoots", numberOfRoots);
      helper.loadUserElement(1, "root1", root1);
      if (helper.userElementExists(1, "root2"))
        helper.loadUserElement(1, "root2", root2);
      edited = root1.isEdited() || root2.isEdited();// edited when any roots are edited
    }
    // now determine if the answer is correct (similar to training)
    boolean correct = false;// answer is correct?
    boolean x1Correct = false;// x1 is in answer?
    boolean x2Correct = false;// x2 is in answer?
    boolean isEdited = false;// are the answers edited?
    if (x1 != x2) {// 2 different roots were generated
      isEdited = root1.isEdited() && root2.isEdited(); // check if both roots are edited
      x1Correct = equalCheck(x1.getDouble(), root1.getDouble())
          || equalCheck(x1.getDouble(), root2.getDouble());
      x2Correct = equalCheck(x2.getDouble(), root1.getDouble())
          || equalCheck(x2.getDouble(), root2.getDouble());
      correct = isEdited && x1Correct && x2Correct;// only correct if both roots are edited and both x1 and x2 are found in the answer
    } else {
      correct = equalCheck(x1.getDouble(), root1.getDouble())
          && root1.isEdited();// correct if root1 is edited and root1 equals x1
    }

    // prepare the roots
    MathMLSerializable[] rootPresentation;
    if (numberOfRoots.getIntValue() == 1) {
      rootPresentation = new MathMLSerializable[] {
          new MString("Root(s) of f(x) = {"),// create new MString to add text
          root1,// add the first root
          new MString("}") // create new MString to add text
      };
    } else {
      rootPresentation = new MathMLSerializable[] {
          new MString("Root(s) of f(x) = {"), root1,// add the first root
          new MString(","), root2,// add the second root
          new MString("}") };
    }

    if (correct) {// in case answer is correct
      helper.addToScore(0.5);// adds half of the total points
      subtask1.getAnswerNode().addParagraphNode("Correctly solved!");
      subtask1.getAnswerNode().addParagraphNode("Your solution:");
      subtask1.getAnswerNode().addMathObject("Number of root(s) = ",
          numberOfRoots);
      subtask1.getAnswerNode().addMathObjects(rootPresentation);// simply add the prepared rootPresentation
      subtask1.getSolutionNode().addParagraphNode("see left.");// expected solution is the same as answer
    } else {// answer is not correct
      if (edited) {// display answer if task is edited
        subtask1.getAnswerNode().addParagraphNode("Not correct!");
        subtask1.getAnswerNode().addParagraphNode("Your solution:");
        subtask1.getAnswerNode().addMathObject("Number of root(s) = ",
            numberOfRoots);
        subtask1.getAnswerNode().addMathObjects(rootPresentation);
      } else {// if not, there is nothing to display
        subtask1.getAnswerNode().addParagraphNode("Not edited!");
      }
      // now write the expected solution
      int correctNumOfRoots = 1;
      if (x1 != x2)
        correctNumOfRoots = 2;
      subtask1.getSolutionNode().addParagraphNode("Correct is:");
      subtask1.getSolutionNode().addParagraphNode(
          "Number of root(s) = " + correctNumOfRoots);
      if (x1 == x2) {
        subtask1.getSolutionNode().addParagraphNode(
            "Root(s) of f(x) = {" + x1.getIntValue() + "}");
      } else {
        subtask1.getSolutionNode().addParagraphNode(
            "Root(s) of f(x) = {" + x1.getIntValue() + ", " + x2.getIntValue()
                + "}");
      }
    }
    // display the given function in the explanation code
    subtask1.getExplanationNode().addParagraphNode("Given function was:");
    subtask1.getExplanationNode().addMathObject("f(x) = ", polynomial);
    // load and correct task b
    answer = new MDouble();
    edited = false;
    if (helper.userElementExists(2, "answer")) {
      helper.loadUserElement(2, "answer", answer);
      edited = answer.isEdited();
    }
    correct = false;
    double correctAnswer = polynomial.getOperation().evaluate(d.getIntValue());
    correct = edited && equalCheck(correctAnswer, answer.getDouble());

    if (correct) {
      subtask2.getAnswerNode().addParagraphNode("Correctly solved!");
      subtask2.getAnswerNode().addParagraphNode("Your solution:");
      subtask2.getAnswerNode().addMathObject("f(" + d.getIntValue() + ") = ",
          answer);
      subtask2.getSolutionNode().addParagraphNode("see left.");
    } else {
      if (edited) {
        subtask2.getAnswerNode().addParagraphNode("Not correct!");
        subtask2.getAnswerNode().addParagraphNode("Your solution:");
        subtask2.getAnswerNode().addMathObject("f(" + d.getIntValue() + ") = ",
            answer);
      } else {
        subtask2.getAnswerNode().addParagraphNode("Not edited!");
      }
      subtask2.getSolutionNode().addParagraphNode("Correct is:");
      subtask2.getSolutionNode().addParagraphNode(
          "f(" + d.getIntValue() + ") = " + correctAnswer);
    }

    helper.finish();// notifies the helper to finish and write the content into the output datasheet
  }

  /**
   * checks whether or not two real numbers are equal with 0.005 precision
   * 
   * @return true if |a-b| < 0.005
   */
  private boolean equalCheck(double a, double b) {
    return Math.abs(a - b) < 0.005; // check with 0.005 precision
  }
}

Add picture from clipboard (Maximum size: 500 MB)