public List<ConfusionMatrixObject> calculate() {

    List<ConfusionMatrixObject> cmoList = new ArrayList<ConfusionMatrixObject>();

    // Calculate the sum
    Double sumPos = 0.0, sumNeg = 0.0, sumWeightedPos = 0.0, sumWeightedNeg = 0.0;
    for (ModelResultObject mo : moList) {
      if (posTags.contains(mo.getTag())) {
        // Positive
        sumPos += posScaleFactor;
        sumWeightedPos += mo.getWeight() * posScaleFactor;
      } else {
        // Negative
        sumNeg += negScaleFactor;
        sumWeightedNeg += mo.getWeight() * negScaleFactor;
      }
    }

    // init ConfusionMatrix
    ConfusionMatrixObject initCmo = new ConfusionMatrixObject();
    initCmo.setTp(0.0);
    initCmo.setFp(0.0);
    initCmo.setFn(sumPos);
    initCmo.setTn(sumNeg);
    initCmo.setWeightedTp(0.0);
    initCmo.setWeightedFp(0.0);
    initCmo.setWeightedFn(sumWeightedPos);
    initCmo.setWeightedTn(sumWeightedNeg);
    initCmo.setScore(moList.get(0).getScore());
    cmoList.add(initCmo);

    // Calculate the rest
    ConfusionMatrixObject prevCmo = initCmo;
    for (ModelResultObject mo : moList) {
      ConfusionMatrixObject cmo = new ConfusionMatrixObject(prevCmo);

      if (posTags.contains(mo.getTag())) {
        // Positive Instance
        cmo.setTp(cmo.getTp() + posScaleFactor);
        cmo.setFn(cmo.getFn() - posScaleFactor);
        cmo.setWeightedTp(cmo.getWeightedTp() + mo.getWeight() * posScaleFactor);
        cmo.setWeightedFn(cmo.getWeightedFn() - mo.getWeight() * posScaleFactor);
      } else {
        // Negative Instance
        cmo.setFp(cmo.getFp() + negScaleFactor);
        cmo.setTn(cmo.getTn() - negScaleFactor);
        cmo.setWeightedFp(cmo.getWeightedFp() + mo.getWeight() * negScaleFactor);
        cmo.setWeightedTn(cmo.getWeightedTn() - mo.getWeight() * negScaleFactor);
      }

      cmo.setScore(mo.getScore());
      cmoList.add(cmo);
      prevCmo = cmo;
    }

    return cmoList;
  }
  public void calculate(BufferedWriter writer) {

    Double sumPos = 0.0, sumNeg = 0.0, sumWeightedPos = 0.0, sumWeightedNeg = 0.0;
    for (ModelResultObject mo : moList) {
      if (posTags.contains(mo.getTag())) {
        // Positive
        sumPos += posScaleFactor;
        sumWeightedPos += mo.getWeight() * posScaleFactor;
      } else {
        // Negative
        sumNeg += negScaleFactor;
        sumWeightedNeg += mo.getWeight() * negScaleFactor;
      }
    }

    ConfusionMatrixObject prevCmo = new ConfusionMatrixObject();

    prevCmo.setTp(0.0);
    prevCmo.setFp(0.0);
    prevCmo.setFn(sumPos);
    prevCmo.setTn(sumNeg);
    prevCmo.setWeightedTp(0.0);
    prevCmo.setWeightedFp(0.0);
    prevCmo.setWeightedFn(sumWeightedPos);
    prevCmo.setWeightedTn(sumWeightedNeg);
    prevCmo.setScore(1000);

    saveConfusionMaxtrixWithWriter(writer, prevCmo);

    for (ModelResultObject mo : moList) {
      ConfusionMatrixObject cmo = new ConfusionMatrixObject(prevCmo);

      if (posTags.contains(mo.getTag())) {
        // Positive Instance
        cmo.setTp(cmo.getTp() + posScaleFactor);
        cmo.setFn(cmo.getFn() - posScaleFactor);
        cmo.setWeightedTp(cmo.getWeightedTp() + mo.getWeight() * posScaleFactor);
        cmo.setWeightedFn(cmo.getWeightedFn() - mo.getWeight() * posScaleFactor);
      } else {
        // Negative Instance
        cmo.setFp(cmo.getFp() + negScaleFactor);
        cmo.setTn(cmo.getTn() - negScaleFactor);
        cmo.setWeightedFp(cmo.getWeightedFp() + mo.getWeight() * negScaleFactor);
        cmo.setWeightedTn(cmo.getWeightedTn() - mo.getWeight() * negScaleFactor);
      }

      cmo.setScore(mo.getScore());
      saveConfusionMaxtrixWithWriter(writer, cmo);
      prevCmo = cmo;
    }
  }
  private void saveConfusionMaxtrixWithWriter(BufferedWriter writer, ConfusionMatrixObject cmo) {
    try {
      writer.write(
          String.format(
              fmt,
              cmo.getTp(),
              cmo.getFp(),
              cmo.getFn(),
              cmo.getTn(),
              cmo.getWeightedTp(),
              cmo.getWeightedFp(),
              cmo.getWeightedFn(),
              cmo.getWeightedTn(),
              cmo.getScore()));
    } catch (IOException e) {
      try {
        writer.close();
      } catch (IOException e1) {
        log.error("Could not close the writer while write into confusion matrix");
      }

      log.error("Could not write into confusion matrix");
    }
  }