001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.plugins.core.timemachine; 021 022 import java.util.List; 023 024 public class TendencyAnalyser { 025 026 public static final Integer TENDENCY_BIG_UP = 2; 027 public static final Integer TENDENCY_UP = 1; 028 public static final Integer TENDENCY_NEUTRAL = 0; 029 public static final Integer TENDENCY_DOWN = -1; 030 public static final Integer TENDENCY_BIG_DOWN = -2; 031 032 public Integer analyseLevel(List<Double> values) { 033 TendencyAnalyser.SlopeData slopeData = analyse(values); 034 if (slopeData != null) { 035 return slopeData.getLevel(); 036 } 037 return null; 038 } 039 040 public SlopeData analyse(List<Double> values) { 041 double sumY = 0.0; 042 double sumX = 0.0; 043 double sumYPower2 = 0.0; 044 double sumXY = 0.0; 045 double sumXPower2 = 0.0; 046 int nbrPoints = 0; 047 boolean nullValuesYList = true; 048 int i = 0; 049 for (Double p : values) { 050 if (p != null) { 051 nullValuesYList = false; 052 //SumY calculation 053 sumY += p; 054 // sumYPower2 calculation 055 sumYPower2 += p * p; 056 //sumXY calculation 057 sumXY += p * (i + 1); 058 //SumX calculation 059 sumX += (i + 1); 060 //sumXPower2 calculation 061 sumXPower2 += (i + 1) * (i + 1); 062 //Point number calculation 063 nbrPoints++; 064 } 065 i++; 066 } 067 // no tendency if null values or only 1 value 068 if (nullValuesYList || nbrPoints == 1) { 069 return null; 070 } 071 double n0 = (((nbrPoints) * (sumXY)) - ((sumX) * (sumY))); 072 double d = (((nbrPoints) * (sumXPower2)) - ((sumX) * (sumX))); 073 double n1 = (((sumY) * (sumXPower2)) - ((sumX) * (sumXY))); 074 075 SlopeData result = new SlopeData(); 076 077 //yIntercept Calculation the value when X equals zero 078 result.setYIntercept(n1 / d); 079 // Slope Calculation 080 if (n0 == 0d && d == 0d) { 081 result.setSlope(0.0); 082 } else { 083 Double slope = n0 / d; 084 if (Double.isNaN(slope) || Double.isInfinite(slope)) { 085 result.setSlope(null); 086 } else { 087 result.setSlope(slope); 088 } 089 } 090 result.setSumXPower2(sumXPower2); 091 result.setSumXY(sumXY); 092 result.setSumYPower2(sumYPower2); 093 094 if (sumXPower2 == 0 || sumYPower2 == 0) { 095 result.setCorrelationRate(0.0); 096 } else { 097 result.setCorrelationRate((sumXY) / (Math.sqrt(sumXPower2 * sumYPower2))); 098 } 099 100 return result; 101 } 102 103 104 static class SlopeData { 105 private double sumXPower2; 106 private double sumYPower2; 107 private double sumXY; 108 private double yIntercept; // not used today 109 private Double slope; 110 private Double correlationRate; 111 112 public double getSumXPower2() { 113 return sumXPower2; 114 } 115 116 public void setSumXPower2(double sumXPower2) { 117 this.sumXPower2 = sumXPower2; 118 } 119 120 public double getSumYPower2() { 121 return sumYPower2; 122 } 123 124 public void setSumYPower2(double sumYPower2) { 125 this.sumYPower2 = sumYPower2; 126 } 127 128 public double getSumXY() { 129 return sumXY; 130 } 131 132 public void setSumXY(double sumXY) { 133 this.sumXY = sumXY; 134 } 135 136 public double getYIntercept() { 137 return yIntercept; 138 } 139 140 public void setYIntercept(double yIntercept) { 141 this.yIntercept = yIntercept; 142 } 143 144 public Double getSlope() { 145 return slope; 146 } 147 148 public void setSlope(Double slope) { 149 this.slope = slope; 150 } 151 152 public Double getCorrelationRate() { 153 return correlationRate; 154 } 155 156 public void setCorrelationRate(Double correlationRate) { 157 this.correlationRate = correlationRate; 158 } 159 160 public Integer getLevel() { 161 double hSlope = 0.8; 162 double nSlope = 0.2; 163 164 double vHighCorcoef = 1.0; 165 double modCorcoef = 0.69; 166 Double correlationCoeff = getCorrelationRate(); 167 boolean vHCorCoefPos = (correlationCoeff > modCorcoef) && (correlationCoeff <= vHighCorcoef); 168 boolean vHCorCoefNeg = (correlationCoeff < -modCorcoef) && (correlationCoeff >= -vHighCorcoef); 169 170 if ((vHCorCoefPos || vHCorCoefNeg) && (slope >= hSlope)) { 171 return TENDENCY_BIG_UP; 172 173 } else if ((vHCorCoefPos || vHCorCoefNeg) && (slope <= -hSlope)) { 174 return TENDENCY_BIG_DOWN; 175 176 } else if ((vHCorCoefPos || vHCorCoefNeg) && ((slope >= nSlope) && (slope < hSlope))) { 177 return TENDENCY_UP; 178 179 } else if ((vHCorCoefPos || vHCorCoefNeg) && ((slope <= -nSlope) && (slope > -hSlope))) { 180 return TENDENCY_DOWN; 181 182 } else if ((vHCorCoefPos || vHCorCoefNeg) && ((slope < nSlope) || (slope > -nSlope))) { 183 return TENDENCY_NEUTRAL; 184 185 } else if (correlationCoeff == 0 && slope == 0 && !vHCorCoefPos && !vHCorCoefNeg) { 186 return TENDENCY_NEUTRAL; 187 } 188 return null; 189 } 190 } 191 }