package org.geogebra.common.gui.view.probcalculator;
import java.util.HashMap;
import java.util.Map.Entry;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.StringTemplate;
import org.geogebra.common.kernel.arithmetic.ExpressionNodeConstants;
import org.geogebra.common.kernel.arithmetic.ExpressionNodeConstants.StringType;
import org.geogebra.common.kernel.arithmetic.NumberValue;
import org.geogebra.common.main.App;
import org.geogebra.common.main.Localization;
import org.geogebra.common.util.TextObject;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* @author gabor StatisticCalculator common superclass
*/
public abstract class StatisticsCalculator {
protected Construction cons;
protected StatisticsCollection sc;
protected StatisticsCalculatorProcessor statProcessor;
protected StatisticsCalculatorHTML statHTML;
protected Kernel kernel;
final static protected int fieldWidth = 6;
protected TextObject fldSigma, fldNullHyp, fldConfLevel;
protected TextObject[] fldSampleStat1, fldSampleStat2;
// =========================================
// Procedures
// =========================================
/***/
public enum Procedure {
ZMEAN_TEST, ZMEAN2_TEST, TMEAN_TEST, TMEAN2_TEST, ZPROP_TEST, ZPROP2_TEST, ZMEAN_CI, ZMEAN2_CI, TMEAN_CI, TMEAN2_CI, ZPROP_CI, ZPROP2_CI, GOF_TEST, CHISQ_TEST
}
protected Procedure selectedProcedure;
protected HashMap<String, Procedure> mapNameToProcedure;
protected HashMap<Procedure, String> mapProcedureToName;
// =========================================
// Misc
// =========================================
public static final String tail_left = "<";
public static final String tail_right = ">";
public static final String tail_two = ExpressionNodeConstants.strNOT_EQUAL;
protected StringBuilder bodyText;
protected String strMean;
protected String strSD;
protected String strSigma;
protected String strSuccesses;
protected String strN;
// protected String strPooled;
protected double[] s1;
protected double[] s2;
protected Localization loc;
protected App app;
// =========================================
// Getters/Setters
// =========================================
@SuppressFBWarnings({ "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD",
"false positive, used in web and desktop" })
public StatisticsCalculator(App app) {
this.loc = app.getLocalization();
this.app = app;
cons = app.getKernel().getConstruction();
kernel = cons.getKernel();
sc = new StatisticsCollection();
statProcessor = new StatisticsCalculatorProcessor(app, this, sc);
statHTML = new StatisticsCalculatorHTML(app, this, sc);
selectedProcedure = Procedure.ZMEAN_TEST;
}
public Procedure getSelectedProcedure() {
return selectedProcedure;
}
/**
* Formats a number string using local format settings.
*
* @param x
* @return
*/
public String format(double x) {
StringTemplate highPrecision;
if (kernel.useSignificantFigures) {
highPrecision = StringTemplate.printFigures(StringType.GEOGEBRA,
kernel.getPrintFigures(), false);
} else {
// override the default decimal place if < 4
int d = kernel.getPrintDecimals() < 4 ? 4
: cons.getKernel().getPrintDecimals();
highPrecision = StringTemplate.printDecimals(StringType.GEOGEBRA, d,
false);
}
// get the formatted string
String result = kernel.format(x, highPrecision);
return result;
}
public HashMap<Procedure, String> getMapProcedureToName() {
return mapProcedureToName;
}
public StatisticsCalculatorProcessor getStatProcessor() {
return statProcessor;
}
public StatisticsCollection getStatististicsCollection() {
return sc;
}
public final void updateResult() {
updateStatisticCollection();
statProcessor.doCalculate();
bodyText = new StringBuilder();
bodyText.append(statHTML.getStatString());
updateResultText(bodyText.toString());
// prevent auto scrolling
resetCaret();
}
private double parseNumberText(String s) {
if (s == null || s.length() == 0) {
return Double.NaN;
}
try {
String inputText = s.trim();
// allow input such as sqrt(2)
NumberValue nv;
nv = cons.getKernel().getAlgebraProcessor()
.evaluateToNumeric(inputText, false);
return nv.getDouble();
} catch (NumberFormatException e) {
e.printStackTrace();
}
return Double.NaN;
}
final protected void updateStatisticCollection() {
try {
sc.level = parseNumberText(fldConfLevel.getText());
sc.sd = parseNumberText(fldSigma.getText());
sc.nullHyp = parseNumberText(fldNullHyp.getText());
if (btnLeftIsSelected()) {
sc.tail = tail_left;
} else if (btnRightIsSelected()) {
sc.tail = tail_right;
} else {
sc.tail = tail_two;
}
for (int i = 0; i < s1.length; i++) {
s1[i] = (parseNumberText(fldSampleStat1[i].getText()));
}
for (int i = 0; i < s2.length; i++) {
s2[i] = (parseNumberText(fldSampleStat2[i].getText()));
}
updateCollectionProcedure();
setSampleFieldText();
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
final protected void setSampleFieldText() {
for (int i = 0; i < 3; i++) {
removeActionListener(fldSampleStat1[i]);
removeActionListener(fldSampleStat2[i]);
fldSampleStat1[i].setText("");
fldSampleStat2[i].setText("");
}
switch (selectedProcedure) {
default:
// do nothing
break;
case ZMEAN_TEST:
case ZMEAN_CI:
case TMEAN_TEST:
case TMEAN_CI:
fldSampleStat1[0].setText(format(sc.mean));
fldSampleStat1[1].setText(format(sc.sd));
fldSampleStat1[2].setText(format(sc.n));
break;
case ZMEAN2_TEST:
case ZMEAN2_CI:
case TMEAN2_TEST:
case TMEAN2_CI:
fldSampleStat1[0].setText(format(sc.mean));
fldSampleStat1[1].setText(format(sc.sd));
fldSampleStat1[2].setText(format(sc.n));
fldSampleStat2[0].setText(format(sc.mean2));
fldSampleStat2[1].setText(format(sc.sd2));
fldSampleStat2[2].setText(format(sc.n2));
break;
case ZPROP_TEST:
case ZPROP_CI:
fldSampleStat1[0].setText(format(sc.count));
fldSampleStat1[1].setText(format(sc.n));
break;
case ZPROP2_TEST:
case ZPROP2_CI:
fldSampleStat1[0].setText(format(sc.count));
fldSampleStat1[1].setText(format(sc.n));
fldSampleStat2[0].setText(format(sc.count2));
fldSampleStat2[1].setText(format(sc.n2));
break;
}
for (int i = 0; i < 3; i++) {
addActionListener(fldSampleStat1[i]);
addActionListener(fldSampleStat2[i]);
}
fldConfLevel.setText(format(sc.level));
fldNullHyp.setText(format(sc.nullHyp));
}
protected void addActionListener(TextObject textObject) {
// not needed in web
}
protected void removeActionListener(TextObject textObject) {
// not needed in web
}
abstract protected boolean btnRightIsSelected();
abstract protected boolean btnLeftIsSelected();
protected abstract void resetCaret();
protected abstract void updateResultText(String string);
protected void combolabelsPreprocess() {
if (mapNameToProcedure == null) {
mapNameToProcedure = new HashMap<String, Procedure>();
}
if (mapProcedureToName == null) {
mapProcedureToName = new HashMap<Procedure, String>();
}
mapNameToProcedure.clear();
mapProcedureToName.clear();
mapNameToProcedure.put(loc.getMenu("ZMeanTest"), Procedure.ZMEAN_TEST);
mapNameToProcedure.put(loc.getMenu("ZMeanTest"), Procedure.ZMEAN_TEST);
mapNameToProcedure.put(loc.getMenu("TMeanTest"), Procedure.TMEAN_TEST);
mapNameToProcedure.put(loc.getMenu("ZMeanInterval"),
Procedure.ZMEAN_CI);
mapNameToProcedure.put(loc.getMenu("TMeanInterval"),
Procedure.TMEAN_CI);
mapNameToProcedure.put(loc.getMenu("ZTestDifferenceOfMeans"),
Procedure.ZMEAN2_TEST);
mapNameToProcedure.put(loc.getMenu("TTestDifferenceOfMeans"),
Procedure.TMEAN2_TEST);
mapNameToProcedure.put(loc.getMenu("ZEstimateDifferenceOfMeans"),
Procedure.ZMEAN2_CI);
mapNameToProcedure.put(loc.getMenu("TEstimateDifferenceOfMeans"),
Procedure.TMEAN2_CI);
mapNameToProcedure.put(loc.getMenu("ZProportionTest"),
Procedure.ZPROP_TEST);
mapNameToProcedure.put(loc.getMenu("ZProportionInterval"),
Procedure.ZPROP_CI);
mapNameToProcedure.put(loc.getMenu("ZTestDifferenceOfProportions"),
Procedure.ZPROP2_TEST);
mapNameToProcedure.put(loc.getMenu("ZEstimateDifferenceOfProportions"),
Procedure.ZPROP2_CI);
mapNameToProcedure.put(loc.getMenu("GoodnessOfFitTest"),
Procedure.GOF_TEST);
mapNameToProcedure.put(loc.getMenu("ChiSquaredTest"),
Procedure.CHISQ_TEST);
for (Entry<String, Procedure> entry : mapNameToProcedure.entrySet()) {
this.mapProcedureToName.put(entry.getValue(), entry.getKey());
}
}
@SuppressFBWarnings({ "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD",
"false positive, used in web and desktop" })
protected void setLabelStrings() {
strMean = loc.getMenu("Mean");
strSD = loc.getMenu("SampleStandardDeviation.short");
strSigma = loc.getMenu("StandardDeviation.short");
strSuccesses = loc.getMenu("Successes");
strN = loc.getMenu("N");
// strPooled = loc.getMenu("Pooled");
}
public App getApp() {
return kernel.getApplication();
}
protected void updateCollectionProcedure() {
switch (selectedProcedure) {
default:
// do nothing
break;
case ZMEAN_TEST:
case ZMEAN_CI:
case TMEAN_TEST:
case TMEAN_CI:
sc.mean = s1[0];
sc.sd = s1[1];
sc.n = s1[2];
break;
case ZMEAN2_TEST:
case ZMEAN2_CI:
case TMEAN2_TEST:
case TMEAN2_CI:
sc.mean = s1[0];
sc.sd = s1[1];
sc.n = s1[2];
sc.mean2 = s2[0];
sc.sd2 = s2[1];
sc.n2 = s2[2];
// force the null hypothesis to zero
// TODO: allow non-zero values
sc.nullHyp = 0;
break;
case ZPROP_TEST:
case ZPROP_CI:
sc.count = s1[0];
sc.n = s1[1];
break;
case ZPROP2_TEST:
case ZPROP2_CI:
sc.count = s1[0];
sc.n = s1[1];
sc.count2 = s2[0];
sc.n2 = s2[1];
// force the null hypothesis to zero
// TODO: allow non-zero values
sc.nullHyp = 0;
break;
}
sc.validate();
}
}