Skip to content

Commit

Permalink
reorganized and cleaned code for the release
Browse files Browse the repository at this point in the history
  • Loading branch information
Tran-Antoine committed Mar 5, 2019
1 parent 5dae496 commit e8dabc4
Show file tree
Hide file tree
Showing 21 changed files with 165 additions and 183 deletions.
65 changes: 3 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,77 +12,18 @@ Mask is a free open source library that helps the user dealing with mathematical

### Build

We recommend using gradle for building the api. Your build.gradle should have the following lines :
You will need gradle to build the api. Your build.gradle should have the following lines :

```groovy
repositories {
maven { url "https://jitpack.io"}
}
dependencies {
implementation 'com.github.Askigh:Mask:v0.2'
implementation 'com.github.Askigh:Mask:<latest_version_here>'
}
```

## How to use it

> A mathematical expression is represented by a class called MaskExpression. The following code shows how to create one properly :
```java
package test;

import net.akami.mask.math.MaskExpression;
import net.akami.mask.math.MaskOperator;

public class MathTest {

public static void main(String... args) {

// Creates the math expression
MaskExpression curve = new MaskExpression("3x^2 + 2x + 6 + 2y");
// Prepares the operator.
MaskOperator operator = MaskOperator.begin();

/* null indicates that the result of the calculation "imageFor" doesn't need to be saved as a mask.
Instead, a final temporary variable will contain the result. The boolean indicates that the mask selected
for calculations need to be changed after the first calculation. In fact, as we want to convert the result to
an integer, we want the result of the calculation to be the actual mask, so that we can convert it to an
integer afterwards
*/
System.out.println("Image : "+operator.imageFor(curve, null, true, 2, 0).asInt());
System.out.println("Expression : "+curve);

// The default mask used for calculation is now set to null
operator.end();
/* Output :
Image : 22
Expression : 3x^2+2x+6+2y
*/

// Let's now imagine we want to change the curve expression, by replacing all the x's by 3.

/* We need to call begin again because we called end() before. If you know that there will be no calculations
between the last one and this one, you don't need to call end(), neither do you need to call begin() again
*/
operator.begin(curve);
operator.imageFor(3);

/*
We use 'false' so the mask used for calculations remains 39+2y, not the result of the calculation.
We use null again so that it affects the temporary variable, and not the mask itself.
When calling asFloat, we need to specify that we want the float value of the temporary variable,
by default the method gives us the value of the default mask, here 39+2y.
*/
float image1 = operator.imageFor(curve, null, false, 0).asFloat(MaskExpression.TEMP);
float image2 = operator.imageFor(curve, null, false, 2).asFloat(MaskExpression.TEMP);
System.out.println(curve);
System.out.println(image1 + " / " + image2);

/* Output : 39+2y
39.0 / 43.0
The expression has indeed been changed. Note that masks are mutable objects, so be careful with constants.
*/
}
}
```
> See the wiki for all the required information
7 changes: 0 additions & 7 deletions src/issues.txt

This file was deleted.

14 changes: 7 additions & 7 deletions src/main/java/net/akami/mask/math/BinaryTree.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package net.akami.mask.math;

