cox.jmatt.java.MathTools
Class MEquation

java.lang.Object
  extended by cox.jmatt.java.MathTools.MEquation

public class MEquation
extends java.lang.Object

MEquation's purpose is to provide a fast and easy way to generate simple equations commonly found on algebra tests. This is by NO means an exhaustive list of all the different equations or configurations of equations in the current world. Rather, it presents some of the equation types found on equation-solving tests. The heart and soul of this class is the Equation enum. Each TYPE_ constant serves to classify the type of equation it represents, identify placeholders (NOT variables) that need to be filled, and provide standard formats for presenting that equation. This class is not written to be the end-all solver of every type of equation or inequality imaginable. Rather, it provides a very fast way to generate simple equations found on basic algebra tests.

A note on TYPE_ constants and their content. There is no particular rationale behind why this type of equation received that designation. The TYPE_ constants simply appear in the order in which they were conceived.

The main production method of this class, and its power method, is createQuestion(). This takes an Equation, a Knobs string, a variable, a relation, and a format key. It grabs the Equation, sets the knobs, preformats, gets the appropriate format, sets the relation, puts the variable and preformat numbers into a String[] array and calls Question.fillTemplate(). The resulting Problem is put into the problem part and a simple Answer of the form 'x = N' is put into the Answer part. The variable and relation are adjusted for those input and the thing is formatted in proper MathML if that is the key chosen. The instance version of createQuestion() is newQuestion() and it takes the same parameters.

The other utility methods are getByType(), its instance version getEquationByType() and checkEquation(). The first two are safety methods for getting a TYPE_ Equation without worrying about Exceptions. If one is thrown it is caught and reported at Debug level and TYPE_ERROR is returned. The checkEquation() method is primarily for debugging the equations and experimenting with them. It prints the solution in place of the variable for the selected Equation, giving a quick way to check.

Equations and Inequalities

Even though the name of the class is MEquation it can be used to generate inequalities. The createQuestion() method doesn't care what relation is sent in, it just formats. It is possible to reverse the equation: x + A = B becomes B = x + A. This is a very naive reversal which can be problematic to inequalities.

To solve this potential problem MEquation and the Equation enum implement BIRD. This is Blind Inequality Reverse Detection and it works as follows. Each Equation in the enum defines the bird() method. This is valid ONLY after a call to preformat() and it indicates whether or not an inequality should be reversed based on the last numbers sent in. createQuestion() handles this automatically but it must be addressed when building inequalities manually.

Concerning reversal, createQuestion() applies NO intelligence to the relation sent in. That is, the method does NOT in any way alter the relation itself. It does not change the sense of the inequality, only the format. Regardless of the relation, if BIRD says to reverse then the Answer will be reversed. So, for the Problem '-2x < 10' the Answer is formatted '-5 < x'. BIRD still works when 'reverse' is requested. If reverse is requested, the previous Problem would appear '10 < -2x' and the Answer would be 'x < -5'.

Preformatting and formatting

Each equation comes equipped with four built-in presentation formats: Standard, OpenOffice, MathML and LaTeX. While this is convenient for those who use these technologies, it presents a problem for those who do not. For that reason each TYPE_ of equation has two preformat() methods. One accepts a String of Knobs and the other an int[] array.

The preformat() methods generate a String consisting of the data required for each type of equation: the values calculated for the placeholders (capital letters) that define the equation and its solution. The preformat format is 'Answer : A B C... : BIRD'. This, along with the 'typewriter-style' representation of each equation is all that's needed to create the equation itself. MEquation's actual formatting methods do exactly this: split the answer away from the constants and coefficients (placeholders) then create a Question.fillTemplate() token array. The variable is, of course, in <0> and the letters go up in order from there. I.e. A = <1>, B = <2>, and so on up to the number of placeholders required. The last element in the array (after the second colon in the preformat String) indicates whether or not an inequality needs reversing.

