/*
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.algos;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.StringTemplate;
import org.geogebra.common.kernel.arithmetic.ExpressionNode;
import org.geogebra.common.kernel.arithmetic.FunctionVariable;
import org.geogebra.common.kernel.arithmetic.MyBoolean;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoFunction;
import org.geogebra.common.kernel.geos.GeoList;
import org.geogebra.common.kernel.geos.GeoNumeric;
/**
*
* @author Michael
*/
public class AlgoCountIf extends AlgoElement {
private GeoFunction boolFun; // input
private GeoList list;
private GeoNumeric result; // output
/**
* Algorithm for handling of a CountIf construct
*
* @param cons
* construction
* @param label
* output label
* @param boolFun
* filter function
* @param list
* filtered list
*/
public AlgoCountIf(Construction cons, String label, GeoFunction boolFun,
GeoList list) {
super(cons);
this.boolFun = boolFun;
this.list = list;
// create output GeoElement of same type as ifGeo
result = new GeoNumeric(cons);
setInputOutput(); // for AlgoElement
// compute value of dependent number
compute();
result.setLabel(label);
}
@Override
public Commands getClassName() {
return Commands.CountIf;
}
// for AlgoElement
@Override
protected void setInputOutput() {
input = new GeoElement[2];
input[0] = boolFun;
input[1] = list;
super.setOutputLength(1);
super.setOutput(0, result);
setDependencies(); // done by AlgoElement
}
/**
* @return object count
*/
public GeoNumeric getResult() {
return result;
}
@Override
public final void compute() {
try {
int count = 0;
/*
* If val is not numeric, we use the underlying Expression of the
* function and plug the list element as variable. Deep copy is
* needed so that we can plug the value repeatedly.
*/
FunctionVariable var = boolFun.getFunction().getFunctionVariable();
for (int i = 0; i < list.size(); i++) {
GeoElement val = list.get(i);
if (val.isGeoNumeric()) {
if (boolFun.evaluateBoolean(((GeoNumeric) val).getValue())) {
count++;
}
} else {
ExpressionNode ex = boolFun.getFunction()
.getExpression().deepCopy(kernel);
ex = ex.replace(var,
val.evaluate(StringTemplate.defaultTemplate))
.wrap();
if (((MyBoolean) ex
.evaluate(StringTemplate.defaultTemplate))
.getBoolean()) {
count++;
}
}
}
result.setValue(count);
} catch (Exception e) {
result.setUndefined();
}
}
}