use of expression.NodeException in project OpenNotebook by jaltekruse.
the class ExUtil method generateRandomExpressions.
public static String[] generateRandomExpressions() {
String[] ops = { ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION };
String[] vars = { "x", "y", "z", "a", "b", "c", "d", "s", "t", "w", "v", "m", "n", "j", "k", "l" };
int numTrials = 10;
String[] expressions = new String[numTrials];
int numZeros = 0;
int numNegatives = 0;
int minNumOps = 2;
int maxNumOps = 5;
int maxAbsVal = 20;
int minGeneratedVal = 1;
int maxGeneratedVal = 10;
int numOps;
for (int j = 0; j < numTrials; j++) {
numOps = randomInt(minNumOps, maxNumOps, false);
Node n = randomExpression(ops, vars, numOps, maxAbsVal, minGeneratedVal, maxGeneratedVal, true, false, false, true);
try {
expressions[j] = n.toStringRepresentation();
if (((Number) n.numericSimplify()).getValue() == 0) {
numZeros++;
}
if (((Number) n.numericSimplify()).getValue() < 0) {
numNegatives++;
}
} catch (NodeException e) {
e.printStackTrace();
}
}
// System.out.println(numNegatives + " out of " + numTrials + " trials evaluated to a negative.");
return expressions;
}
use of expression.NodeException in project OpenNotebook by jaltekruse.
the class ExUtil method addRandomOp.
public static Node addRandomOp(Node n, String[] ops, String[] vars, int min, int max, double maxAbsVal, boolean excludeZero, boolean subtractNegatives, boolean addNegatives) {
int opIndex = rand.nextInt(ops.length);
String opCode = ops[opIndex];
Node newChild = new Number(randomInt(min, max, excludeZero));
Operator op = null;
Number newNum;
Expression newEx;
double expressionVal = 0;
boolean numberTooBig = false;
try {
// System.out.println(n.toStringRepresentation());
expressionVal = ((Number) n.numericSimplify()).getValue();
} catch (NodeException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (Math.abs(expressionVal) > maxAbsVal) {
numberTooBig = true;
}
if (opCode.equals(DIVISION)) {
op = new Operator.Division();
newEx = new Expression(op);
if (!(newChild instanceof Number)) {
// to keep the answer clean
return addNodeOnRandomSide(n, newChild, op);
} else if (expressionVal == 0) {
newNum = (Number) newChild;
do {
newChild = new Number(randomInt(min, max, excludeZero));
} while (newNum.getValue() == 0);
return new Expression(op, n, newChild);
} else if (isPrime(expressionVal) || (rand.nextBoolean() && !numberTooBig)) {
// or the expression was randomly selected to be the divisor when it wasn't prime
return addRandomOp(n, ops, vars, min, max, maxAbsVal, excludeZero, subtractNegatives, addNegatives);
// had problem with these next two lines, gave up for now and just adding another operation
// newChild = new Number( expressionVal * randomInt(min, max, excludeZero));
// return new Expression(op, newChild, n);
} else {
// need to find a divisor
if (numberTooBig) {
return addRandomOp(n, ops, vars, min, max, maxAbsVal, excludeZero, subtractNegatives, addNegatives);
}
double[] factors = getFactors(expressionVal);
int factorIndex = rand.nextInt(factors.length);
newChild = new Number(factors[factorIndex]);
return new Expression(op, n, newChild);
}
} else if (opCode.equals(ADDITION)) {
op = new Operator.Addition();
if (!(newChild instanceof Number)) {
// to keep the answer clean
return addNodeOnRandomSide(n, newChild, op);
}
if (!addNegatives) {
if (max < 0) {
// the settings contradict one another, the user wanted only negative numbers generated
//do nothing
} else {
// the minimum is below zero, so exclude those values between 0 and the minimum while finding a new number
int tempMin = 0;
newNum = (Number) newChild;
if (min > 0)
tempMin = min;
while (newNum.getValue() < 0) {
newNum = new Number(randomInt(tempMin, max, excludeZero));
}
}
}
} else if (opCode.equals(SUBTRACTION)) {
op = new Operator.Subtraction();
if (!(newChild instanceof Number)) {
// to keep the answer clean
if (n instanceof Expression && ((Expression) n).getOperator() instanceof Operator.Negation) {
// MIGHT CAUSE INFINITE RECURSION, BE CAREFUL
return addRandomOp(n, ops, vars, min, max, maxAbsVal, excludeZero, subtractNegatives, addNegatives);
}
return addNodeOnRandomSide(n, newChild, op);
}
if (!subtractNegatives) {
// negative numbers are not supposed to be subtracted, generate new positive number
if (max < 0) {
// the settings contradict one another, the user wanted only negative numbers generated
//do nothing, ignore the value of subtractNegatives
} else {
// the minimum is below zero, so exclude those values between 0 and the minimum while finding a new number
int tempMin = 0;
newNum = (Number) newChild;
if (min > 0)
tempMin = min;
while (newNum.getValue() < 0) {
newNum = new Number(randomInt(tempMin, max, excludeZero));
}
}
}
} else if (opCode.equals(MULTIPLICATION)) {
op = new Operator.Multiplication();
newEx = new Expression(op);
if (!(newChild instanceof Number)) {
// to keep the answer clean
return addNodeOnRandomSide(n, newChild, op);
}
} else if (opCode.equals(NEGATION)) {
if (n instanceof Expression && ((Expression) n).getOperator() instanceof Operator.Negation || (n instanceof Number && ((Number) n).getValue() < 0)) {
// THIS WILL CAUSE INFINITE RECURSION IF THE ONLY OPERATOR IS NEGATION!!
return addRandomOp(n, ops, vars, min, max, maxAbsVal, excludeZero, subtractNegatives, addNegatives);
}
return new Expression(new Operator.Negation(), true, n);
} else {
throw new RuntimeException("unknown op");
}
return addNodeOnRandomSide(n, newChild, op);
}
use of expression.NodeException in project OpenNotebook by jaltekruse.
the class ExpressionGenerator method generateProblem.
public GeneratedProblem generateProblem(int difficulty) {
GeneratedProblem newProblem = new GeneratedProblem();
ExpressionObject expressionObj = new ExpressionObject();
try {
newProblem.setDifficulty(difficulty);
newProblem.getListWithName(GeneratedProblem.GEN_LIST).getValues().clear();
((ListAttribute<UUIDAttribute>) newProblem.getListWithName(GeneratedProblem.GEN_LIST)).addValueWithString(getProblemID().toString());
Node[] n = generateExpression(difficulty);
expressionObj.setExpression(n[0].toStringRepresentation());
expressionObj.addCorrectAnswer(n[1].toStringRepresentation());
} catch (AttributeException e) {
e.printStackTrace();
} catch (NodeException e) {
e.printStackTrace();
}
getProblemHoldingDocument().getDocViewerPanel().drawObjectInBackground(expressionObj);
expressionObj.setParentContainer(newProblem.getParentContainer());
newProblem.addObjectFromPage(expressionObj);
return newProblem;
}
use of expression.NodeException in project OpenNotebook by jaltekruse.
the class VariableValueInsertionProblem method generateProblem.
public GeneratedProblem generateProblem(int difficulty) {
Grouping newProblem = new Grouping(getParentContainer(), getxPos(), getyPos() + getHeight() + bufferSpace, getWidth(), getHeight());
String s;
Node n = null;
Vector<String> varNames = new Vector<>();
Vector<Number> varVals = new Vector<>();
for (StringAttribute strAtt : (Vector<StringAttribute>) getScripts().getValues()) {
s = strAtt.getValue();
if (s == null || s.equals("")) {
continue;
}
try {
n = Node.parseNode(s);
//sub in variables already assigned in previous scripts
for (int i = 0; i < varNames.size(); i++) {
n = n.replace(varNames.get(i), varVals.get(i));
}
n = n.numericSimplify();
if (n instanceof Expression) {
Expression ex = (Expression) n;
if (ex.getOperator() instanceof Operator.Equals) {
if (ex.getChild(0) instanceof Identifier) {
Identifier var = (Identifier) ex.getChild(0);
if (ex.getChild(1) instanceof Number) {
varNames.add(var.getIdentifier());
// this causes a lot of unneeded parenthesis
// but without it, you cannot sub in a value
// where there is an implied parenthesis
// ex.getChild(1).setDisplayParentheses(true);
varVals.add((Number) ex.getChild(1));
}
}
}
}
} catch (NodeException e) {
JOptionPane.showMessageDialog(null, "Error generating a problem, check scripts.", ERROR, JOptionPane.ERROR_MESSAGE);
}
}
MathObject newObj = null;
for (MathObject mObj : getObjects()) {
newObj = mObj.clone();
for (int i = 0; i < varNames.size(); i++) {
newObj = subInVal(varNames.get(i), varVals.get(i), newObj);
}
//shift object down so it doesn't overlap the current problem
newObj.setyPos(newObj.getyPos() + getHeight() + bufferSpace);
//this line sets the bounds to the actual space it takes to render them
if (getParentContainer() != null) {
// if this problem formula is in the background storage for a document
getParentDoc().getDocViewerPanel().drawObjectInBackground(newObj);
} else {
// if this problem formula is actually on a document
getProblemHoldingDocument().getDocViewerPanel().drawObjectInBackground(newObj);
}
newObj.setParentContainer(newProblem.getParentContainer());
newProblem.addObjectFromPage(newObj);
}
return new GeneratedProblem(newProblem.getParentContainer(), this.getProblemID(), newProblem);
}
use of expression.NodeException in project OpenNotebook by jaltekruse.
the class ExpressionObjectGUI method drawInteractiveComponents.
public void drawInteractiveComponents(ExpressionObject object, Graphics g, Point pageOrigin, float zoomLevel) {
g.setColor(Color.BLACK);
ScaledSizeAndPosition sap = getSizeAndPositionWithFontSize(object, pageOrigin, zoomLevel, object.getFontSize());
int outerBufferSpace = (int) (5 * zoomLevel);
int stepBufferSpace = (int) (10 * zoomLevel);
Graphics2D g2d = (Graphics2D) g;
RootNodeGraphic rootGraphic;
if (!(object.getExpression().equals("") && object.allAnswersBlank())) {
// if any of the steps cannot be rendered, this information will allow
// space to be left for printing an error message in its place
g.setFont(g.getFont().deriveFont(sap.getFontSize()));
int errorMessageHeight = g.getFontMetrics().getHeight();
int errorMessageWidth = g.getFontMetrics().stringWidth(EX_ERROR);
Node n = null;
int totalHeight = 0;
int greatestWidth = 0;
Vector<Integer> indeciesInError = new Vector<>();
Vector<Integer> yPosOfSteps = new Vector<>();
int currentIndex = 0;
Vector<RootNodeGraphic> expressions = new Vector<>();
// add the expression
try {
n = parser.parseNode(object.getExpression());
boolean objectChanged = currentSelectionStep || current == null || currentExObj != object || !object.getDecimalRectangleBounds().equals(currentPosSize) || !currentEx.equals(object.getExpression());
if (objectChanged) {
rootGraphic = new RootNodeGraphic(n);
rootGraphic.generateExpressionGraphic(g, outerBufferSpace + sap.getxOrigin(), outerBufferSpace + sap.getyOrigin(), (int) sap.getFontSize(), zoomLevel);
} else if (currentZoom != zoomLevel) {
rootGraphic = current;
rootGraphic.requestSize(g, outerBufferSpace + sap.getxOrigin(), outerBufferSpace + sap.getyOrigin(), (int) sap.getFontSize(), zoomLevel);
} else {
rootGraphic = current;
rootGraphic.setGraphics((Graphics2D) g);
}
// keep these next three lines in the try catch block, they should only happen
// if they line above does not throw an error
expressions.add(rootGraphic);
yPosOfSteps.add(rootGraphic.yPos);
totalHeight = rootGraphic.getHeight();
greatestWidth = rootGraphic.getWidth();
currentSelectionStep = false;
current = rootGraphic;
currentExObj = object;
currentEx = object.getExpression();
currentPosSize = object.getDecimalRectangleBounds();
currentZoom = zoomLevel;
} catch (Exception e) {
indeciesInError.add(currentIndex);
yPosOfSteps.add(outerBufferSpace + sap.getyOrigin());
expressions.add(null);
totalHeight += errorMessageHeight;
greatestWidth = errorMessageWidth;
}
Vector<StringAttribute> steps = (Vector<StringAttribute>) object.getListWithName(ExpressionObject.STEPS).getValues();
// TODO - confirm if this works with multiple correct answers
for (StringAttribute strAtt : object.getCorrectAnswers()) {
if (!strAtt.getValue().equals("")) {
steps.add(strAtt);
}
}
// add the steps to the list of expressions to render
String s;
int i = 0;
for (StringAttribute mAtt : steps) {
s = mAtt.getValue();
currentIndex++;
totalHeight += stepBufferSpace;
try {
n = parser.parseNode(s);
rootGraphic = new RootNodeGraphic(n);
// current = rootGraphic;
rootGraphic.generateExpressionGraphic(g, sap.getxOrigin() + outerBufferSpace, outerBufferSpace + sap.getyOrigin() + totalHeight, (int) sap.getFontSize(), zoomLevel);
expressions.add(rootGraphic);
yPosOfSteps.add(rootGraphic.yPos);
if (rootGraphic.getWidth() > greatestWidth) {
greatestWidth = rootGraphic.getWidth();
}
totalHeight += rootGraphic.getHeight();
i++;
} catch (Exception e) {
indeciesInError.add(currentIndex);
totalHeight += errorMessageHeight;
if (errorMessageWidth > greatestWidth) {
greatestWidth = errorMessageWidth;
}
yPosOfSteps.add(outerBufferSpace + sap.getyOrigin() + totalHeight);
}
}
// remove the correct answers, so they are not permanently added as steps
steps.removeAll(object.getCorrectAnswers());
if (object.getColor() != null) {
g.setColor(object.getColor());
} else {
g.setColor(Color.white);
}
g.fillRect(sap.getxOrigin(), sap.getyOrigin(), greatestWidth + 2 * outerBufferSpace, totalHeight + 2 * outerBufferSpace);
g.setColor(Color.BLACK);
int index = 0;
int numberOfSteps = steps.size() + 1;
for (RootNodeGraphic r : expressions) {
try {
if (indeciesInError.contains(index)) {
g.setFont(g.getFont().deriveFont(sap.getFontSize()));
g.setColor(Color.RED);
g.drawString(EX_ERROR, sap.getxOrigin() + outerBufferSpace, yPosOfSteps.get(index) + errorMessageHeight);
g.setColor(Color.BLACK);
index++;
continue;
} else {
if (index >= numberOfSteps) {
// draw the answers with a highlight
g.setColor(new Color(180, 255, 100));
g.fillRect(r.xPos - 4, r.yPos - 4, r.getWidth() + 8, r.getHeight() + 8);
g.setColor(Color.BLACK);
}
if (index != 0)
r.setCursor(new Cursor(null, 0));
r.draw();
}
} catch (NodeException e) {
e.printStackTrace();
g.setFont(g.getFont().deriveFont(sap.getFontSize()));
g.setColor(Color.RED);
g.drawString(EX_ERROR, r.xPos, r.yPos + errorMessageHeight);
}
index++;
}
if (greatestWidth > 0 && totalHeight > 0) {
object.setWidth((int) ((greatestWidth + 2 * outerBufferSpace) / zoomLevel));
object.setHeight((int) ((totalHeight + 2 * outerBufferSpace) / zoomLevel));
}
} else {
g2d.setStroke(new BasicStroke());
g2d.setPaint(Color.BLACK);
g.drawRect(sap.getxOrigin(), sap.getyOrigin(), sap.getWidth(), sap.getHeight());
}
}
Aggregations