In addition to the preformat() methods two tokens() methods are also available. One takes an int[] array and the other a String of Knobs but both return the preformat data as a String[] array. The first element in the array (tokens()[0]) is the answer and the placeholders start at element 1 and move upward in order; that is, tokens[1] = 'A', tokens[2] = 'B' etc. The last element in the array is the BIRD value 'true' or 'false'. These methods were added to facilitate easier custom formatting via Question.fillTemplate().

If desired, negative placeholders can be enclosed in parentheses. The setNegativeParentheses() method does this. It accepts two Strings that correspond to the left and right parenthesis. These values work independently and if eithr is set to a non-null, non-blank value it will be applied to its side of a negative placeholder. IMPORTANT NOTE: If set, these indicators do apply to isolated placeholders; e.g. the single constant on one side of an equation. Setting either value to null or blank clears it and any values set remain until changed.

Calculations, Placeholders, and Knobs

All of the equations listed have placeholders and require Knobs. Even though the equations typically require as many Knobs as they have placeholders, the two are not directly connected! That is to say calculations are performed on the Knobs in order to calculate values for the placeholders, the constants or coefficients. The way the solution and placeholders are calculated is listed in the Equation docs.

EXAMPLE: Equation.TYPE_400, 'Ax + B = C', requires 3 Knobs. Knob 0 is the answer ('x'), Knob 1 is the value of 'A' and Knob 2 is the value of 'B'. The 'C' placeholder is calculated as 'A*x + B'. The best way to get a feel for this is to examine the enum docs and experiment with the checkEquation() method.

Making Nasty Equations

MEquation and its preformat() methods were written to generate nice equations. Using these methods guarantees that no matter what values are passed in, the answer will be an integer and not a fractional value.

The Equation.solveFor() and the MEquation.solveEquation() methods allow the generation of NON-nice equations. The heart of these methods is an int[] array consisting of the placeholders in order: [0] = 'A', [1] = 'B' etc. These values are substituted for the placeholders and the equation solved. There is NO GUARANTEE that the result will be nice, though! The Equation.solveFor() method presents the answer as a String consisting of one or two answers - one if no fractions are involved, a typewriter-style fraction followed by the double value otherwise - followed by the literal String '(REV)' if an inequality needs reversing.

The MEquation.solveEquation() methods (and their instance shadows) provide an easy way to access the raw 'solve-string' or to generate a Question. In the latter case the variable, relation and format must be specified, BIRD is applied if necessary and a Question is returned.

The MEquation Container

Though primarily designed only to support the Equation enum, instances of MEquation can act as containers for Equation data. The createMEquation() method does this, and it or its instance version are the only ways such a container should be created. The primary rationale for this is to allow XML or some other form of Object persistence. Once created, a MEquation is immutable.

NOTE: MEquation instances can only be created for nice equations, not nasty ones.


Nested Class Summary
static class MEquation.Equation
          This enum specifies the standard types of equations contained within the MEquations class.
 
Field Summary
static int LATEX
          Copy of Equation.LATEX
static int MATHML
          Copy of Equation.MATHML.
static int OPEN_OFFICE
          Copy of Equation.OPEN_OFFICE.
static int STANDARD
          Copy of Equation.STANDARD.
 
Constructor Summary
MEquation()
          Constructor for script access.
 
Method Summary
static java.lang.String checkEquation(MEquation.Equation pType, int[] pVals)
          Check the values for a particular type of equation.
static MEquation createMEquation(java.lang.String pDataString)
          (Re-)Create a MEquation from a dataString().
static MEquation createMEquation(java.lang.String pType, java.lang.String pKnobs, java.lang.String pVar, java.lang.String pRel, java.lang.String pReverse)
          This method creates a MEquation to hold the data supplied.
static Question createQuestion(int pEqn, java.lang.String pKnobs, java.lang.String pVar, java.lang.String pRel, int pFormat, boolean pReverse)
          This is createQuestion() with an int for the Equation type, otherwise it is identical.
static Question createQuestion(MEquation.Equation pEqn, java.lang.String pKnobs, java.lang.String pVar, java.lang.String pRel, int pFormat, boolean pReverse)
          Generate a Question from one of the Equation types, a Knobs string, a relation and a format.
 java.lang.String dataString()
          Return the internal data for this MEquation in a simple, colon-separated format.
 java.lang.String get_Format(int pType, int pFormat, java.lang.String pRel)
          Instance getFormat().
