From 2624a67b114e5d61b01f59dc5bc32b33abd606bd Mon Sep 17 00:00:00 2001 From: serso Date: Wed, 19 Oct 2011 00:40:01 +0400 Subject: [PATCH] support for symbolic computations --- AndroidManifest.xml | 2 +- res/layout-port/main.xml | 1 - res/values-ru/strings.xml | 3 +- res/values/strings.xml | 3 +- .../calculator/CalculatorActivity.java | 10 +++ .../android/calculator/CalculatorEditor.java | 2 +- .../android/calculator/CalculatorModel.java | 1 + .../calculator/CalculatorVarsActivity.java | 32 ++++++--- .../android/calculator/JsclOperation.java | 15 ----- .../android/calculator/TextHighlighter.java | 2 +- .../FromJsclNumericTextProcessor.java} | 7 +- .../calculator/jscl/JsclOperation.java | 31 +++++++++ .../calculator/model/CalculatorEngine.java | 43 +++++++++--- .../calculator/model/DummyTextProcessor.java | 25 +++++++ .../calculator/model/PreparedExpression.java | 64 ++++++++++++++++++ .../calculator/model/TextProcessor.java | 4 +- .../calculator/model/ToJsclTextProcessor.java | 30 ++++++--- .../android/calculator/model/Var.java | 27 ++++---- .../solovyev/android/msg/AndroidMessage.java | 33 ++++++++++ .../android/msg/AndroidMessageRegistry.java | 66 +++++++++++++++++++ .../FromJsclNumericTextProcessorTest.java | 28 ++++++++ .../model/CalculatorEngineTest.java | 17 ++--- 22 files changed, 373 insertions(+), 73 deletions(-) delete mode 100644 src/main/java/org/solovyev/android/calculator/JsclOperation.java rename src/main/java/org/solovyev/android/calculator/{model/FromJsclTextProcessor.java => jscl/FromJsclNumericTextProcessor.java} (87%) create mode 100644 src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java create mode 100644 src/main/java/org/solovyev/android/calculator/model/DummyTextProcessor.java create mode 100644 src/main/java/org/solovyev/android/calculator/model/PreparedExpression.java create mode 100644 src/main/java/org/solovyev/android/msg/AndroidMessage.java create mode 100644 src/main/java/org/solovyev/android/msg/AndroidMessageRegistry.java create mode 100644 src/test/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessorTest.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index aa3b5aa0..ce808ad7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -8,7 +8,7 @@ + android:label="@string/c_app_name"> diff --git a/res/layout-port/main.xml b/res/layout-port/main.xml index fb94f8ec..4ddceba1 100644 --- a/res/layout-port/main.xml +++ b/res/layout-port/main.xml @@ -14,7 +14,6 @@ - Создать переменную Редактировать переменную - Значение - не число! + Значение должно либо оставаться пустым либо быть числом! Имя переменной не может быть зарезервированным системным именем! Переменная с таким именем уже существует! Имя не может быть пустым! @@ -84,4 +84,5 @@ Включает/выключает подсветку синтаксиса в поле редактирования калькулятора Устанавливает тему оформления приложения Очистить историю + Следующие константы не определены: {0}! diff --git a/res/values/strings.xml b/res/values/strings.xml index d2f5948f..6e0d68ac 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -52,7 +52,7 @@ Create variable Edit variable - Value is not a number! + Value must be either number or empty! Variable name clashes with function name! Variable with same name already exists! Name is empty! @@ -84,4 +84,5 @@ Enables/disables colouring and styling in calculator editor Sets the theme for calculator Clear history + Next constants are undefined: {0}! diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java index 217aa17c..c60c30b9 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java @@ -24,6 +24,7 @@ import bsh.EvalError; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.solovyev.android.calculator.model.CalculatorEngine; +import org.solovyev.android.msg.AndroidMessageRegistry; import org.solovyev.android.view.FontSizeAdjuster; import org.solovyev.android.view.widgets.*; 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); + AndroidMessageRegistry.instance.init(this); + this.calculatorModel.evaluate(); } + @Override + protected void onDestroy() { + super.onDestroy(); + + AndroidMessageRegistry.instance.finish(); + } + @Override public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String s) { dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this)); diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java b/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java index 5f21212c..9857d542 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java @@ -26,7 +26,7 @@ public class CalculatorEditor extends EditText { private boolean highlightText = true; @NotNull - private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE); + private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE); public CalculatorEditor(Context context) { super(context); diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java index de1641bb..530fcf07 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java @@ -18,6 +18,7 @@ import android.widget.Toast; import bsh.EvalError; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.ParseException; diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorVarsActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorVarsActivity.java index 2dd5d836..fc0552ca 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorVarsActivity.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorVarsActivity.java @@ -119,7 +119,9 @@ public class CalculatorVarsActivity extends ListActivity { }); final EditText editValue = (EditText) editView.findViewById(R.id.var_edit_value); - editValue.setText(value); + if (!StringUtils.isEmpty(value)) { + editValue.setText(value); + } final EditText editDescription = (EditText) editView.findViewById(R.id.var_edit_description); editDescription.setText(description); @@ -198,20 +200,30 @@ public class CalculatorVarsActivity extends ListActivity { final MathType.Result mathType = MathType.getType(name, 0); if (mathType.getMathType() == MathType.text || mathType.getMathType() == MathType.constant) { - boolean correctDouble = true; - try { - Double.valueOf(value); - } catch (NumberFormatException e) { - correctDouble = false; - } - if (correctDouble) { + if (StringUtils.isEmpty(value)) { + // value is empty => undefined variable varBuilder.setName(name); - varBuilder.setValue(value); varBuilder.setDescription(description); + varBuilder.setValue(null); error = null; } else { - error = R.string.c_value_is_not_a_number; + // value is not empty => must be a number + boolean correctDouble = true; + try { + Double.valueOf(value); + } catch (NumberFormatException e) { + correctDouble = false; + } + + if (correctDouble) { + varBuilder.setName(name); + varBuilder.setDescription(description); + varBuilder.setValue(value); + error = null; + } else { + error = R.string.c_value_is_not_a_number; + } } } else { error = R.string.c_var_name_clashes; diff --git a/src/main/java/org/solovyev/android/calculator/JsclOperation.java b/src/main/java/org/solovyev/android/calculator/JsclOperation.java deleted file mode 100644 index 2bdfcd61..00000000 --- a/src/main/java/org/solovyev/android/calculator/JsclOperation.java +++ /dev/null @@ -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; - -} diff --git a/src/main/java/org/solovyev/android/calculator/TextHighlighter.java b/src/main/java/org/solovyev/android/calculator/TextHighlighter.java index 2b8364ac..72711aef 100644 --- a/src/main/java/org/solovyev/android/calculator/TextHighlighter.java +++ b/src/main/java/org/solovyev/android/calculator/TextHighlighter.java @@ -17,7 +17,7 @@ import org.solovyev.android.calculator.model.TextProcessor; * Date: 10/12/11 * Time: 9:47 PM */ -public class TextHighlighter implements TextProcessor { +public class TextHighlighter implements TextProcessor { private final int color; private final int colorRed; diff --git a/src/main/java/org/solovyev/android/calculator/model/FromJsclTextProcessor.java b/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java similarity index 87% rename from src/main/java/org/solovyev/android/calculator/model/FromJsclTextProcessor.java rename to src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java index 2071e515..3809f4fe 100644 --- a/src/main/java/org/solovyev/android/calculator/model/FromJsclTextProcessor.java +++ b/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java @@ -4,10 +4,13 @@ * 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.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.util.math.Complex; @@ -16,7 +19,7 @@ import org.solovyev.util.math.Complex; * Date: 10/6/11 * Time: 9:48 PM */ -class FromJsclTextProcessor implements TextProcessor { +class FromJsclNumericTextProcessor implements TextProcessor { @NotNull @Override diff --git a/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java b/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java new file mode 100644 index 00000000..e12ebdd0 --- /dev/null +++ b/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java @@ -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 fromProcessor; + + JsclOperation(@NotNull TextProcessor fromProcessor) { + this.fromProcessor = fromProcessor; + } + + @NotNull + public TextProcessor getFromProcessor() { + return fromProcessor; + } +} diff --git a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java index cc14d9af..97daf5d5 100644 --- a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java +++ b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java @@ -11,8 +11,14 @@ import bsh.EvalError; import bsh.Interpreter; import org.jetbrains.annotations.NotNull; 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.msg.MessageRegistry; +import org.solovyev.common.msg.MessageType; +import org.solovyev.common.utils.CollectionsUtils; +import org.solovyev.common.utils.Formatter; /** * User: serso @@ -36,25 +42,46 @@ public enum CalculatorEngine { private int numberOfFractionDigits = 5; @NotNull - public final TextProcessor preprocessor = new ToJsclTextProcessor(); - - @NotNull - public final TextProcessor postprocessor = new FromJsclTextProcessor(); + public final TextProcessor preprocessor = new ToJsclTextProcessor(); @NotNull 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 mr) throws EvalError, ParseException { synchronized (lock) { 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); + if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) { + operation = JsclOperation.simplify; + + if (mr != null) { + final String undefinedVars = CollectionsUtils.formatValue(preparedExpression.getUndefinedVars(), ", ", new Formatter() { + @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())); - return postprocessor.process(String.valueOf(evaluationObject).trim()); + final String result = String.valueOf(evaluationObject).trim(); + + return operation.getFromProcessor().process(result); } } diff --git a/src/main/java/org/solovyev/android/calculator/model/DummyTextProcessor.java b/src/main/java/org/solovyev/android/calculator/model/DummyTextProcessor.java new file mode 100644 index 00000000..bad92e21 --- /dev/null +++ b/src/main/java/org/solovyev/android/calculator/model/DummyTextProcessor.java @@ -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 { + + instance; + + @NotNull + @Override + public String process(@NotNull String s) throws ParseException { + return s.replace(ToJsclTextProcessor.SPECIAL_STRING, ""); + } +} diff --git a/src/main/java/org/solovyev/android/calculator/model/PreparedExpression.java b/src/main/java/org/solovyev/android/calculator/model/PreparedExpression.java new file mode 100644 index 00000000..820ae664 --- /dev/null +++ b/src/main/java/org/solovyev/android/calculator/model/PreparedExpression.java @@ -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 undefinedVars; + + public PreparedExpression(@NotNull String expression, @NotNull List undefinedVars) { + this.expression = expression; + this.undefinedVars = undefinedVars; + } + + @NotNull + public String getExpression() { + return expression; + } + + public boolean isExistsUndefinedVar() { + return !this.undefinedVars.isEmpty(); + } + + @NotNull + public List 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; + } +} diff --git a/src/main/java/org/solovyev/android/calculator/model/TextProcessor.java b/src/main/java/org/solovyev/android/calculator/model/TextProcessor.java index 082cd196..d89a69b2 100644 --- a/src/main/java/org/solovyev/android/calculator/model/TextProcessor.java +++ b/src/main/java/org/solovyev/android/calculator/model/TextProcessor.java @@ -7,8 +7,8 @@ import org.jetbrains.annotations.NotNull; * Date: 9/26/11 * Time: 12:12 PM */ -public interface TextProcessor { +public interface TextProcessor { @NotNull - String process(@NotNull String s) throws ParseException; + T process(@NotNull String s) throws ParseException; } diff --git a/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java b/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java index 675fbe13..ddb9c39c 100644 --- a/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java +++ b/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java @@ -8,7 +8,7 @@ package org.solovyev.android.calculator.model; import org.jetbrains.annotations.NotNull; 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.math.Functions; 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.Finder; -class ToJsclTextProcessor implements TextProcessor { +import java.util.ArrayList; +import java.util.List; + +class ToJsclTextProcessor implements TextProcessor { + + public static final String SPECIAL_STRING = "☀☀☀"; @Override @NotNull - public String process(@NotNull String s) { + public PreparedExpression process(@NotNull String s) { final StartsWithFinder startsWithFinder = new StartsWithFinder(s, 0); final StringBuilder sb = new StringBuilder(); @@ -47,7 +52,7 @@ class ToJsclTextProcessor implements TextProcessor { startsWithFinder.setI(i + 1); if ( i < s.length() && CollectionsUtils.get(MathType.groupSymbols, startsWithFinder) != null) { i += 2; - sb.append("(foo)"); + sb.append("(" + SPECIAL_STRING + ")"); mathTypeResult = new MathType.Result(MathType.close_group_symbol, ")"); } } else if (mathType == MathType.constant) { @@ -61,9 +66,12 @@ class ToJsclTextProcessor implements TextProcessor { 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 List undefinedVars = new ArrayList(); + final StringBuilder result = new StringBuilder(); for (int i = 0; i < s.length(); i++) { startsWithFinder.setI(i); @@ -75,8 +83,14 @@ class ToJsclTextProcessor implements TextProcessor { if (varName != null) { final Var var = CalculatorEngine.instance.getVarsRegister().getVar(varName); if (var != null) { - result.append(var.getValue()); - offset = varName.length(); + if (var.isUndefined()) { + undefinedVars.add(var); + result.append(varName); + offset = varName.length(); + } else { + result.append(var.getValue()); + offset = varName.length(); + } } } } else { @@ -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) { diff --git a/src/main/java/org/solovyev/android/calculator/model/Var.java b/src/main/java/org/solovyev/android/calculator/model/Var.java index 8abe5137..66232167 100644 --- a/src/main/java/org/solovyev/android/calculator/model/Var.java +++ b/src/main/java/org/solovyev/android/calculator/model/Var.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.simpleframework.xml.Element; import org.simpleframework.xml.Root; +import org.solovyev.common.utils.StringUtils; /** * User: serso @@ -24,8 +25,8 @@ public class Var { @NotNull private String name; - @Element - @NotNull + @Element(required = false) + @Nullable private String value; @Element @@ -40,7 +41,7 @@ public class Var { @NotNull private String name; - @NotNull + @Nullable private String value; private boolean system = false; @@ -62,7 +63,7 @@ public class Var { 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.value = value; } @@ -71,7 +72,7 @@ public class Var { this.name = name; } - public void setValue(@NotNull String value) { + public void setValue(@Nullable String value) { this.value = value; } @@ -107,7 +108,7 @@ public class Var { this.system = var.system; } - @NotNull + @Nullable public String getValue() { return value; } @@ -121,18 +122,22 @@ public class Var { return name; } + public boolean isUndefined() { + return StringUtils.isEmpty(this.value); + } + @Nullable public String getDescription() { return description; } - public void setDescription(@Nullable String description) { - this.description = description; - } - @Override public String toString() { - return getName() + " = " + value; + if (value != null) { + return getName() + " = " + value; + } else { + return getName(); + } } @Override diff --git a/src/main/java/org/solovyev/android/msg/AndroidMessage.java b/src/main/java/org/solovyev/android/msg/AndroidMessage.java new file mode 100644 index 00000000..36aec500 --- /dev/null +++ b/src/main/java/org/solovyev/android/msg/AndroidMessage.java @@ -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 { + + 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); + } +} diff --git a/src/main/java/org/solovyev/android/msg/AndroidMessageRegistry.java b/src/main/java/org/solovyev/android/msg/AndroidMessageRegistry.java new file mode 100644 index 00000000..64e950f8 --- /dev/null +++ b/src/main/java/org/solovyev/android/msg/AndroidMessageRegistry.java @@ -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 { + + 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; + } +} diff --git a/src/test/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessorTest.java b/src/test/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessorTest.java new file mode 100644 index 00000000..1ad6633a --- /dev/null +++ b/src/test/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessorTest.java @@ -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")); + } +} diff --git a/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java b/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java index 73e885bb..857cbd03 100644 --- a/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java +++ b/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java @@ -10,7 +10,7 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.simpleframework.xml.Attribute; -import org.solovyev.android.calculator.JsclOperation; +import org.solovyev.android.calculator.jscl.JsclOperation; /** * 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("k1", 4d)); 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 {