com.userweave.module.methoden.iconunderstandability.service.ComputeIconTestStatisticsImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.userweave.module.methoden.iconunderstandability.service.ComputeIconTestStatisticsImpl.java

Source

/*******************************************************************************
 * This file is part of UserWeave.
 *
 *     UserWeave is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     UserWeave is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with UserWeave.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright 2012 User Prompt GmbH | Psychologic IT Expertise
 *******************************************************************************/
package com.userweave.module.methoden.iconunderstandability.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import org.apache.commons.math.stat.regression.SimpleRegression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.userweave.module.methoden.iconunderstandability.dao.ITMTestResultDao;
import com.userweave.module.methoden.iconunderstandability.dao.ReactionTimeStatisticsDao;
import com.userweave.module.methoden.iconunderstandability.domain.report.IconTestReactionTimeStatistics;

@Service(value = "computeIconTestStatistics")
public class ComputeIconTestStatisticsImpl implements ComputeIconTestStatistics {

    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ITMTestResultDao testResultDao;

    @Autowired
    private ReactionTimeStatisticsDao reactionTimeStatisticsDao;

    public void computeStatisticsAndSave() {
        LOGGER.info("computeStatisticsAndSave : cron job started");

        final OverallStatistics overallStatistics = computeOverallStatistics();

        if (overallStatistics != null) {

            for (int iconCount = 2; iconCount < 40; iconCount++) {

                IconTestReactionTimeStatistics statisticsEntity = getStatisticsPersistentEntityForIconCount(
                        iconCount);

                setMeanReactionTime(overallStatistics, iconCount, statisticsEntity);

                setRegression(overallStatistics, iconCount, statisticsEntity);

                reactionTimeStatisticsDao.save(statisticsEntity);
            }
        }
        LOGGER.info("computeStatisticsAndSave : cron job finished");
    }

    private void setRegression(final OverallStatistics overallStatistics, int iconCount,
            IconTestReactionTimeStatistics statisticsEntity) {

        // set regress if regression was computed
        if (overallStatistics.hasValidRegression()) {
            statisticsEntity.setRegressionValue(overallStatistics.getRegression().predict(iconCount));
        } else { // set mean otherwise
            statisticsEntity.setRegressionValue(overallStatistics.getMean());
        }
    }

    private void setMeanReactionTime(final OverallStatistics overallStatistics, int iconCount,
            IconTestReactionTimeStatistics statisticsEntity) {
        final DescriptiveStatistics statisticsForIconCount = overallStatistics.getIconCount2Statistics()
                .get(new Integer(iconCount));
        if (statisticsForIconCount != null) {
            statisticsEntity.setMeanReactionTime(statisticsForIconCount.getMean());
        } else {
            statisticsEntity.setMeanReactionTime(-1);
        }
    }

    private IconTestReactionTimeStatistics getStatisticsPersistentEntityForIconCount(int iconCount) {
        IconTestReactionTimeStatistics reactionTimeStatistics = reactionTimeStatisticsDao
                .findByIconCount(iconCount);

        if (reactionTimeStatistics == null) {
            reactionTimeStatistics = new IconTestReactionTimeStatistics();
            reactionTimeStatistics.setIconCount(iconCount);
        }
        return reactionTimeStatistics;
    }

    // contains 
    // 1. regression and mean for all icons
    // 2. map of descriptive statistics for each icon count
    private class OverallStatistics {

        public OverallStatistics(SimpleRegression regression, Double mean,
                Map<Integer, DescriptiveStatistics> iconCount2Statistics) {
            super();
            this.regression = regression;
            this.mean = mean;
            this.iconCount2Statistics = iconCount2Statistics;
        }

        public Map<Integer, DescriptiveStatistics> getIconCount2Statistics() {
            return iconCount2Statistics;
        }

        private final SimpleRegression regression;

        public SimpleRegression getRegression() {
            return regression;
        }

        private final Double mean;

        public Double getMean() {
            return mean;
        }

        public boolean hasValidRegression() {
            return regression != null;
        }

        private final Map<Integer, DescriptiveStatistics> iconCount2Statistics;

    };

    /**
     * return regression, if regression can be computed
     * @return
     */
    private OverallStatistics computeOverallStatistics() {

        SimpleRegression regression = new SimpleRegression();

        DescriptiveStatistics overallStatistics = DescriptiveStatistics.newInstance();

        Map<Integer, DescriptiveStatistics> iconCount2Statistics = new HashMap<Integer, DescriptiveStatistics>();

        List<Object[]> executionTimesIconCount = testResultDao.findAllValidExecutionTimesAndIconCount();

        if (!executionTimesIconCount.isEmpty()) {

            // check, if there is variation in x (only one x value for all observation yield NaN!)
            boolean canComputeRegression = false;

            int iconCountForFirstResult = ((Long) executionTimesIconCount.get(0)[1]).intValue();

            for (Object[] executionTimeIconCount : executionTimesIconCount) {

                int iconCount = ((Long) executionTimeIconCount[1]).intValue();
                if (iconCount != iconCountForFirstResult) {
                    canComputeRegression = true;
                }

                double executionTime = (Long) executionTimeIconCount[0];

                if (isValid(executionTime)) {
                    regression.addData(iconCount, executionTime);
                    overallStatistics.addValue(executionTime);
                    getStatisticsForIconCount(iconCount2Statistics, iconCount).addValue(executionTime);
                }
            }

            if (canComputeRegression) {
                return new OverallStatistics(regression, overallStatistics.getMean(), iconCount2Statistics);
            } else {
                return new OverallStatistics(null, overallStatistics.getMean(), iconCount2Statistics);
            }
        } else {
            return null;
        }
    }

    private DescriptiveStatistics getStatisticsForIconCount(
            Map<Integer, DescriptiveStatistics> iconCount2Statistics, int iconCount) {
        final Integer count = new Integer(iconCount);
        DescriptiveStatistics statsForIconCount = iconCount2Statistics.get(count);
        if (statsForIconCount == null) {
            statsForIconCount = DescriptiveStatistics.newInstance();
            iconCount2Statistics.put(count, statsForIconCount);
        }
        return statsForIconCount;
    }

    private boolean isValid(double value) {

        // only accept values betwenn minSeconds and maxSeconds
        double minSeconds = 1.5;

        double maxSeconds = 60;

        return ((value > minSeconds * 1000) && (value < maxSeconds * 1000));
    }

}