static MEquation.Equation getByType(int pTypeNumber)
          This method provides an Exception-proof way to fetch a particular TYPE_ of Equation.
static MEquation.Equation getByType(java.lang.String pType)
          This method provides an Exception-proof way to fetch a particular TYPE_ of Equation from a String.
 MEquation.Equation getEquationByType(int pTypeNum)
          Instance method for getByType().
 MEquation.Equation getEquationByType(java.lang.String pType)
          Instance version of getByType(String).
static java.lang.String getFormat(int pType, int pFormat, java.lang.String pRel)
          Return the specified format for the given equation with the relation supplied.
 MEquation newMEquation(java.lang.String pDataString)
          Instance flavor of createMEquation(DataString).
 MEquation newMEquation(java.lang.String pType, java.lang.String pKnobs, java.lang.String pVar, java.lang.String pRel, java.lang.String pReverse)
          Instance version of createMEquation().
 Question newQuestion(int pEqn, java.lang.String pKnobs, java.lang.String pVar, java.lang.String pRel, int pFormat, boolean pReverse)
          Instance shadow of int-typed createQuestion().
 Question newQuestion(MEquation.Equation pEqn, java.lang.String pKnobs, java.lang.String pVar, java.lang.String pRel, int pFormat, boolean pReverse)
          Instance version of createQuestion().
static void setEscapeFormat(boolean pEnable)
          Use this method to XML-escape the relations sent into a MathML format.
static void setNegativeParentheses(java.lang.String pLeft, java.lang.String pRight)
          Set or clear the parenthesis symbols used to enclose negative placeholder values.
 void setNewEscapeFormat(boolean pEnable)
          Instance version.
 void setNewNegativeParentheses(java.lang.String pLeft, java.lang.String pRight)
          Instance shadow to set parentheses.
 java.lang.String solve_Equation(int pType, int... phVals)
          Instance String solveEquation() shadow.
 Question solve_Equation(int pType, int pFormat, java.lang.String pVar, java.lang.String pRel, int... phVals)
          Question-valued instance version of solveEquation().
static java.lang.String solveEquation(int pType, int... phVals)
          Use this method when custom-formatting an Equation enum equation that doesn't necessarily solve nicely.
static Question solveEquation(int pType, int pFormat, java.lang.String pVar, java.lang.String pRel, int... phVals)
          This is the full-featured nasty-equation formatting method.
 Question toQuestion()
          Output the current MEquation as a Question using STANDARD format.
 Question toQuestion(int pFormat)
          Output the current MEquation as a Question using the format supplied.
 java.lang.String toString()
          Return dataString() with some added text.
 java.lang.String toXML(java.lang.String pID)
          Convert this MEquation to XML.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

STANDARD

public static final int STANDARD
Copy of Equation.STANDARD.

See Also:
Constant Field Values

OPEN_OFFICE

public static final int OPEN_OFFICE
Copy of Equation.OPEN_OFFICE.

See Also:
Constant Field Values

MATHML

public static final int MATHML
Copy of Equation.MATHML.

See Also:
Constant Field Values

LATEX

public static final int LATEX
Copy of Equation.LATEX

See Also:
Constant Field Values
Constructor Detail

MEquation

public MEquation()
Constructor for script access.

Method Detail

setNegativeParentheses

public static void setNegativeParentheses(java.lang.String pLeft,
                                          java.lang.String pRight)
Set or clear the parenthesis symbols used to enclose negative placeholder values. Each symbol is independent of the other so one or both may be set or cleared. If set, the left value is prepended to a negative placeholder and the right value is appended. Setting null or blank clears them. These values remain until re-set.

Parameters:
pLeft - The left parenthesis symbol to enclose negative numbers.
pRight - The right parenthesis symbol.

setNewNegativeParentheses

