/* 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 java.util.ArrayList; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.arithmetic.ExpressionNode; import org.geogebra.common.kernel.arithmetic.MyList; import org.geogebra.common.kernel.arithmetic.MyNumberPair; 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.Test; import org.geogebra.common.plugin.Operation; /** * * @author Markus */ public class AlgoIf extends AlgoElement { private GeoElement result; // output private ArrayList<GeoElement> alternatives; private ArrayList<GeoBoolean> conditions; /** * Algorithm for handling of an if-then-else construct * * @param cons * construction * @param label * output label * @param conditions * bool expressions * @param alternatives * possible outputs * */ public AlgoIf(Construction cons, String label, ArrayList<GeoBoolean> conditions, ArrayList<GeoElement> alternatives) { super(cons); this.conditions = conditions; this.alternatives = alternatives; this.result = alternatives.get(0); // create output GeoElement of same type as ifGeo int i = 1; while (i < alternatives.size() && Test.canSet(alternatives.get(i), result)) { result = alternatives.get(i); i++; } result = result.copyInternal(cons); setInputOutput(); // for AlgoElement // compute value of dependent number compute(); result.setLabel(label); } @Override public Commands getClassName() { return Commands.If; } // for AlgoElement @Override protected void setInputOutput() { input = new GeoElement[conditions.size() + alternatives.size()]; for (int i = 0; i < this.conditions.size(); i++) { input[2 * i] = conditions.get(i); input[2 * i + 1] = alternatives.get(i); } if (alternatives.size() > conditions.size()) { input[input.length - 1] = alternatives.get(alternatives.size() - 1); } super.setOutputLength(1); super.setOutput(0, result); setDependencies(); // done by AlgoElement } /** * @return result */ public GeoElement getGeoElement() { return result; } // calc the current value of the arithmetic tree @Override public final void compute() { try { for (int i = 0; i < conditions.size(); i++) { if (conditions.get(i).getBoolean()) { setResult(alternatives.get(i)); return; } GeoElement last = alternatives.get(alternatives.size() - 1); if (conditions.size() == alternatives.size()) { result.setUndefined(); } else { setResult(last); } } } catch (Exception e) { // e.printStackTrace(); result.setUndefined(); } } private void setResult(GeoElement newResult) { // in case ? is used for different object type if (!newResult.isDefined()) { result.setUndefined(); return; } result.set(newResult); if (!newResult.isIndependent()) { result.setDefinition(newResult.getDefinition() == null ? null : newResult.getDefinition().deepCopy(kernel)); } if (newResult.getDrawAlgorithm() instanceof DrawInformationAlgo) { result.setDrawAlgorithm( ((DrawInformationAlgo) newResult.getDrawAlgorithm()) .copy()); } } /** * For Curve[If[t>0,t^2,-t^2],t,t,-5,5] * * @return expression expanision of this algo */ public ExpressionNode toExpression() { if (this.alternatives.size() == 1) { return new ExpressionNode(kernel, kernel.convertNumberValueToExpressionNode( this.conditions.get(0)), Operation.IF, kernel.convertNumberValueToExpressionNode( this.alternatives.get(0))); } else if (this.conditions.size() == 1) { return new ExpressionNode(kernel, new MyNumberPair(kernel, kernel.convertNumberValueToExpressionNode( this.conditions.get(0)), kernel.convertNumberValueToExpressionNode( this.alternatives.get(0))), Operation.IF_ELSE, kernel.convertNumberValueToExpressionNode( this.alternatives.get(1))); } MyList cond = new MyList(kernel), funs = new MyList(kernel); for (GeoBoolean f : conditions) { cond.addListElement(kernel.convertNumberValueToExpressionNode(f)); } for (GeoElement f : alternatives) { funs.addListElement(kernel.convertNumberValueToExpressionNode(f)); } return new ExpressionNode(kernel, cond, Operation.IF_LIST, funs); } @Override public boolean isUndefined() { for (int i = 0; i < conditions.size(); i++) { if (conditions.get(i).getBoolean()) { return !alternatives.get(i).isDefined(); } } return false; } }