From d181ecaf25f6033292774d7b476a0cd54ccb52fb Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Sun, 24 Dec 2017 11:59:09 +0100 Subject: [PATCH] Updated rules --- .../picalculator/math/rules/RulesManager.java | 25 +++--- src/main/resources/rules.csv | 16 +++- .../resources/rules/functions/EmptyNumber.js | 35 +++++++++ src/main/resources/rules/functions/Joke.js | 35 +++++++++ .../rules/functions/Multiplication.js | 52 +++++++++++++ .../resources/rules/functions/Negative.js | 62 +++++++++++++++ src/main/resources/rules/functions/Number.js | 49 ++++++++++++ src/main/resources/rules/functions/Power.js | 53 +++++++++++++ src/main/resources/rules/functions/Root.js | 78 +++++++++++++++++++ 9 files changed, 390 insertions(+), 15 deletions(-) create mode 100644 src/main/resources/rules/functions/EmptyNumber.js create mode 100644 src/main/resources/rules/functions/Joke.js create mode 100644 src/main/resources/rules/functions/Multiplication.js create mode 100644 src/main/resources/rules/functions/Negative.js create mode 100644 src/main/resources/rules/functions/Number.js create mode 100644 src/main/resources/rules/functions/Power.js create mode 100644 src/main/resources/rules/functions/Root.js diff --git a/src/main/java/org/warp/picalculator/math/rules/RulesManager.java b/src/main/java/org/warp/picalculator/math/rules/RulesManager.java index 90ae94b8..5ab7dc67 100644 --- a/src/main/java/org/warp/picalculator/math/rules/RulesManager.java +++ b/src/main/java/org/warp/picalculator/math/rules/RulesManager.java @@ -59,15 +59,18 @@ public class RulesManager { } ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); List ruleLines = Files.readAllLines(rulesPath); + ruleLines.remove(0); //Remove the headers for (String rulesLine : ruleLines) { - String[] ruleDetails = rulesLine.split(",", 1); - String ruleName = ruleDetails[0]; - Utils.out.println("Evaluating /rules/" + ruleName + ".js"); - InputStream resourcePath = Utils.getResourceStream("/rules/" + ruleName.replace(".", "_") + ".js"); - if (resourcePath == null) { - System.err.println(new FileNotFoundException("/rules/" + ruleName + ".js not found!")); - } else { - engine.eval(new InputStreamReader(resourcePath)); + if (rulesLine.length() > 0) { + String[] ruleDetails = rulesLine.split(",", 1); + String ruleName = ruleDetails[0]; + Utils.out.println("Evaluating /rules/" + ruleName + ".js"); + InputStream resourcePath = Utils.getResourceStream("/rules/" + ruleName.replace(".", "_") + ".js"); + if (resourcePath == null) { + System.err.println(new FileNotFoundException("/rules/" + ruleName + ".js not found!")); + } else { + engine.eval(new InputStreamReader(resourcePath)); + } } } } catch (URISyntaxException | IOException e) { @@ -96,10 +99,10 @@ public class RulesManager { } } - private static Expression generateUselessExpression() { + private static Function generateUselessExpression() { MathContext mc = new MathContext(); - Expression expr = new Expression(mc); - expr = (Expression) expr.setParameter(new Variable(mc, 'x', V_TYPE.VARIABLE)); + Function expr = new Expression(mc); + expr = expr.setParameter(0, new Variable(mc, 'x', V_TYPE.VARIABLE)); return expr; } diff --git a/src/main/resources/rules.csv b/src/main/resources/rules.csv index dd5be13a..9145d4ca 100644 --- a/src/main/resources/rules.csv +++ b/src/main/resources/rules.csv @@ -1,5 +1,13 @@ -functions/Expression -functions/Division -ExpandRule1 -ExpandRule2 +Rule file +functions/Division +functions/EmptyNumber +functions/Expression +functions/Joke +functions/Multiplication +functions/Negative +functions/Number +functions/Power +functions/Root +ExpandRule1 +ExpandRule2 ExpandRule5 \ No newline at end of file diff --git a/src/main/resources/rules/functions/EmptyNumber.js b/src/main/resources/rules/functions/EmptyNumber.js new file mode 100644 index 00000000..3c1eaf1e --- /dev/null +++ b/src/main/resources/rules/functions/EmptyNumber.js @@ -0,0 +1,35 @@ +// Imports +var ObjectArrayList = Java.type("it.unimi.dsi.fastutil.objects.ObjectArrayList"); +var ScriptUtils = org.warp.picalculator.ScriptUtils; +var Rule = org.warp.picalculator.math.rules.Rule; +var RuleType = org.warp.picalculator.math.rules.RuleType; +var RulesManager = org.warp.picalculator.math.rules.RulesManager; + +/** + * EmptyNumber + * + * + * @author Andrea Cavalli + * + */ +var rule = { + // Rule name + getRuleName: function() { + return "EmptyNumber"; + }, + // Rule type + getRuleType: function() { + return RuleType.CALCULATION; + }, + /* Rule function + Returns: + - null if it's not executable on the function "f" + - An ObjectArrayList if it did something + */ + execute: function(f) { + return null; + } +} + +//Add this rule to the list of rules +RulesManager.addRule(engine.getInterface(rule, Rule.class)); \ No newline at end of file diff --git a/src/main/resources/rules/functions/Joke.js b/src/main/resources/rules/functions/Joke.js new file mode 100644 index 00000000..8f12f600 --- /dev/null +++ b/src/main/resources/rules/functions/Joke.js @@ -0,0 +1,35 @@ +// Imports +var ObjectArrayList = Java.type("it.unimi.dsi.fastutil.objects.ObjectArrayList"); +var ScriptUtils = org.warp.picalculator.ScriptUtils; +var Rule = org.warp.picalculator.math.rules.Rule; +var RuleType = org.warp.picalculator.math.rules.RuleType; +var RulesManager = org.warp.picalculator.math.rules.RulesManager; + +/** + * Joke + * + * + * @author Andrea Cavalli + * + */ +var rule = { + // Rule name + getRuleName: function() { + return "Joke"; + }, + // Rule type + getRuleType: function() { + return RuleType.CALCULATION; + }, + /* Rule function + Returns: + - null if it's not executable on the function "f" + - An ObjectArrayList if it did something + */ + execute: function(f) { + return null; + } +} + +//Add this rule to the list of rules +RulesManager.addRule(engine.getInterface(rule, Rule.class)); \ No newline at end of file diff --git a/src/main/resources/rules/functions/Multiplication.js b/src/main/resources/rules/functions/Multiplication.js new file mode 100644 index 00000000..58be484b --- /dev/null +++ b/src/main/resources/rules/functions/Multiplication.js @@ -0,0 +1,52 @@ +// Imports +var ObjectArrayList = Java.type("it.unimi.dsi.fastutil.objects.ObjectArrayList"); +var ScriptUtils = org.warp.picalculator.ScriptUtils; +var Rule = org.warp.picalculator.math.rules.Rule; +var RuleType = org.warp.picalculator.math.rules.RuleType; +var RulesManager = org.warp.picalculator.math.rules.RulesManager; +var Multiplication = org.warp.picalculator.math.functions.Multiplication; +var Sum = org.warp.picalculator.math.functions.Sum; +var Subtraction = org.warp.picalculator.math.functions.Subtraction; +var SumSubtraction = org.warp.picalculator.math.functions.SumSubtraction; +var Number = org.warp.picalculator.math.functions.Number; +var Division = org.warp.picalculator.math.functions.Division; + +/** + * Multiplication + * a*b = c + * + * @author Andrea Cavalli + * + */ +var rule = { + // Rule name + getRuleName: function() { + return "Multiplication"; + }, + // Rule type + getRuleType: function() { + return RuleType.CALCULATION; + }, + /* Rule function + Returns: + - null if it's not executable on the function "f" + - An ObjectArrayList if it did something + */ + execute: function(f) { + if (ScriptUtils.instanceOf(f, Multiplication.class)) { + var result = new ObjectArrayList(); + var variable1 = f.getParameter1(); + var variable2 = f.getParameter2(); + var mathContext = f.getMathContext(); + if (ScriptUtils.instanceOf(variable1, Number.class) && ScriptUtils.instanceOf(variable2, Number.class)) { + //multiply a by b (a*b = c) + result.add(variable1.multiply(variable2)); + return result; + } + } + return null; + } +} + +//Add this rule to the list of rules +RulesManager.addRule(engine.getInterface(rule, Rule.class)); \ No newline at end of file diff --git a/src/main/resources/rules/functions/Negative.js b/src/main/resources/rules/functions/Negative.js new file mode 100644 index 00000000..f2523cd0 --- /dev/null +++ b/src/main/resources/rules/functions/Negative.js @@ -0,0 +1,62 @@ +// Imports +var ObjectArrayList = Java.type("it.unimi.dsi.fastutil.objects.ObjectArrayList"); +var ScriptUtils = org.warp.picalculator.ScriptUtils; +var Rule = org.warp.picalculator.math.rules.Rule; +var RuleType = org.warp.picalculator.math.rules.RuleType; +var RulesManager = org.warp.picalculator.math.rules.RulesManager; +var Number = org.warp.picalculator.math.functions.Number; +var Negative = org.warp.picalculator.math.functions.Negative; +var Error = org.warp.picalculator.Error; +var Errors = org.warp.picalculator.Errors; +var NullPointerException = java.lang.NullPointerException; +var NumberFormatException = java.lang.NumberFormatException; +var ArithmeticException = java.lang.ArithmeticException; + +/** + * Negative + * -a = b + * + * @author Andrea Cavalli + * + */ +var rule = { + // Rule name + getRuleName: function() { + return "Negative"; + }, + // Rule type + getRuleType: function() { + return RuleType.CALCULATION; + }, + /* Rule function + Returns: + - null if it's not executable on the function "f" + - An ObjectArrayList if it did something + */ + execute: function(f) { + if (ScriptUtils.instanceOf(f, Negative.class)) { + var result = new ObjectArrayList(); + var variable = f.getParameter(); + var mathContext = f.getMathContext(); + if (ScriptUtils.instanceOf(variable, Number.class)) { + //-a = a*-1 = b + try { + result.add(variable.multiply(new Number(mathContext, -1))); + } catch (ex) { + if (ScriptUtils.instanceOf(ex, NullPointerException.class)) { + throw new Error(Errors.ERROR); + } else if (ScriptUtils.instanceOf(ex, NumberFormatException.class)) { + throw new Error(Errors.SYNTAX_ERROR); + } else if (ScriptUtils.instanceOf(ex, ArithmeticException.class)) { + throw new Error(Errors.NUMBER_TOO_SMALL); + } + } + return result; + } + } + return null; + } +} + +//Add this rule to the list of rules +RulesManager.addRule(engine.getInterface(rule, Rule.class)); \ No newline at end of file diff --git a/src/main/resources/rules/functions/Number.js b/src/main/resources/rules/functions/Number.js new file mode 100644 index 00000000..b2c2bdfe --- /dev/null +++ b/src/main/resources/rules/functions/Number.js @@ -0,0 +1,49 @@ +// Imports +var ObjectArrayList = Java.type("it.unimi.dsi.fastutil.objects.ObjectArrayList"); +var ScriptUtils = org.warp.picalculator.ScriptUtils; +var Rule = org.warp.picalculator.math.rules.Rule; +var RuleType = org.warp.picalculator.math.rules.RuleType; +var RulesManager = org.warp.picalculator.math.rules.RulesManager; +var BigInteger = java.math.BigInteger; + +/** + * Number + * + * + * @author Andrea Cavalli + * + */ +var rule = { + // Rule name + getRuleName: function() { + return "Number"; + }, + // Rule type + getRuleType: function() { + return RuleType.CALCULATION; + }, + /* Rule function + Returns: + - null if it's not executable on the function "f" + - An ObjectArrayList if it did something + */ + execute: function(f) { + if (ScriptUtils.instanceOf(f, Number.class)) { + var result = new ObjectArrayList(); + var mathContext = f.getMathContext(); + if (mathContext.exactMode) { + if (f.isInteger() == false) { + var divisor = new Number(mathContext, BigInteger.TEN.pow(f.getNumberOfDecimalPlaces())); + var number = new Number(mathContext, f.getTerm().multiply(divisor.term)); + var div = new Division(mathContext, number, divisor); + result.add(div); + return result; + } + } + } + return null; + } +} + +//Add this rule to the list of rules +RulesManager.addRule(engine.getInterface(rule, Rule.class)); \ No newline at end of file diff --git a/src/main/resources/rules/functions/Power.js b/src/main/resources/rules/functions/Power.js new file mode 100644 index 00000000..c7feccef --- /dev/null +++ b/src/main/resources/rules/functions/Power.js @@ -0,0 +1,53 @@ +// Imports +var ObjectArrayList = Java.type("it.unimi.dsi.fastutil.objects.ObjectArrayList"); +var ScriptUtils = org.warp.picalculator.ScriptUtils; +var Rule = org.warp.picalculator.math.rules.Rule; +var RuleType = org.warp.picalculator.math.rules.RuleType; +var RulesManager = org.warp.picalculator.math.rules.RulesManager; +var Multiplication = org.warp.picalculator.math.functions.Multiplication; +var Sum = org.warp.picalculator.math.functions.Sum; +var Subtraction = org.warp.picalculator.math.functions.Subtraction; +var SumSubtraction = org.warp.picalculator.math.functions.SumSubtraction; +var Number = org.warp.picalculator.math.functions.Number; +var Division = org.warp.picalculator.math.functions.Division; +var Power = org.warp.picalculator.math.functions.Power; + +/** + * Power + * a^b = c + * + * @author Andrea Cavalli + * + */ +var rule = { + // Rule name + getRuleName: function() { + return "Power"; + }, + // Rule type + getRuleType: function() { + return RuleType.CALCULATION; + }, + /* Rule function + Returns: + - null if it's not executable on the function "f" + - An ObjectArrayList if it did something + */ + execute: function(f) { + if (ScriptUtils.instanceOf(f, Power.class)) { + var result = new ObjectArrayList(); + var variable1 = f.getParameter1(); + var variable2 = f.getParameter2(); + var mathContext = f.getMathContext(); + if (ScriptUtils.instanceOf(variable1, Number.class) && ScriptUtils.instanceOf(variable2, Number.class)) { + //a^b = c + result.add(variable1.pow(variable2)); + return result; + } + } + return null; + } +} + +//Add this rule to the list of rules +RulesManager.addRule(engine.getInterface(rule, Rule.class)); \ No newline at end of file diff --git a/src/main/resources/rules/functions/Root.js b/src/main/resources/rules/functions/Root.js new file mode 100644 index 00000000..5f9f8f73 --- /dev/null +++ b/src/main/resources/rules/functions/Root.js @@ -0,0 +1,78 @@ +// Imports +var ObjectArrayList = Java.type("it.unimi.dsi.fastutil.objects.ObjectArrayList"); +var ScriptUtils = org.warp.picalculator.ScriptUtils; +var Rule = org.warp.picalculator.math.rules.Rule; +var RuleType = org.warp.picalculator.math.rules.RuleType; +var RulesManager = org.warp.picalculator.math.rules.RulesManager; +var Multiplication = org.warp.picalculator.math.functions.Multiplication; +var Sum = org.warp.picalculator.math.functions.Sum; +var Subtraction = org.warp.picalculator.math.functions.Subtraction; +var SumSubtraction = org.warp.picalculator.math.functions.SumSubtraction; +var Number = org.warp.picalculator.math.functions.Number; +var Division = org.warp.picalculator.math.functions.Division; +var Root = org.warp.picalculator.math.functions.Root; +var RootSquare = org.warp.picalculator.math.functions.RootSquare; +var BigDecimal = java.math.BigDecimal; + +/** + * Root + * a√b = c + * + * @author Andrea Cavalli + * + */ +var rule = { + // Rule name + getRuleName: function() { + return "Power"; + }, + // Rule type + getRuleType: function() { + return RuleType.CALCULATION; + }, + /* Rule function + Returns: + - null if it's not executable on the function "f" + - An ObjectArrayList if it did something + */ + execute: function(f) { + var isSquare = false; + if (ScriptUtils.instanceOf(f, Root.class) || (isSquare = ScriptUtils.instanceOf(f, RootSquare.class))) { + var result = new ObjectArrayList(); + var mathContext = f.getMathContext(); + var variable1 = isSquare?new Number(mathContext, 2):f.getParameter1(); + var variable2 = isSquare?f.getParameter():f.getParameter2(); + var isSolvable = false; + var canBePorted = false; + if (ScriptUtils.instanceOf(variable1, Number.class) && ScriptUtils.instanceOf(variable2, Number.class)) { + isSolvable = isSolvable|!mathContext.exactMode; + if (!isSolvable) { + try { + var resultVar = variable2.pow(new Number(mathContext, BigDecimal.ONE).divide(variable1)); + var originalVariable = resultVar.pow(new Number(mathContext, 2)); + if (originalVariable.equals(parameter2)) { + isSolvable = true; + } + } catch (ex) { + ex.printStackTrace(); + } + } + } + if (!isSquare && !isSolvable && ScriptUtils.instanceOf(variable1, Number.class) && variable1.equals(new Number(mathContext, 2))) { + canBePorted = true; + } + + if (isSolvable) { + result.add(variable2.pow(new Number(mathContext, BigInteger.ONE).divide(variable1))); + return result; + } + if (canBePorted) { + result.add(new RootSquare(mathContext, variable2)); + } + } + return null; + } +} + +//Add this rule to the list of rules +RulesManager.addRule(engine.getInterface(rule, Rule.class)); \ No newline at end of file