// Path: dkpro-statistics-agreement/src/main/java/org/dkpro/statistics/agreement/IAnnotationUnit.java
// public interface IAnnotationUnit
//     extends Serializable
// {
//     /**
//      * Returns the index of the rater who coded this unit (in case of a coding study) or defined the
//      * boundaries of this unit (in case of a unitizing study). The first rater has index 0.
//      */
//     public int getRaterIdx();
// 
//     /**
//      * Returns the category assigned to this unit by one of the raters. The category might be null
//      * if, and only if, the unit represents a missing value (in case of a coding study) or a gap (in
//      * case of a unitizing study).
//      */
//     public Object getCategory();
// }
// 
// Path: dkpro-statistics-agreement/src/main/java/org/dkpro/statistics/agreement/ICategorySpecificAgreement.java
// public interface ICategorySpecificAgreement
// {
//     /**
//      * Calculates the inter-rater agreement for the given category.
//      * 
//      * @see ICategorySpecificAgreement
//      */
//     /*
//      * TODO @throws NullPointerException if the study is null or the given category is null.
//      * 
//      * @throws ArrayIndexOutOfBoundsException if the study does not contain the given category.
//      * 
//      * @throws ArithmeticException if the study does not contain annotations for the given category.
//      */
//     public double calculateCategoryAgreement(final Object category);
// }
// 
// Path: dkpro-statistics-agreement/src/main/java/org/dkpro/statistics/agreement/IChanceCorrectedAgreement.java
// public interface IChanceCorrectedAgreement
//     extends IAgreementMeasure
// {
//     /**
//      * Returns the observed agreement of an annotation study. The observed agreement is basically
//      * the proportion of annotation units that the raters agree on divided by the number of units in
//      * the given study.
//      */
//     public double calculateObservedAgreement();
// 
//     /**
//      * Returns the expected agreement of an annotation study. The expected agreement is the
//      * proportion of agreement that would be expected by chance alone. The expected agreement should
//      * be equal to the observed agreement if each rater makes a random decision for each unit.
//      */
//     public double calculateExpectedAgreement();
// }


import java.math.BigDecimal;
import java.math.MathContext;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.dkpro.statistics.agreement.IAnnotationUnit;
import org.dkpro.statistics.agreement.ICategorySpecificAgreement;
import org.dkpro.statistics.agreement.IChanceCorrectedAgreement;
     * @date 04.03.2011
     */
    /*
     * Calculates the inter-rater agreement for the given annotation category based on the object's
     * annotation study that has been passed to the class constructor.
     * 
     * @throws NullPointerException if the study is null or the given category is null.
     * 
     * @throws ArrayIndexOutOfBoundsException if the study does not contain the given category.
     * 
     * @throws ArithmeticException if the study does not contain annotations for the given category.
     */
    @Override
    public double calculateCategoryAgreement(final Object category)
    {
        // N = # subjects = #items -> index i
        // n = # ratings/subject = #raters
        // k = # categories -> index j
        // n_ij = # raters that annotated item i as category j
        //
        // k_j = (P_j - p_j) / (1 - p_j)
        // P_j = (sum( n_ij^2 ) - N n p_j) / (N n (n-1) p_j )
        // p_j = 1/Nn sum n_ij

        int N = study.getItemCount();
        int n = study.getRaterCount();
        int sum_nij = 0;
        int sum_nij_2 = 0;
        for (ICodingAnnotationItem item : study.getItems()) {
            int nij = 0;
// Path: dkpro-statistics-agreement/src/main/java/org/dkpro/statistics/agreement/IAnnotationUnit.java
// public interface IAnnotationUnit
//     extends Serializable
// {
//     /**
//      * Returns the index of the rater who coded this unit (in case of a coding study) or defined the
//      * boundaries of this unit (in case of a unitizing study). The first rater has index 0.
//      */
//     public int getRaterIdx();
// 
//     /**
//      * Returns the category assigned to this unit by one of the raters. The category might be null
//      * if, and only if, the unit represents a missing value (in case of a coding study) or a gap (in
//      * case of a unitizing study).
//      */
//     public Object getCategory();
// }
// 
// Path: dkpro-statistics-agreement/src/main/java/org/dkpro/statistics/agreement/ICategorySpecificAgreement.java
// public interface ICategorySpecificAgreement
// {
//     /**
//      * Calculates the inter-rater agreement for the given category.
//      * 
//      * @see ICategorySpecificAgreement
//      */
//     /*
//      * TODO @throws NullPointerException if the study is null or the given category is null.
//      * 
//      * @throws ArrayIndexOutOfBoundsException if the study does not contain the given category.
//      * 
//      * @throws ArithmeticException if the study does not contain annotations for the given category.
//      */
//     public double calculateCategoryAgreement(final Object category);
// }
// 
// Path: dkpro-statistics-agreement/src/main/java/org/dkpro/statistics/agreement/IChanceCorrectedAgreement.java
// public interface IChanceCorrectedAgreement
//     extends IAgreementMeasure
// {
//     /**
//      * Returns the observed agreement of an annotation study. The observed agreement is basically
//      * the proportion of annotation units that the raters agree on divided by the number of units in
//      * the given study.
//      */
//     public double calculateObservedAgreement();
// 
//     /**
//      * Returns the expected agreement of an annotation study. The expected agreement is the
//      * proportion of agreement that would be expected by chance alone. The expected agreement should
//      * be equal to the observed agreement if each rater makes a random decision for each unit.
//      */
//     public double calculateExpectedAgreement();
// }


// Path: dkpro-statistics-agreement/src/main/java/org/dkpro/statistics/agreement/coding/FleissKappaAgreement.java
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.dkpro.statistics.agreement.IAnnotationUnit;
import org.dkpro.statistics.agreement.ICategorySpecificAgreement;
import org.dkpro.statistics.agreement.IChanceCorrectedAgreement;

     * @date 04.03.2011
     */
    /*
     * Calculates the inter-rater agreement for the given annotation category based on the object's
     * annotation study that has been passed to the class constructor.
     * 
     * @throws NullPointerException if the study is null or the given category is null.
     * 
     * @throws ArrayIndexOutOfBoundsException if the study does not contain the given category.
     * 
     * @throws ArithmeticException if the study does not contain annotations for the given category.
     */
    @Override
    public double calculateCategoryAgreement(final Object category)
    {
        // N = # subjects = #items -> index i
        // n = # ratings/subject = #raters
        // k = # categories -> index j
        // n_ij = # raters that annotated item i as category j
        //
        // k_j = (P_j - p_j) / (1 - p_j)
        // P_j = (sum( n_ij^2 ) - N n p_j) / (N n (n-1) p_j )
        // p_j = 1/Nn sum n_ij

        int N = study.getItemCount();
        int n = study.getRaterCount();
        int sum_nij = 0;
        int sum_nij_2 = 0;
        for (ICodingAnnotationItem item : study.getItems()) {
            int nij = 0;
            for (IAnnotationUnit annotation : item.getUnits()) {