/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.kernel.statistics; import java.util.ArrayList; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.algos.AlgoBarChart; import org.geogebra.common.kernel.algos.AlgoElement; import org.geogebra.common.kernel.algos.TableAlgo; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoBoolean; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.kernel.geos.GeoText; /** * FrequencyTable[] algorithm based on AlgoFrequency * * @author Zbynek Konecny * */ public class AlgoFrequencyTable extends AlgoElement implements TableAlgo { private enum inputType { STANDARD, HISTOGRAM, BARCHART } private inputType type; private GeoList dataList; // input private GeoList classList; // input private GeoBoolean isCumulative; // input private GeoBoolean useDensity; // input private GeoNumeric density; // input private GeoNumeric scale; // input private GeoNumeric chart; // input // private GeoList frequency; //output private GeoText table; // output // for compute private AlgoFrequency freq; String[] strHeader = null; String[] strValue = null; String[] strFrequency = null; private StringBuilder sb = new StringBuilder(); private void createTable() { table = new GeoText(cons); table.setAbsoluteScreenLoc(0, 0); table.setAbsoluteScreenLocActive(true); } public AlgoFrequencyTable(Construction cons, String label, GeoBoolean isCumulative, GeoList classList, GeoList dataList) { this(cons, label, isCumulative, classList, dataList, null, null, null); } public AlgoFrequencyTable(Construction cons, String label, GeoBoolean isCumulative, GeoList classList, GeoList dataList, GeoNumeric scale) { this(cons, label, isCumulative, classList, dataList, null, null, scale); } public AlgoFrequencyTable(Construction cons, String label, GeoBoolean isCumulative, GeoList classList, GeoList dataList, GeoBoolean useDensity, GeoNumeric density) { this(cons, label, isCumulative, classList, dataList, useDensity, density, null); } public AlgoFrequencyTable(Construction cons, String label, GeoBoolean isCumulative, GeoList classList, GeoList dataList, GeoBoolean useDensity, GeoNumeric density, GeoNumeric scale) { this(cons, isCumulative, classList, dataList, useDensity, density, scale); table.setLabel(label); } public AlgoFrequencyTable(Construction cons, GeoBoolean isCumulative, GeoList classList, GeoList dataList, GeoBoolean useDensity, GeoNumeric density, GeoNumeric scale) { super(cons); this.classList = classList; this.dataList = dataList; this.isCumulative = isCumulative; this.useDensity = useDensity; this.density = density; this.scale = scale; freq = new AlgoFrequency(cons, isCumulative, classList, dataList, useDensity, density, scale); cons.removeFromConstructionList(freq); createTable(); type = inputType.STANDARD; setInputOutput(); compute(); table.isTextCommand = true; table.setLaTeX(true, false); } public AlgoFrequencyTable(Construction cons, String label, GeoNumeric chart) { this(cons, chart); table.setLabel(label); } public AlgoFrequencyTable(Construction cons, GeoNumeric chart) { super(cons); AlgoElement algo = chart.getParentAlgorithm(); if (algo instanceof AlgoHistogram) { type = inputType.HISTOGRAM; } else { type = inputType.BARCHART; } this.chart = chart; createTable(); setInputOutput(); compute(); table.isTextCommand = true; table.setLaTeX(true, false); } @Override public Commands getClassName() { return Commands.FrequencyTable; } @Override protected void setInputOutput() { switch (type) { case HISTOGRAM: case BARCHART: input = new GeoElement[1]; input[0] = chart; break; case STANDARD: ArrayList<GeoElement> tempList = new ArrayList<GeoElement>(); if (isCumulative != null) { tempList.add(isCumulative); } if (classList != null) { tempList.add(classList); } tempList.add(dataList); if (useDensity != null) { tempList.add(useDensity); } if (density != null) { tempList.add(density); } if (scale != null) { tempList.add(scale); } input = new GeoElement[tempList.size()]; input = tempList.toArray(input); break; } setOutputLength(1); setOutput(0, table); setDependencies(); // done by AlgoElement } public GeoText getResult() { return table; } public String[] getValueString() { if (!table.isDefined()) { return null; } return strValue; } public String[] getFrequencyString() { if (!table.isDefined()) { return null; } return strFrequency; } public String[] getHeaderString() { if (!table.isDefined()) { return null; } return strHeader; } @Override public final void compute() { switch (type) { case HISTOGRAM: AlgoHistogram algoHistogram = (AlgoHistogram) chart .getParentAlgorithm(); if (algoHistogram == null || algoHistogram.getLeftBorder() == null || algoHistogram.getValues() == null) { table.setUndefined(); return; } strHeader = new String[2]; strHeader[0] = getLoc().getMenu("Interval"); if (algoHistogram.getUseDensityGeo() != null && ((GeoBoolean) algoHistogram.getUseDensityGeo()) .getBoolean()) { strHeader[1] = getLoc().getMenu("Frequency"); } else { strHeader[1] = getLoc().getMenu("Count"); } double[] leftBorder = algoHistogram.getLeftBorder(); double[] f = algoHistogram.getValues(); strValue = new String[f.length]; strFrequency = new String[f.length]; for (int i = 0; i < f.length; i++) { strValue[i] = kernel.format(leftBorder[i], table.getStringTemplate()); strFrequency[i] = kernel.format(f[i], table.getStringTemplate()); } createLaTeXTable(true); break; case BARCHART: AlgoBarChart algoBarChart = (AlgoBarChart) chart .getParentAlgorithm(); if (algoBarChart == null || algoBarChart.getValue() == null || algoBarChart.getYValue() == null) { table.setUndefined(); return; } strHeader = new String[2]; strHeader[0] = getLoc().getMenu("Value"); strHeader[1] = getLoc().getMenu("Count"); strValue = algoBarChart.getValue(); double[] f2 = algoBarChart.getYValue(); strFrequency = new String[f2.length]; for (int i = 0; i < f2.length; i++) { strFrequency[i] = kernel.format(f2[i], table.getStringTemplate()); } createLaTeXTable(false); break; case STANDARD: // validate input arguments if (!freq.getResult().isDefined()) { table.setUndefined(); return; } boolean useDens = useDensity != null && useDensity.getBoolean(); GeoList fr = freq.getResult(); int length = fr.size(); // If classList does not exist, // get the unique value list and compute frequencies for this list if (classList == null) { if (scale != null) { useDens = true; // we assume this will be used to compute // frequencies } strHeader = new String[2]; strHeader[0] = getLoc().getMenu("Value"); if (useDens) { if (scale != null) { double scaleValue = scale.getDouble(); if (Kernel.isEqual(scaleValue, 1.0)) { strHeader[1] = getLoc() .getMenu("FrequencyTable.Count"); } else if (Kernel.isEqual(scaleValue * dataList.size(), 1)) { strHeader[1] = getLoc().getMenu( "FrequencyTable.RelativeFrequency"); } else { strHeader[1] = getLoc() .getMenu("FrequencyTable.Frequency"); } } else { strHeader[1] = getLoc() .getMenu("FrequencyTable.Frequency"); } } else { strHeader[1] = getLoc().getMenu("FrequencyTable.Count"); } strValue = new String[length]; strFrequency = new String[length]; GeoList va = freq.getValue(); for (int i = 0; i < length; i++) { strValue[i] = va.get(i) .toValueString(table.getStringTemplate()); strFrequency[i] = fr.get(i) .toValueString(table.getStringTemplate()); } createLaTeXTable(false); } // If classList exists, compute frequencies using the classList else { if (!classList.isDefined()) { table.setUndefined(); return; } strHeader = new String[2]; strHeader[0] = getLoc().getMenu("Interval"); strHeader[1] = useDens ? getLoc().getMenu("Frequency") : getLoc().getMenu("Count"); strValue = new String[length + 1]; strFrequency = new String[length + 1]; for (int i = 0; i < length; i++) { strValue[i] = classList.get(i) .toValueString(table.getStringTemplate()); strFrequency[i] = fr.get(i) .toValueString(table.getStringTemplate()); } // include final class limit strValue[length] = classList.get(length) .toValueString(table.getStringTemplate()); createLaTeXTable(true); } break; } table.setTextString(sb.toString()); } private void createLaTeXTable(boolean useClassList) { sb.setLength(0); sb.append("\\begin{array}{c|c}"); sb.append(strHeader[0]); sb.append("&\\text{"); sb.append(strHeader[1]); sb.append("} \\\\\\hline "); if (useClassList) { for (int i = 0; i < strFrequency.length - 1; i++) { sb.append(strValue[i]); sb.append("\\text{ -- }"); sb.append(strValue[i + 1]); sb.append("&"); sb.append(strFrequency[i]); sb.append("\\\\"); } } else { for (int i = 0; i < strFrequency.length; i++) { sb.append(strValue[i]); sb.append("&"); sb.append(strFrequency[i]); sb.append("\\\\"); } } sb.append("\\end{array}"); } }