public void setNewNegativeParentheses(java.lang.String pLeft,
                                      java.lang.String pRight)
Instance shadow to set parentheses.


setEscapeFormat

public static void setEscapeFormat(boolean pEnable)
Use this method to XML-escape the relations sent into a MathML format. Once set this value remains until un-set. The default is false.


setNewEscapeFormat

public void setNewEscapeFormat(boolean pEnable)
Instance version.


checkEquation

public static java.lang.String checkEquation(MEquation.Equation pType,
                                             int[] pVals)
Check the values for a particular type of equation. The answer, enclosed within parentheses, is substituted in place of the variable in STANDARD format. This allows a particular equation to be investigated and its difficulty adjusted. ANY Exceptions are caught and reported at Error level.

Parameters:
pType - The equation TYPE_ to check.
pVals - An int[] array containing values for the Knobs the equationr requires.
Returns:
A STANDARD-format statement to check the equation.

createQuestion

public static Question createQuestion(MEquation.Equation pEqn,
                                      java.lang.String pKnobs,
                                      java.lang.String pVar,
                                      java.lang.String pRel,
                                      int pFormat,
                                      boolean pReverse)

Generate a Question from one of the Equation types, a Knobs string, a relation and a format. This is the only actual production method MEquation has. The newQuestion() method reflects to this one and the checkEquation() method is primarily meant for experimentation and debugging. The 'get Equation' methods simply provide an error-proof way to obtain TYPE_ constants.

If desired, the equation (inequality) can be reversed. This simply swaps sides around the relation, so the equation 'x + A = B' becomes 'B = x + A.' CAUTION: reversing the sides of an inequality does NOT reverse the inequality! Send the proper one in. The Answer is reversed based on the 'pReverse' argument and BIRD.

Parameters:
pEqn - The TYPE_ of equation to generate.
pKnobs - The Knobs string for the equation.
pVar - The variable to use in place of 'x'. If null or empty, one will be selected.
pRel - The relation to use. Defaults to equality.
pFormat - One of the format constant keys to use. Defaults to STANDARD.
pReverse - true to reverse the sides of the equation, false to leave them as written.

newQuestion

public Question newQuestion(MEquation.Equation pEqn,
                            java.lang.String pKnobs,
                            java.lang.String pVar,
                            java.lang.String pRel,
                            int pFormat,
                            boolean pReverse)
Instance version of createQuestion().


createQuestion

public static Question createQuestion(int pEqn,
                                      java.lang.String pKnobs,
                                      java.lang.String pVar,
                                      java.lang.String pRel,
                                      int pFormat,
                                      boolean pReverse)
This is createQuestion() with an int for the Equation type, otherwise it is identical.


newQuestion

public Question newQuestion(int pEqn,
                            java.lang.String pKnobs,
                            java.lang.String pVar,
                            java.lang.String pRel,
                            int pFormat,
                            boolean pReverse)
Instance shadow of int-typed createQuestion().


solveEquation

public static java.lang.String solveEquation(int pType,
                                             int... phVals)
Use this method when custom-formatting an Equation enum equation that doesn't necessarily solve nicely. The 'phVals' values are the placeholders in the order they appear in the description: A, B, C.... The return value is the solveFor() String for the equation selected.

Parameters:
pType - The Equation type to solve.
phVals - The placeholder values.

solve_Equation

public java.lang.String solve_Equation(int pType,
                                       int... phVals)
Instance String solveEquation() shadow.


solveEquation

public static Question solveEquation(int pType,
                                     int pFormat,
                                     java.lang.String pVar,
                                     java.lang.String pRel,
                                     int... phVals)

This is the full-featured nasty-equation formatting method. It accepts a type, a format constant, a variable, a relation and a placeholder array. It returns a Question consisting of the formatted equation for the Problem part and the answer for the Answer part. BIRD is applied to the Answer.

Default values are supplied for the variable ('x') and the relation ('=').

Parameters:
pType - The TYPE_ number of the equation to format.
pFormat - The constant for the desired format. Use -1 for STANDARD.
pVar - The variable to use in the equation.
pRel - The relation to use in the equation.
phVals - The placeholder values to plug in.