import net.akami.mask.utils.ReducerFactory;
import net.akami.mask.utils.ExpressionUtils;
import net.akami.mask.utils.TreeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static net.akami.mask.utils.ReducerFactory.OPERATIONS;
import static net.akami.mask.utils.ReducerFactory.PROCEDURAL_OPERATIONS;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -39,13 +39,13 @@ public Branch(String expression) {
reduced = false;
branches.add(this);
LOGGER.debug("Now treating : "+this);
for (int i = 0; i < OPERATIONS.length; i += 2) {
split(OPERATIONS[i].getSign(), OPERATIONS[i + 1].getSign());
for (int i = 0; i < PROCEDURAL_OPERATIONS.length; i += 2) {
split(PROCEDURAL_OPERATIONS[i].getSign(), PROCEDURAL_OPERATIONS[i + 1].getSign());
}
}

private String deleteUselessBrackets(String exp) {
while(TreeUtils.areEdgesBracketsConnected(exp)) {
while(ExpressionUtils.areEdgesBracketsConnected(exp)) {
exp = exp.substring(1, exp.length()-1);
}
return exp;
Expand Down Expand Up @@ -113,9 +113,9 @@ public void split(char c1, char c2) {

if ((c == c1 || c == c2)) {
LOGGER.debug("Checking if sign {} at index {} is surrounded in {}", c, i, this);
boolean bracketsConnected = TreeUtils.areEdgesBracketsConnected(expression);
boolean bracketsConnected = ExpressionUtils.areEdgesBracketsConnected(expression);

if (!ReducerFactory.isSurroundedByParentheses(i, expression)) {
if (!ExpressionUtils.isSurroundedByParentheses(i, expression)) {
LOGGER.debug("Found a place to split at index {}, character '{}'", i, c);
TreeUtils.createNewBranch(BinaryTree.this, this, i, c, bracketsConnected);
break;
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/net/akami/mask/math/MaskExpression.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package net.akami.mask.math;

import net.akami.mask.exception.MaskException;
import net.akami.mask.operation.MaskOperator;
import net.akami.mask.utils.ExpressionUtils;

import java.util.ArrayList;

/**
* MaskExpression is the core object of the mask library. It handles a String, which corresponds to the expression,
* and an array of variables, used to solve the expression for values, or to provide images of the function.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.akami.mask.math;
package net.akami.mask.operation;

import net.akami.mask.exception.MaskException;
import net.akami.mask.math.MaskExpression;
import net.akami.mask.utils.ExpressionUtils;
import net.akami.mask.utils.MathUtils;
import net.akami.mask.utils.ReducerFactory;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.akami.mask.math;
package net.akami.mask.operation;

import net.akami.mask.utils.MathUtils;

Expand All @@ -12,9 +12,9 @@ public enum OperationSign {
NONE(' ', null);

private char sign;
private MathOperation function;
private BinaryMathOperation function;

OperationSign(char sign, MathOperation function) {
OperationSign(char sign, BinaryMathOperation function) {
this.sign = sign;
this.function = function;
}
Expand All @@ -37,7 +37,7 @@ public static OperationSign getBySign(char sign) {
}

@FunctionalInterface
private interface MathOperation {
private interface BinaryMathOperation {
String compute(String a, String b);
}
}
12 changes: 11 additions & 1 deletion src/main/java/net/akami/mask/structure/EquationSolver.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.akami.mask.structure;

import net.akami.mask.math.MaskExpression;
import net.akami.mask.math.MaskOperator;
import net.akami.mask.operation.MaskOperator;
import net.akami.mask.utils.ExpressionUtils;
import net.akami.mask.utils.MathUtils;
import net.akami.mask.utils.ReducerFactory;
Expand All @@ -14,6 +14,16 @@ public class EquationSolver {

private static final Logger LOGGER = LoggerFactory.getLogger(EquationSolver.class);

public static List<BiMask> build(String... lines) {
List<BiMask> biMasks = new ArrayList<>();
for(String line : lines) {
String[] sides = line.split("=");
if(sides.length != 2) throw new IllegalArgumentException("Invalid line given (0 or more than 1 '=' found");
biMasks.add(new BiMask(new MaskExpression(sides[0]), new MaskExpression(sides[1])));
}
return biMasks;
}

public static String[] solve(List<BiMask> biMasks) {
MaskOperator op = MaskOperator.begin();
for(BiMask biMask : biMasks) {
Expand Down
18 changes: 0 additions & 18 deletions src/main/java/net/akami/mask/structure/MaskStructure.java

This file was deleted.

67 changes: 59 additions & 8 deletions src/main/java/net/akami/mask/utils/ExpressionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,20 @@ public class ExpressionUtils {

private static final Logger LOGGER = LoggerFactory.getLogger(ExpressionUtils.class);
private static final StringBuilder BUILDER = new StringBuilder();
private static final String DELETE_VARIABLES = "[a-zA-DF-Z]+";
private static final String DELETE_NON_VARIABLES = "[\\d.+\\-/*()^]+";
public static final String MATH_SIGNS = "+-*/^()";
public static final String NUMBERS = "0123456789";
// 'E' deliberately missing
public static final String VARIABLES = "abcdefghijklmnopqrstuvwxyzABCDFGHIJKLMNOPQRSTUVWXYZ";

public static final String TRIGONOMETRY_SHORTCUTS = "@#§";
public static List<String> toMonomials(String self) {

List<String> monomials = new ArrayList<>();
int lastIndex = 0;
for (int i = 0; i < self.length(); i++) {
// We don't want i = 0 because if the first char is '-', it will add an empty string to the list
if (self.charAt(i) == '+' || self.charAt(i) == '-' && i != 0) {
if (ReducerFactory.isSurroundedByParentheses(i, self)) {
if (isSurroundedByParentheses(i, self)) {
continue;
}
String monomial = self.substring(lastIndex, i);
Expand Down Expand Up @@ -196,7 +195,7 @@ private static void finishSequenceCalculation(SequenceCalculationResult result,
result.start = index;
result.end = exp.length();
}
if(TreeUtils.areEdgesBracketsConnected(result.sequence)) {
if(areEdgesBracketsConnected(result.sequence)) {
result.sequence = result.sequence.substring(1, result.sequence.length()-1);
}
}
Expand Down Expand Up @@ -273,10 +272,12 @@ public static String cancelMultShortcut(String self) {

for(int i = 0; i < self.length(); i++) {
String c = String.valueOf(self.charAt(i));
if(ExpressionUtils.VARIABLES.contains(c) && i!= 0 &&
!ExpressionUtils.MATH_SIGNS.contains(String.valueOf(self.charAt(i-1)))) {
BUILDER.append("*").append(c);
} else if(i != 0 && c.equals("(") && self.charAt(i-1) == ')') {
boolean varOrTrigo = ExpressionUtils.VARIABLES.contains(c) || ExpressionUtils.TRIGONOMETRY_SHORTCUTS.contains(c);

if(varOrTrigo && i!= 0 && !ExpressionUtils.MATH_SIGNS.contains(String.valueOf(self.charAt(i-1)))) {
BUILDER.append("*").append(c);
} else if(i != 0 && c.equals("(") &&
(self.charAt(i-1) == ')' || !MATH_SIGNS.contains(String.valueOf(self.charAt(i-1))))) {
BUILDER.append("*").append(c);
} else {
BUILDER.append(c);
Expand Down Expand Up @@ -422,6 +423,56 @@ public static boolean isSigned(String exp) {
return exp.charAt(0) == '+' || exp.charAt(0) == '-';
}

public static boolean areEdgesBracketsConnected(String exp) {
if (exp.isEmpty() || exp.charAt(0) != '(') {
return false;
}
int left = 0;
for (int i = 1; i < exp.length() - 1; i++) {
if (exp.charAt(i) == ')') {
left--;
} else if (exp.charAt(i) == '(') {
left++;
}
if (left < 0) {
break;
}
}
if (left >= 0) {
exp = exp.substring(1, exp.length() - 1);
LOGGER.debug("Connected brackets found at position 0 and last, new expression : {}", exp);
return true;
}
return false;
}

public static boolean isSurroundedByParentheses(int index, String exp) {

// In case the exp is 5*-3 or 5/-3
if(index > 0 && (exp.charAt(index-1) == '/' || exp.charAt(index-1) == '*')) {
LOGGER.info("Character right after * or /. Is surrounded = true");
return true;
}

int leftParenthesis = 0;

for(int i = 0; i < exp.length(); i++) {
if(exp.charAt(i) == '(') {
leftParenthesis++;
}

if(exp.charAt(i) == ')') {
leftParenthesis--;
}
if(leftParenthesis > 0 && i == index) {
LOGGER.debug("- Indeed surrounded");
return true;
}
}
LOGGER.debug("- Not surrounded");
return false;
}

public static class SequenceCalculationResult {
private String sequence;
private int start;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/net/akami/mask/utils/FormatterFactory.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package net.akami.mask.utils;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FormatterFactory {

Expand All @@ -20,6 +22,16 @@ public static String removeFractions(String origin) {
return BUILDER.toString();
}

/*public static String deleteMathShortcuts(String origin) {
origin = origin.replaceAll("\\s", "");
Pattern pattern = Pattern.compile("(cos\\()(.+)(\\))");
Matcher matcher = pattern.matcher(origin);
while(matcher.find()) {
System.out.println(matcher.replaceAll(matcher.group(2)));
}
return ExpressionUtils.cancelMultShortcut(origin);
}*/

private static void clearBuilder() {
BUILDER.delete(0, BUILDER.length());
}
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/net/akami/mask/utils/MathUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,26 @@ public static String pow(String a, String b) {
return Pow.getInstance().rawOperate(a, b);
}

public static String sin(String a) {
if(ExpressionUtils.isANumber(a)) {
return String.valueOf(Math.sin(Float.valueOf(a)));
}
return a;
}

public static String cos(String a) {
if(ExpressionUtils.isANumber(a)) {
return String.valueOf(Math.cos(Float.valueOf(a)));
}
return a;
}

public static String tan(String a) {
if(ExpressionUtils.isANumber(a)) {
return String.valueOf(Math.tan(Float.valueOf(a)));
}
return a;
}
/**
* Method currently in development. Do not use
*
Expand Down
Loading

0 comments on commit e8dabc4

Please sign in to comment.