support for symbolic computations
This commit is contained in:
parent
0453519913
commit
ea7b249ed2
@ -8,7 +8,7 @@
|
|||||||
<uses-sdk android:minSdkVersion="8"/>
|
<uses-sdk android:minSdkVersion="8"/>
|
||||||
|
|
||||||
<application android:icon="@drawable/icon"
|
<application android:icon="@drawable/icon"
|
||||||
android:label="@string/c_app_icon_name">
|
android:label="@string/c_app_name">
|
||||||
|
|
||||||
<activity android:name=".CalculatorActivity"
|
<activity android:name=".CalculatorActivity"
|
||||||
android:label="@string/c_app_name">
|
android:label="@string/c_app_name">
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
<include layout="@layout/calc_editor"/>
|
<include layout="@layout/calc_editor"/>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout a:layout_weight="1" a:layout_width="match_parent" a:layout_height="0dp">
|
<LinearLayout a:layout_weight="1" a:layout_width="match_parent" a:layout_height="0dp">
|
||||||
|
|
||||||
<include layout="@layout/calc_display"
|
<include layout="@layout/calc_display"
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<string name="c_var_create_var">Создать переменную</string>
|
<string name="c_var_create_var">Создать переменную</string>
|
||||||
<string name="c_var_edit_var">Редактировать переменную</string>
|
<string name="c_var_edit_var">Редактировать переменную</string>
|
||||||
|
|
||||||
<string name="c_value.is.not.a.number">Значение - не число!</string>
|
<string name="c_value.is.not.a.number">Значение должно либо оставаться пустым либо быть числом!</string>
|
||||||
<string name="c_var.name.clashes">Имя переменной не может быть зарезервированным системным именем!</string>
|
<string name="c_var.name.clashes">Имя переменной не может быть зарезервированным системным именем!</string>
|
||||||
<string name="c_var.already.exists">Переменная с таким именем уже существует!</string>
|
<string name="c_var.already.exists">Переменная с таким именем уже существует!</string>
|
||||||
<string name="c_name.is.empty">Имя не может быть пустым!</string>
|
<string name="c_name.is.empty">Имя не может быть пустым!</string>
|
||||||
@ -84,4 +84,5 @@
|
|||||||
<string name="c_calc_color_display_summary">Включает/выключает подсветку синтаксиса в поле редактирования калькулятора</string>
|
<string name="c_calc_color_display_summary">Включает/выключает подсветку синтаксиса в поле редактирования калькулятора</string>
|
||||||
<string name="c_calc_theme_summary">Устанавливает тему оформления приложения</string>
|
<string name="c_calc_theme_summary">Устанавливает тему оформления приложения</string>
|
||||||
<string name="c_clear_history">Очистить историю</string>
|
<string name="c_clear_history">Очистить историю</string>
|
||||||
|
<string name="c_simplify_instead_of_numeric">Следующие константы не определены: {0}!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
<string name="c_var_create_var">Create variable</string>
|
<string name="c_var_create_var">Create variable</string>
|
||||||
<string name="c_var_edit_var">Edit variable</string>
|
<string name="c_var_edit_var">Edit variable</string>
|
||||||
|
|
||||||
<string name="c_value.is.not.a.number">Value is not a number!</string>
|
<string name="c_value.is.not.a.number">Value must be either number or empty!</string>
|
||||||
<string name="c_var.name.clashes">Variable name clashes with function name!</string>
|
<string name="c_var.name.clashes">Variable name clashes with function name!</string>
|
||||||
<string name="c_var.already.exists">Variable with same name already exists!</string>
|
<string name="c_var.already.exists">Variable with same name already exists!</string>
|
||||||
<string name="c_name.is.empty">Name is empty!</string>
|
<string name="c_name.is.empty">Name is empty!</string>
|
||||||
@ -84,4 +84,5 @@
|
|||||||
<string name="c_calc_color_display_summary">Enables/disables colouring and styling in calculator editor</string>
|
<string name="c_calc_color_display_summary">Enables/disables colouring and styling in calculator editor</string>
|
||||||
<string name="c_calc_theme_summary">Sets the theme for calculator</string>
|
<string name="c_calc_theme_summary">Sets the theme for calculator</string>
|
||||||
<string name="c_clear_history">Clear history</string>
|
<string name="c_clear_history">Clear history</string>
|
||||||
|
<string name="c_simplify_instead_of_numeric">Next constants are undefined: {0}!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -24,6 +24,7 @@ import bsh.EvalError;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
|
import org.solovyev.android.msg.AndroidMessageRegistry;
|
||||||
import org.solovyev.android.view.FontSizeAdjuster;
|
import org.solovyev.android.view.FontSizeAdjuster;
|
||||||
import org.solovyev.android.view.widgets.*;
|
import org.solovyev.android.view.widgets.*;
|
||||||
import org.solovyev.common.BooleanMapper;
|
import org.solovyev.common.BooleanMapper;
|
||||||
@ -364,9 +365,18 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
|
|
||||||
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
|
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
|
||||||
|
|
||||||
|
AndroidMessageRegistry.instance.init(this);
|
||||||
|
|
||||||
this.calculatorModel.evaluate();
|
this.calculatorModel.evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
AndroidMessageRegistry.instance.finish();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String s) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String s) {
|
||||||
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this));
|
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this));
|
||||||
|
@ -26,7 +26,7 @@ public class CalculatorEditor extends EditText {
|
|||||||
private boolean highlightText = true;
|
private boolean highlightText = true;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE);
|
private final static TextProcessor<String> textHighlighter = new TextHighlighter(Color.WHITE);
|
||||||
|
|
||||||
public CalculatorEditor(Context context) {
|
public CalculatorEditor(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -18,6 +18,7 @@ import android.widget.Toast;
|
|||||||
import bsh.EvalError;
|
import bsh.EvalError;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.model.ParseException;
|
import org.solovyev.android.calculator.model.ParseException;
|
||||||
|
@ -119,7 +119,9 @@ public class CalculatorVarsActivity extends ListActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final EditText editValue = (EditText) editView.findViewById(R.id.var_edit_value);
|
final EditText editValue = (EditText) editView.findViewById(R.id.var_edit_value);
|
||||||
|
if (!StringUtils.isEmpty(value)) {
|
||||||
editValue.setText(value);
|
editValue.setText(value);
|
||||||
|
}
|
||||||
|
|
||||||
final EditText editDescription = (EditText) editView.findViewById(R.id.var_edit_description);
|
final EditText editDescription = (EditText) editView.findViewById(R.id.var_edit_description);
|
||||||
editDescription.setText(description);
|
editDescription.setText(description);
|
||||||
@ -198,6 +200,15 @@ public class CalculatorVarsActivity extends ListActivity {
|
|||||||
final MathType.Result mathType = MathType.getType(name, 0);
|
final MathType.Result mathType = MathType.getType(name, 0);
|
||||||
|
|
||||||
if (mathType.getMathType() == MathType.text || mathType.getMathType() == MathType.constant) {
|
if (mathType.getMathType() == MathType.text || mathType.getMathType() == MathType.constant) {
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(value)) {
|
||||||
|
// value is empty => undefined variable
|
||||||
|
varBuilder.setName(name);
|
||||||
|
varBuilder.setDescription(description);
|
||||||
|
varBuilder.setValue(null);
|
||||||
|
error = null;
|
||||||
|
} else {
|
||||||
|
// value is not empty => must be a number
|
||||||
boolean correctDouble = true;
|
boolean correctDouble = true;
|
||||||
try {
|
try {
|
||||||
Double.valueOf(value);
|
Double.valueOf(value);
|
||||||
@ -207,12 +218,13 @@ public class CalculatorVarsActivity extends ListActivity {
|
|||||||
|
|
||||||
if (correctDouble) {
|
if (correctDouble) {
|
||||||
varBuilder.setName(name);
|
varBuilder.setName(name);
|
||||||
varBuilder.setValue(value);
|
|
||||||
varBuilder.setDescription(description);
|
varBuilder.setDescription(description);
|
||||||
|
varBuilder.setValue(value);
|
||||||
error = null;
|
error = null;
|
||||||
} else {
|
} else {
|
||||||
error = R.string.c_value_is_not_a_number;
|
error = R.string.c_value_is_not_a_number;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error = R.string.c_var_name_clashes;
|
error = R.string.c_var_name_clashes;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
|
||||||
|
|
||||||
public enum JsclOperation {
|
|
||||||
|
|
||||||
simplify,
|
|
||||||
elementary,
|
|
||||||
importCommands,
|
|
||||||
numeric;
|
|
||||||
|
|
||||||
}
|
|
@ -17,7 +17,7 @@ import org.solovyev.android.calculator.model.TextProcessor;
|
|||||||
* Date: 10/12/11
|
* Date: 10/12/11
|
||||||
* Time: 9:47 PM
|
* Time: 9:47 PM
|
||||||
*/
|
*/
|
||||||
public class TextHighlighter implements TextProcessor {
|
public class TextHighlighter implements TextProcessor<String> {
|
||||||
|
|
||||||
private final int color;
|
private final int color;
|
||||||
private final int colorRed;
|
private final int colorRed;
|
||||||
|
@ -4,10 +4,13 @@
|
|||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
|
import org.solovyev.android.calculator.model.ParseException;
|
||||||
|
import org.solovyev.android.calculator.model.TextProcessor;
|
||||||
import org.solovyev.common.utils.MathUtils;
|
import org.solovyev.common.utils.MathUtils;
|
||||||
import org.solovyev.util.math.Complex;
|
import org.solovyev.util.math.Complex;
|
||||||
|
|
||||||
@ -16,7 +19,7 @@ import org.solovyev.util.math.Complex;
|
|||||||
* Date: 10/6/11
|
* Date: 10/6/11
|
||||||
* Time: 9:48 PM
|
* Time: 9:48 PM
|
||||||
*/
|
*/
|
||||||
class FromJsclTextProcessor implements TextProcessor {
|
class FromJsclNumericTextProcessor implements TextProcessor<String> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.model.DummyTextProcessor;
|
||||||
|
import org.solovyev.android.calculator.model.TextProcessor;
|
||||||
|
|
||||||
|
public enum JsclOperation {
|
||||||
|
|
||||||
|
simplify(DummyTextProcessor.instance),
|
||||||
|
elementary(DummyTextProcessor.instance),
|
||||||
|
importCommands(DummyTextProcessor.instance),
|
||||||
|
numeric(new FromJsclNumericTextProcessor());
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final TextProcessor<String> fromProcessor;
|
||||||
|
|
||||||
|
JsclOperation(@NotNull TextProcessor<String> fromProcessor) {
|
||||||
|
this.fromProcessor = fromProcessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public TextProcessor<String> getFromProcessor() {
|
||||||
|
return fromProcessor;
|
||||||
|
}
|
||||||
|
}
|
@ -11,8 +11,14 @@ import bsh.EvalError;
|
|||||||
import bsh.Interpreter;
|
import bsh.Interpreter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.JsclOperation;
|
import org.solovyev.android.calculator.R;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.android.msg.AndroidMessage;
|
||||||
import org.solovyev.common.NumberMapper;
|
import org.solovyev.common.NumberMapper;
|
||||||
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
|
import org.solovyev.common.msg.MessageType;
|
||||||
|
import org.solovyev.common.utils.CollectionsUtils;
|
||||||
|
import org.solovyev.common.utils.Formatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -36,25 +42,46 @@ public enum CalculatorEngine {
|
|||||||
private int numberOfFractionDigits = 5;
|
private int numberOfFractionDigits = 5;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final TextProcessor preprocessor = new ToJsclTextProcessor();
|
public final TextProcessor<PreparedExpression> preprocessor = new ToJsclTextProcessor();
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public final TextProcessor postprocessor = new FromJsclTextProcessor();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final VarsRegisterImpl varsRegister = new VarsRegisterImpl();
|
private final VarsRegisterImpl varsRegister = new VarsRegisterImpl();
|
||||||
|
|
||||||
public String evaluate(@NotNull JsclOperation operation, @NotNull String expression) throws EvalError, ParseException {
|
public String evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression) throws EvalError, ParseException {
|
||||||
|
return evaluate(operation, expression, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry<AndroidMessage> mr) throws EvalError, ParseException {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.append(preprocessor.process(expression));
|
final PreparedExpression preparedExpression = preprocessor.process(expression);
|
||||||
|
sb.append(preparedExpression);
|
||||||
|
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preprocessedExpression);
|
//Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preprocessedExpression);
|
||||||
|
if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
|
||||||
|
operation = JsclOperation.simplify;
|
||||||
|
|
||||||
|
if (mr != null) {
|
||||||
|
final String undefinedVars = CollectionsUtils.formatValue(preparedExpression.getUndefinedVars(), ", ", new Formatter<Var>() {
|
||||||
|
@Override
|
||||||
|
public String formatValue(@Nullable Var var) throws IllegalArgumentException {
|
||||||
|
return var != null ? var.getName() : "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final Object evaluationObject = interpreter.eval(ToJsclTextProcessor.wrap(operation, sb.toString()));
|
final Object evaluationObject = interpreter.eval(ToJsclTextProcessor.wrap(operation, sb.toString()));
|
||||||
|
|
||||||
return postprocessor.process(String.valueOf(evaluationObject).trim());
|
final String result = String.valueOf(evaluationObject).trim();
|
||||||
|
|
||||||
|
return operation.getFromProcessor().process(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 10/18/11
|
||||||
|
* Time: 10:39 PM
|
||||||
|
*/
|
||||||
|
public enum DummyTextProcessor implements TextProcessor<String> {
|
||||||
|
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String process(@NotNull String s) throws ParseException {
|
||||||
|
return s.replace(ToJsclTextProcessor.SPECIAL_STRING, "");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 10/18/11
|
||||||
|
* Time: 10:07 PM
|
||||||
|
*/
|
||||||
|
public class PreparedExpression implements CharSequence{
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String expression;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private List<Var> undefinedVars;
|
||||||
|
|
||||||
|
public PreparedExpression(@NotNull String expression, @NotNull List<Var> undefinedVars) {
|
||||||
|
this.expression = expression;
|
||||||
|
this.undefinedVars = undefinedVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExistsUndefinedVar() {
|
||||||
|
return !this.undefinedVars.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<Var> getUndefinedVars() {
|
||||||
|
return undefinedVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int length() {
|
||||||
|
return expression.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char charAt(int i) {
|
||||||
|
return expression.charAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence subSequence(int i, int i1) {
|
||||||
|
return expression.subSequence(i, i1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.expression;
|
||||||
|
}
|
||||||
|
}
|
@ -7,8 +7,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* Date: 9/26/11
|
* Date: 9/26/11
|
||||||
* Time: 12:12 PM
|
* Time: 12:12 PM
|
||||||
*/
|
*/
|
||||||
public interface TextProcessor {
|
public interface TextProcessor<T extends CharSequence> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
String process(@NotNull String s) throws ParseException;
|
T process(@NotNull String s) throws ParseException;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ package org.solovyev.android.calculator.model;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.android.calculator.StartsWithFinder;
|
import org.solovyev.android.calculator.StartsWithFinder;
|
||||||
import org.solovyev.android.calculator.math.Functions;
|
import org.solovyev.android.calculator.math.Functions;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
@ -16,11 +16,16 @@ import org.solovyev.common.utils.CollectionsUtils;
|
|||||||
import org.solovyev.common.utils.FilterType;
|
import org.solovyev.common.utils.FilterType;
|
||||||
import org.solovyev.common.utils.Finder;
|
import org.solovyev.common.utils.Finder;
|
||||||
|
|
||||||
class ToJsclTextProcessor implements TextProcessor {
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
|
||||||
|
|
||||||
|
public static final String SPECIAL_STRING = "☀☀☀";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public String process(@NotNull String s) {
|
public PreparedExpression process(@NotNull String s) {
|
||||||
|
|
||||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(s, 0);
|
final StartsWithFinder startsWithFinder = new StartsWithFinder(s, 0);
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
@ -47,7 +52,7 @@ class ToJsclTextProcessor implements TextProcessor {
|
|||||||
startsWithFinder.setI(i + 1);
|
startsWithFinder.setI(i + 1);
|
||||||
if ( i < s.length() && CollectionsUtils.get(MathType.groupSymbols, startsWithFinder) != null) {
|
if ( i < s.length() && CollectionsUtils.get(MathType.groupSymbols, startsWithFinder) != null) {
|
||||||
i += 2;
|
i += 2;
|
||||||
sb.append("(foo)");
|
sb.append("(" + SPECIAL_STRING + ")");
|
||||||
mathTypeResult = new MathType.Result(MathType.close_group_symbol, ")");
|
mathTypeResult = new MathType.Result(MathType.close_group_symbol, ")");
|
||||||
}
|
}
|
||||||
} else if (mathType == MathType.constant) {
|
} else if (mathType == MathType.constant) {
|
||||||
@ -61,9 +66,12 @@ class ToJsclTextProcessor implements TextProcessor {
|
|||||||
return replaceVariables(sb.toString());
|
return replaceVariables(sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String replaceVariables(@NotNull final String s) {
|
@NotNull
|
||||||
|
private PreparedExpression replaceVariables(@NotNull final String s) {
|
||||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(s, 0);
|
final StartsWithFinder startsWithFinder = new StartsWithFinder(s, 0);
|
||||||
|
|
||||||
|
final List<Var> undefinedVars = new ArrayList<Var>();
|
||||||
|
|
||||||
final StringBuilder result = new StringBuilder();
|
final StringBuilder result = new StringBuilder();
|
||||||
for (int i = 0; i < s.length(); i++) {
|
for (int i = 0; i < s.length(); i++) {
|
||||||
startsWithFinder.setI(i);
|
startsWithFinder.setI(i);
|
||||||
@ -75,10 +83,16 @@ class ToJsclTextProcessor implements TextProcessor {
|
|||||||
if (varName != null) {
|
if (varName != null) {
|
||||||
final Var var = CalculatorEngine.instance.getVarsRegister().getVar(varName);
|
final Var var = CalculatorEngine.instance.getVarsRegister().getVar(varName);
|
||||||
if (var != null) {
|
if (var != null) {
|
||||||
|
if (var.isUndefined()) {
|
||||||
|
undefinedVars.add(var);
|
||||||
|
result.append(varName);
|
||||||
|
offset = varName.length();
|
||||||
|
} else {
|
||||||
result.append(var.getValue());
|
result.append(var.getValue());
|
||||||
offset = varName.length();
|
offset = varName.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result.append(functionName);
|
result.append(functionName);
|
||||||
offset = functionName.length();
|
offset = functionName.length();
|
||||||
@ -92,7 +106,7 @@ class ToJsclTextProcessor implements TextProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.toString();
|
return new PreparedExpression(result.toString(), undefinedVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replaceVariables(StringBuilder sb, String s, int i, @NotNull StartsWithFinder startsWithFinder) {
|
private void replaceVariables(StringBuilder sb, String s, int i, @NotNull StartsWithFinder startsWithFinder) {
|
||||||
|
@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.simpleframework.xml.Element;
|
import org.simpleframework.xml.Element;
|
||||||
import org.simpleframework.xml.Root;
|
import org.simpleframework.xml.Root;
|
||||||
|
import org.solovyev.common.utils.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -24,8 +25,8 @@ public class Var {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Element
|
@Element(required = false)
|
||||||
@NotNull
|
@Nullable
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
@Element
|
@Element
|
||||||
@ -40,7 +41,7 @@ public class Var {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@NotNull
|
@Nullable
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
private boolean system = false;
|
private boolean system = false;
|
||||||
@ -62,7 +63,7 @@ public class Var {
|
|||||||
this(name, String.valueOf(value));
|
this(name, String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder(@NotNull String name, @NotNull String value) {
|
public Builder(@NotNull String name, @Nullable String value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
@ -71,7 +72,7 @@ public class Var {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(@NotNull String value) {
|
public void setValue(@Nullable String value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ public class Var {
|
|||||||
this.system = var.system;
|
this.system = var.system;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nullable
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -121,18 +122,22 @@ public class Var {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUndefined() {
|
||||||
|
return StringUtils.isEmpty(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDescription(@Nullable String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
if (value != null) {
|
||||||
return getName() + " = " + value;
|
return getName() + " = " + value;
|
||||||
|
} else {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
33
src/main/java/org/solovyev/android/msg/AndroidMessage.java
Normal file
33
src/main/java/org/solovyev/android/msg/AndroidMessage.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.msg;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.common.msg.AbstractMessage;
|
||||||
|
import org.solovyev.common.msg.MessageType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 10/18/11
|
||||||
|
* Time: 11:57 PM
|
||||||
|
*/
|
||||||
|
public class AndroidMessage extends AbstractMessage<Integer> {
|
||||||
|
|
||||||
|
public AndroidMessage(@NotNull Integer messageCode,
|
||||||
|
@NotNull MessageType messageType,
|
||||||
|
@org.jetbrains.annotations.Nullable Object... arguments) {
|
||||||
|
super(messageCode, messageType, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AndroidMessage(@NotNull Integer messageCode,
|
||||||
|
@NotNull MessageType messageType,
|
||||||
|
@org.jetbrains.annotations.Nullable List<?> arguments) {
|
||||||
|
super(messageCode, messageType, arguments);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.msg;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 10/18/11
|
||||||
|
* Time: 11:49 PM
|
||||||
|
*/
|
||||||
|
public enum AndroidMessageRegistry implements MessageRegistry<AndroidMessage> {
|
||||||
|
|
||||||
|
instance;
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public void init(@NotNull Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addMessage(@NotNull AndroidMessage message) {
|
||||||
|
if (context != null) {
|
||||||
|
Toast.makeText(context, formatMessage(message), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public AndroidMessage getMessage() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMessage() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String formatMessage(@NotNull AndroidMessage message) {
|
||||||
|
final String messagePattern = context.getString(message.getMessageCode());
|
||||||
|
|
||||||
|
final String result;
|
||||||
|
if (messagePattern != null) {
|
||||||
|
result = message.formatMessage(messagePattern, Locale.getDefault());
|
||||||
|
} else {
|
||||||
|
result = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
this.context = null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 10/18/11
|
||||||
|
* Time: 10:42 PM
|
||||||
|
*/
|
||||||
|
public class FromJsclNumericTextProcessorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateResultForComplexNumber() throws Exception {
|
||||||
|
final FromJsclNumericTextProcessor cm = new FromJsclNumericTextProcessor();
|
||||||
|
|
||||||
|
Assert.assertEquals("1.22133+23123.0i", cm.createResultForComplexNumber("1.22133232+23123*i"));
|
||||||
|
Assert.assertEquals("1.22133+1.2i", cm.createResultForComplexNumber("1.22133232+1.2*i"));
|
||||||
|
Assert.assertEquals("1.22i", cm.createResultForComplexNumber("1.22*i"));
|
||||||
|
Assert.assertEquals("i", cm.createResultForComplexNumber("i"));
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ import org.junit.Assert;
|
|||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.simpleframework.xml.Attribute;
|
import org.simpleframework.xml.Attribute;
|
||||||
import org.solovyev.android.calculator.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -81,17 +81,12 @@ public class CalculatorEngineTest {
|
|||||||
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k", 3.5d));
|
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k", 3.5d));
|
||||||
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k1", 4d));
|
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k1", 4d));
|
||||||
Assert.assertEquals("4.0", cm.evaluate(JsclOperation.numeric, "k11"));
|
Assert.assertEquals("4.0", cm.evaluate(JsclOperation.numeric, "k11"));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testComplexNumbers() throws Exception {
|
|
||||||
final FromJsclTextProcessor cm = new FromJsclTextProcessor();
|
|
||||||
|
|
||||||
Assert.assertEquals("1.22133+23123.0i", cm.createResultForComplexNumber("1.22133232+23123*i"));
|
|
||||||
Assert.assertEquals("1.22133+1.2i", cm.createResultForComplexNumber("1.22133232+1.2*i"));
|
|
||||||
Assert.assertEquals("1.22i", cm.createResultForComplexNumber("1.22*i"));
|
|
||||||
Assert.assertEquals("i", cm.createResultForComplexNumber("i"));
|
|
||||||
|
|
||||||
|
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("t", (String)null));
|
||||||
|
Assert.assertEquals("11*t", cm.evaluate(JsclOperation.numeric, "t11"));
|
||||||
|
Assert.assertEquals("11*2.718281828459045*t", cm.evaluate(JsclOperation.numeric, "t11e"));
|
||||||
|
Assert.assertEquals("11*Infinity*t", cm.evaluate(JsclOperation.numeric, "t11∞"));
|
||||||
|
Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface TestInterface {
|
public interface TestInterface {
|
||||||
|
Loading…
Reference in New Issue
Block a user