solve_Equation

public Question solve_Equation(int pType,
                               int pFormat,
                               java.lang.String pVar,
                               java.lang.String pRel,
                               int... phVals)
Question-valued instance version of solveEquation().


createMEquation

public static MEquation createMEquation(java.lang.String pType,
                                        java.lang.String pKnobs,
                                        java.lang.String pVar,
                                        java.lang.String pRel,
                                        java.lang.String pReverse)
This method creates a MEquation to hold the data supplied. The Knobs are evaluated and stored 'frozen' to ensure immutability. Though this is a static method, it returns a MEquation instance. The output format is NOT stored; it is specified upon formatting!

Parameters:
pType - A String corresponding to the type of equation desired.
pKnobs - The Knobs to use for the equation.
pVar - The variable to use for the equation. The default is 'x.'
pRel - The relation to use. Defaults to '=.'
pReverse - Whether or not to reverse the equation.

newMEquation

public MEquation newMEquation(java.lang.String pType,
                              java.lang.String pKnobs,
                              java.lang.String pVar,
                              java.lang.String pRel,
                              java.lang.String pReverse)
Instance version of createMEquation().


createMEquation

public static MEquation createMEquation(java.lang.String pDataString)
(Re-)Create a MEquation from a dataString(). If the string is not properly formatted a default MEquation is returned.


newMEquation

public MEquation newMEquation(java.lang.String pDataString)
Instance flavor of createMEquation(DataString).


getByType

public static MEquation.Equation getByType(int pTypeNumber)
This method provides an Exception-proof way to fetch a particular TYPE_ of Equation. If anything terrible happens, TYPE_ERROR is returned. If this is the case, it is reported at DEBUG level.

Parameters:
pTypeNumber - An int corresponding to the numeric type of Equation desired; so '550' would create a TYPE_550 Equation.

getEquationByType

public MEquation.Equation getEquationByType(int pTypeNum)
Instance method for getByType().


getByType

public static MEquation.Equation getByType(java.lang.String pType)
This method provides an Exception-proof way to fetch a particular TYPE_ of Equation from a String. If the String supplied cannot be resolved to a TYPE_ of Equation, TYPE_ERROR is returned and the incident is reported at Debug level.

Parameters:
pType - The String label of an Equation type; 'TYPE_100' would return a TYPE_100 Equation.

getEquationByType

public MEquation.Equation getEquationByType(java.lang.String pType)
Instance version of getByType(String).


getFormat

public static java.lang.String getFormat(int pType,
                                         int pFormat,
                                         java.lang.String pRel)
Return the specified format for the given equation with the relation supplied.

Parameters:
pType - The TYPE_ number of the desired equation.
pFormat - The format desired. Defaults to STANDARD.
pRel - The relation to set. Defaults to '='.

get_Format

public java.lang.String get_Format(int pType,
                                   int pFormat,
                                   java.lang.String pRel)
Instance getFormat().


dataString

public java.lang.String dataString()
Return the internal data for this MEquation in a simple, colon-separated format. The order of the elements is per the createMEquation() method.


toString

public java.lang.String toString()
Return dataString() with some added text.

Overrides:
toString in class java.lang.Object

toXML

public java.lang.String toXML(java.lang.String pID)
Convert this MEquation to XML. The data String is basically a colon-separated collection of the values required for the createMEquation() method. This format should not be hand-edited as it can break the parsing process! The Knobs represented are in MathEngine.isoKnob() format to preserve the immutability of the data between marshalling (to XML) and unmarshalling. The relation String is escaped and restored in a very simple fashion: '<' is replaced with 'L' and '>' is replaced with 'G'. The (output) format is not a part of the tag since it is a part of the formatting process ONLY.

Parameters:
pID - An optional ID attribute to be added to the tag. Ignored if null or empty.

toQuestion

public Question toQuestion(int pFormat)
Output the current MEquation as a Question using the format supplied.


toQuestion

public Question toQuestion()
Output the current MEquation as a Question using STANDARD format.