package cn.com.qmth.stmms.biz.report.utils.unit;

import cn.com.qmth.stmms.common.utils.BigDecimalUtils;

public class BaseCalculatorUnit {

    public int count;

    public int zeroCount;

    public int fullCount;

    public double fullScore;

    public Double passScore;

    public int passCount;

    public double passRate;

    public Double excellentScore;

    public int excellentCount;

    public double excellentRate;

    public double aggScore;

    public double sumScore;

    public double sumScore2;

    public double sumTotalScore;

    public double sumTotalScore2;

    public double maxScore;

    public double minScore;

    public double avgScore;

    public double stdev;

    public double tempSum;

    public double difficulty;

    public double coefficient;

    public double discrimination;

    public double fullScoreRate;

    public BaseCalculatorUnit() {
        minScore = Double.MAX_VALUE;
    }

    public void process(Double score, Double fullScore, Double totalScore) {
        if (score == null || fullScore == null || totalScore == null) {
            return;
        }
        if (this.fullScore == 0) {
            this.fullScore = fullScore;
        }
        count++;
        if (score == 0) {
            zeroCount++;
        } else if (score.equals(fullScore)) {
            fullCount++;
        }
        if (passScore != null && score >= passScore) {
            passCount++;
        }
        if (excellentScore != null && score >= excellentScore) {
            excellentCount++;
        }
        sumScore = BigDecimalUtils.add(score, sumScore);
        sumScore2 = BigDecimalUtils.add(sumScore2, BigDecimalUtils.mul(score, score));
        aggScore = BigDecimalUtils.add(aggScore, BigDecimalUtils.mul(score, totalScore));
        sumTotalScore = BigDecimalUtils.add(sumTotalScore, totalScore);
        sumTotalScore2 = BigDecimalUtils.add(sumTotalScore2, BigDecimalUtils.mul(totalScore, totalScore));
        maxScore = Math.max(maxScore, score);
        minScore = Math.min(minScore, score);
        avgScore = BigDecimalUtils.div(sumScore, count);
        // 递归法计算标准差
        stdev = Math.sqrt(BigDecimalUtils.sub(BigDecimalUtils.div(sumScore2, count),
                BigDecimalUtils.mul(avgScore, avgScore)));
        if (Double.isNaN(stdev)) {
            stdev = 0;
        }
        // 难度
        difficulty = fullScore > 0 ? BigDecimalUtils.div(avgScore, fullScore) : 0;
        // 差异系数
        coefficient = avgScore > 0 ? BigDecimalUtils.div(stdev * 100, avgScore) : 0;
        // 区分度
        double temp = Math.sqrt((sumScore2 - sumScore * sumScore / count)
                * (sumTotalScore2 - sumTotalScore * sumTotalScore / count));
        if (temp != 0 && Double.NaN != temp) {
            discrimination = (aggScore - sumScore * sumTotalScore / count) / temp;
            if (Double.isNaN(discrimination)) {
                discrimination = 0;
            }
        } else {
            discrimination = 0;
        }
        // 及格率
        passRate = BigDecimalUtils.div(passCount, count);
        // 优秀率
        excellentRate = BigDecimalUtils.div(excellentCount, count);
        // 满分率
        fullScoreRate = BigDecimalUtils.div(fullCount, count);
    }

    @Override
    public String toString() {
        return "count=" + count + ",zeroCount=" + zeroCount + ",fullCount=" + fullCount + ",fullScore=" + fullScore
                + ",maxScore=" + maxScore + ",minScore=" + minScore + ",avgScore=" + avgScore + ",stdev=" + stdev
                + ",difficulty=" + difficulty + ",coefficient=" + coefficient + ",discrimination=" + discrimination;
    }
}
