plotting added
This commit is contained in:
parent
9867ca9949
commit
731e178b51
@ -68,5 +68,10 @@
|
|||||||
a:configChanges="orientation|keyboardHidden">
|
a:configChanges="orientation|keyboardHidden">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity a:name=".CalculatorPlotActivity"
|
||||||
|
a:label="@string/c_plot_graph"
|
||||||
|
a:configChanges="orientation|keyboardHidden">
|
||||||
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
31
res/layout/display_error_message.xml
Normal file
31
res/layout/display_error_message.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ 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
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ScrollView xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:orientation="vertical"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="fill_parent"
|
||||||
|
a:scrollbars="vertical"
|
||||||
|
a:scrollbarAlwaysDrawVerticalTrack="true">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:id="@+id/error_message_text_view"
|
||||||
|
a:layout_height="fill_parent"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:padding="6dp"
|
||||||
|
style="@style/default_text_size"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
@ -276,4 +276,6 @@ Check the \'Round result\' preference in application settings - it should be tur
|
|||||||
<string name="msg_5">No parameters are specified for function: {0}</string>
|
<string name="msg_5">No parameters are specified for function: {0}</string>
|
||||||
<string name="msg_6">Infinite loop is detected in expression</string>
|
<string name="msg_6">Infinite loop is detected in expression</string>
|
||||||
|
|
||||||
|
<string name="c_plot_graph">Graph</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -3,6 +3,19 @@ package org.solovyev.android.calculator;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import jscl.math.Expression;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.JsclInteger;
|
||||||
|
import jscl.math.NumericWrapper;
|
||||||
|
import jscl.math.function.Constant;
|
||||||
|
import jscl.math.numeric.Complex;
|
||||||
|
import jscl.math.numeric.Numeric;
|
||||||
|
import jscl.math.numeric.Real;
|
||||||
|
import org.achartengine.ChartFactory;
|
||||||
|
import org.achartengine.model.XYMultipleSeriesDataset;
|
||||||
|
import org.achartengine.model.XYSeries;
|
||||||
|
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||||
|
import org.achartengine.renderer.XYSeriesRenderer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.help.HelpActivity;
|
import org.solovyev.android.calculator.help.HelpActivity;
|
||||||
import org.solovyev.common.utils.StringUtils;
|
import org.solovyev.common.utils.StringUtils;
|
||||||
@ -42,6 +55,48 @@ public class CalculatorActivityLauncher {
|
|||||||
context.startActivity(new Intent(context, CalculatorVarsActivity.class));
|
context.startActivity(new Intent(context, CalculatorVarsActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void plotGraph(@NotNull final Context context, @NotNull Generic generic, @NotNull Constant constant) throws ArithmeticException {
|
||||||
|
|
||||||
|
final XYSeries series = new XYSeries(generic.toString());
|
||||||
|
|
||||||
|
final double min = -10;
|
||||||
|
final double max = 10;
|
||||||
|
final double step = 0.5;
|
||||||
|
double x = min;
|
||||||
|
while (x <= max) {
|
||||||
|
Generic numeric = generic.substitute(constant, Expression.valueOf(x)).numeric();
|
||||||
|
series.add(x, unwrap(numeric));
|
||||||
|
x += step;
|
||||||
|
}
|
||||||
|
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
|
||||||
|
data.addSeries(series);
|
||||||
|
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
|
||||||
|
renderer.addSeriesRenderer(new XYSeriesRenderer());
|
||||||
|
final Intent intent = ChartFactory.getLineChartIntent(context, data, renderer);
|
||||||
|
intent.setClass(context, CalculatorPlotActivity.class);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double unwrap(Generic numeric) {
|
||||||
|
if ( numeric instanceof JsclInteger) {
|
||||||
|
return ((JsclInteger) numeric).intValue();
|
||||||
|
} else if ( numeric instanceof NumericWrapper ) {
|
||||||
|
return unwrap(((NumericWrapper) numeric).content());
|
||||||
|
} else {
|
||||||
|
throw new ArithmeticException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double unwrap(Numeric content) {
|
||||||
|
if (content instanceof Real) {
|
||||||
|
return ((Real) content).doubleValue();
|
||||||
|
} else if ( content instanceof Complex) {
|
||||||
|
return ((Complex) content).realPart();
|
||||||
|
} else {
|
||||||
|
throw new ArithmeticException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void createVar(@NotNull final Context context, @NotNull CalculatorModel calculatorModel) {
|
public static void createVar(@NotNull final Context context, @NotNull CalculatorModel calculatorModel) {
|
||||||
if (calculatorModel.getDisplay().isValid() ) {
|
if (calculatorModel.getDisplay().isValid() ) {
|
||||||
final String varValue = calculatorModel.getDisplay().getText().toString();
|
final String varValue = calculatorModel.getDisplay().getText().toString();
|
||||||
|
@ -10,6 +10,7 @@ import android.graphics.Color;
|
|||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import jscl.math.Generic;
|
||||||
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.jscl.JsclOperation;
|
||||||
@ -35,6 +36,9 @@ public class CalculatorDisplay extends AutoResizeTextView {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final static TextProcessor<TextHighlighter.Result> textHighlighter = new TextHighlighter(Color.WHITE, true);
|
private final static TextProcessor<TextHighlighter.Result> textHighlighter = new TextHighlighter(Color.WHITE, true);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Generic genericResult;
|
||||||
|
|
||||||
public CalculatorDisplay(Context context) {
|
public CalculatorDisplay(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
@ -106,4 +110,12 @@ public class CalculatorDisplay extends AutoResizeTextView {
|
|||||||
resizeText();
|
resizeText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGenericResult(@Nullable Generic genericResult) {
|
||||||
|
this.genericResult = genericResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Generic getGenericResult() {
|
||||||
|
return genericResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
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.jscl.JsclOperation;
|
||||||
@ -27,6 +28,9 @@ public class CalculatorDisplayHistoryState {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private JsclOperation jsclOperation;
|
private JsclOperation jsclOperation;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Generic genericResult;
|
||||||
|
|
||||||
private CalculatorDisplayHistoryState() {
|
private CalculatorDisplayHistoryState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +41,7 @@ public class CalculatorDisplayHistoryState {
|
|||||||
result.editorHistoryState = EditorHistoryState.newInstance(display);
|
result.editorHistoryState = EditorHistoryState.newInstance(display);
|
||||||
result.valid = display.isValid();
|
result.valid = display.isValid();
|
||||||
result.jsclOperation = display.getJsclOperation();
|
result.jsclOperation = display.getJsclOperation();
|
||||||
|
result.genericResult = display.getGenericResult();
|
||||||
result.errorMessage = display.getErrorMessage();
|
result.errorMessage = display.getErrorMessage();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -61,6 +66,11 @@ public class CalculatorDisplayHistoryState {
|
|||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Generic getGenericResult() {
|
||||||
|
return genericResult;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -12,23 +12,31 @@ import android.content.SharedPreferences;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.text.ClipboardManager;
|
import android.text.ClipboardManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.function.Constant;
|
||||||
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.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;
|
||||||
|
import org.solovyev.android.calculator.model.Var;
|
||||||
import org.solovyev.android.view.CursorControl;
|
import org.solovyev.android.view.CursorControl;
|
||||||
import org.solovyev.android.view.HistoryControl;
|
import org.solovyev.android.view.HistoryControl;
|
||||||
import org.solovyev.common.BooleanMapper;
|
import org.solovyev.common.BooleanMapper;
|
||||||
|
import org.solovyev.common.utils.CollectionsUtils;
|
||||||
import org.solovyev.common.utils.MutableObject;
|
import org.solovyev.common.utils.MutableObject;
|
||||||
import org.solovyev.common.utils.StringUtils;
|
import org.solovyev.common.utils.StringUtils;
|
||||||
import org.solovyev.common.utils.history.HistoryAction;
|
import org.solovyev.common.utils.history.HistoryAction;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 9/12/11
|
* Date: 9/12/11
|
||||||
@ -67,7 +75,42 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
if (v instanceof CalculatorDisplay) {
|
if (v instanceof CalculatorDisplay) {
|
||||||
final CalculatorDisplay cd = (CalculatorDisplay)v;
|
final CalculatorDisplay cd = (CalculatorDisplay)v;
|
||||||
if (cd.isValid()) {
|
if (cd.isValid()) {
|
||||||
copyResult(activity, cd);
|
switch (cd.getJsclOperation()) {
|
||||||
|
case simplify:
|
||||||
|
Generic genericResult = cd.getGenericResult();
|
||||||
|
if ( genericResult != null ) {
|
||||||
|
final Set<Constant> notSystemConstants = new HashSet<Constant>();
|
||||||
|
for (Constant constant : genericResult.getConstants()) {
|
||||||
|
Var var = CalculatorEngine.instance.getVarsRegister().get(constant.getName());
|
||||||
|
if (var != null && !var.isSystem()) {
|
||||||
|
notSystemConstants.add(constant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( notSystemConstants.size() > 0 ) {
|
||||||
|
if (notSystemConstants.size() > 1) {
|
||||||
|
copyResult(activity, cd);
|
||||||
|
} else {
|
||||||
|
final Constant constant = CollectionsUtils.getFirstCollectionElement(notSystemConstants);
|
||||||
|
assert constant != null;
|
||||||
|
try {
|
||||||
|
CalculatorActivityLauncher.plotGraph(activity, genericResult, constant);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
copyResult(activity, cd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
copyResult(activity, cd);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
copyResult(activity, cd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case elementary:
|
||||||
|
case numeric:
|
||||||
|
copyResult(activity, cd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
final String errorMessage = cd.getErrorMessage();
|
final String errorMessage = cd.getErrorMessage();
|
||||||
if ( errorMessage != null ) {
|
if ( errorMessage != null ) {
|
||||||
@ -91,11 +134,14 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) {
|
private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) {
|
||||||
final TextView errorMessageTextView = new TextView(activity);
|
final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
||||||
errorMessageTextView.setText(errorMessage);
|
|
||||||
|
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
|
||||||
|
((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
|
||||||
|
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
||||||
.setPositiveButton(R.string.c_cancel, null)
|
.setPositiveButton(R.string.c_cancel, null)
|
||||||
.setView(errorMessageTextView);
|
.setView(errorMessageView);
|
||||||
|
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
@ -104,9 +150,9 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
copyResult(context, display);
|
copyResult(context, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyResult(@NotNull Context context, @NotNull final CalculatorDisplay display) {
|
public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplay display) {
|
||||||
if (display.isValid()) {
|
if (display.isValid()) {
|
||||||
final CharSequence text = this.display.getText();
|
final CharSequence text = display.getText();
|
||||||
if (!StringUtils.isEmpty(text)) {
|
if (!StringUtils.isEmpty(text)) {
|
||||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||||
clipboard.setText(text.toString());
|
clipboard.setText(text.toString());
|
||||||
@ -238,12 +284,14 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
display.setText("");
|
display.setText("");
|
||||||
}
|
}
|
||||||
display.setJsclOperation(result.getUserOperation());
|
display.setJsclOperation(result.getUserOperation());
|
||||||
|
display.setGenericResult(result.getGenericResult());
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
handleEvaluationException(expression, display, operation, e);
|
handleEvaluationException(expression, display, operation, e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.display.setText("");
|
this.display.setText("");
|
||||||
this.display.setJsclOperation(operation);
|
this.display.setJsclOperation(operation);
|
||||||
|
this.display.setGenericResult(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -258,6 +306,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e.getMessage());
|
Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e.getMessage());
|
||||||
localDisplay.setText(R.string.c_syntax_error);
|
localDisplay.setText(R.string.c_syntax_error);
|
||||||
localDisplay.setJsclOperation(operation);
|
localDisplay.setJsclOperation(operation);
|
||||||
|
localDisplay.setGenericResult(null);
|
||||||
localDisplay.setValid(false);
|
localDisplay.setValid(false);
|
||||||
localDisplay.setErrorMessage(e.getLocalizedMessage());
|
localDisplay.setErrorMessage(e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
@ -355,6 +404,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
display.setValid(editorHistoryState.isValid());
|
display.setValid(editorHistoryState.isValid());
|
||||||
display.setErrorMessage(editorHistoryState.getErrorMessage());
|
display.setErrorMessage(editorHistoryState.getErrorMessage());
|
||||||
display.setJsclOperation(editorHistoryState.getJsclOperation());
|
display.setJsclOperation(editorHistoryState.getJsclOperation());
|
||||||
|
display.setGenericResult(editorHistoryState.getGenericResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setValuesFromHistory(@NotNull TextView editText, EditorHistoryState editorHistoryState) {
|
private void setValuesFromHistory(@NotNull TextView editText, EditorHistoryState editorHistoryState) {
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.achartengine.GraphicalActivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 12/1/11
|
||||||
|
* Time: 12:40 AM
|
||||||
|
*/
|
||||||
|
public class CalculatorPlotActivity extends GraphicalActivity{
|
||||||
|
}
|
@ -19,6 +19,7 @@ import android.widget.*;
|
|||||||
import jscl.text.Identifier;
|
import jscl.text.Identifier;
|
||||||
import jscl.text.MutableInt;
|
import jscl.text.MutableInt;
|
||||||
import jscl.text.ParseException;
|
import jscl.text.ParseException;
|
||||||
|
import jscl.text.Parser;
|
||||||
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.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
@ -301,7 +302,7 @@ public class CalculatorVarsActivity extends ListActivity {
|
|||||||
|
|
||||||
if (!StringUtils.isEmpty(name)) {
|
if (!StringUtils.isEmpty(name)) {
|
||||||
try {
|
try {
|
||||||
Identifier.parser.parse(name, new MutableInt(0), null);
|
Identifier.parser.parse(Parser.Parameters.newInstance(name, new MutableInt(0), CalculatorEngine.instance.getEngine()), null);
|
||||||
result = true;
|
result = true;
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
// not valid name;
|
// not valid name;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package org.solovyev.android.calculator.jscl;
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
import jscl.text.ParseException;
|
import jscl.text.ParseException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
@ -21,6 +22,12 @@ public enum JsclOperation {
|
|||||||
public String evaluate(@NotNull String expression) throws ParseException {
|
public String evaluate(@NotNull String expression) throws ParseException {
|
||||||
return CalculatorEngine.instance.getEngine().simplify(expression);
|
return CalculatorEngine.instance.getEngine().simplify(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Generic evaluateGeneric(@NotNull String expression) throws ParseException {
|
||||||
|
return CalculatorEngine.instance.getEngine().simplifyGeneric(expression);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
elementary(DummyTextProcessor.instance) {
|
elementary(DummyTextProcessor.instance) {
|
||||||
@ -30,6 +37,12 @@ public enum JsclOperation {
|
|||||||
return CalculatorEngine.instance.getEngine().elementary(expression);
|
return CalculatorEngine.instance.getEngine().elementary(expression);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Generic evaluateGeneric(@NotNull String expression) throws ParseException {
|
||||||
|
return CalculatorEngine.instance.getEngine().elementaryGeneric(expression);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
numeric(new FromJsclNumericTextProcessor()) {
|
numeric(new FromJsclNumericTextProcessor()) {
|
||||||
@ -38,6 +51,12 @@ public enum JsclOperation {
|
|||||||
public String evaluate(@NotNull String expression) throws ParseException {
|
public String evaluate(@NotNull String expression) throws ParseException {
|
||||||
return CalculatorEngine.instance.getEngine().evaluate(expression);
|
return CalculatorEngine.instance.getEngine().evaluate(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Generic evaluateGeneric(@NotNull String expression) throws ParseException {
|
||||||
|
return CalculatorEngine.instance.getEngine().evaluateGeneric(expression);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -54,4 +73,9 @@ public enum JsclOperation {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public abstract String evaluate(@NotNull String expression) throws ParseException;
|
public abstract String evaluate(@NotNull String expression) throws ParseException;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public abstract Generic evaluateGeneric(@NotNull String expression) throws ParseException;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import java.util.*;
|
|||||||
|
|
||||||
public enum MathType {
|
public enum MathType {
|
||||||
|
|
||||||
numeral_base(50, true, false) {
|
/* numeral_base(50, true, false) {
|
||||||
|
|
||||||
private final List<String> tokens = new ArrayList<String>(10);
|
private final List<String> tokens = new ArrayList<String>(10);
|
||||||
{
|
{
|
||||||
@ -37,7 +37,7 @@ public enum MathType {
|
|||||||
public List<String> getTokens() {
|
public List<String> getTokens() {
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
},
|
},*/
|
||||||
|
|
||||||
dot(200, true, true, ".") {
|
dot(200, true, true, ".") {
|
||||||
@Override
|
@Override
|
||||||
@ -138,7 +138,7 @@ public enum MathType {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
||||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot && mathTypeBefore != numeral_base;
|
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot /*&& mathTypeBefore != numeral_base*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -10,13 +10,13 @@ import android.content.SharedPreferences;
|
|||||||
import jscl.AngleUnit;
|
import jscl.AngleUnit;
|
||||||
import jscl.JsclMathEngine;
|
import jscl.JsclMathEngine;
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
|
import jscl.math.Generic;
|
||||||
import jscl.math.function.Function;
|
import jscl.math.function.Function;
|
||||||
import jscl.math.operator.Operator;
|
import jscl.math.operator.Operator;
|
||||||
import jscl.text.ParseInterruptedException;
|
import jscl.text.ParseInterruptedException;
|
||||||
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.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.MessageRegistry;
|
||||||
import org.solovyev.common.utils.MutableObject;
|
import org.solovyev.common.utils.MutableObject;
|
||||||
@ -50,6 +50,7 @@ public enum CalculatorEngine {
|
|||||||
|
|
||||||
public static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units";
|
public static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units";
|
||||||
public static final String ANGLE_UNITS_DEFAULT = "deg";
|
public static final String ANGLE_UNITS_DEFAULT = "deg";
|
||||||
|
public static final int DEFAULT_TIMEOUT = 3000;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
@ -89,7 +90,7 @@ public enum CalculatorEngine {
|
|||||||
private ThreadKiller threadKiller = new AndroidThreadKiller();
|
private ThreadKiller threadKiller = new AndroidThreadKiller();
|
||||||
|
|
||||||
// calculation thread timeout in milliseconds, after timeout thread would be interrupted
|
// calculation thread timeout in milliseconds, after timeout thread would be interrupted
|
||||||
private int timeout = 3000;
|
private int timeout = DEFAULT_TIMEOUT;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String format(@NotNull Double value) {
|
public String format(@NotNull Double value) {
|
||||||
@ -118,15 +119,20 @@ public enum CalculatorEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Result {
|
public static class Result {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Generic genericResult;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String result;
|
private String result;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsclOperation userOperation;
|
private JsclOperation userOperation;
|
||||||
|
|
||||||
public Result(@NotNull String result, @NotNull JsclOperation userOperation) {
|
public Result(@NotNull String result, @NotNull JsclOperation userOperation, @NotNull Generic genericResult) {
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.userOperation = userOperation;
|
this.userOperation = userOperation;
|
||||||
|
this.genericResult = genericResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -138,6 +144,11 @@ public enum CalculatorEngine {
|
|||||||
public JsclOperation getUserOperation() {
|
public JsclOperation getUserOperation() {
|
||||||
return userOperation;
|
return userOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Generic getGenericResult() {
|
||||||
|
return genericResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result evaluate(@NotNull JsclOperation operation,
|
public Result evaluate(@NotNull JsclOperation operation,
|
||||||
@ -174,7 +185,7 @@ public enum CalculatorEngine {
|
|||||||
final JsclOperation finalOperation = operation;
|
final JsclOperation finalOperation = operation;
|
||||||
|
|
||||||
final String result;
|
final String result;
|
||||||
final MutableObject<String> calculationResult = new MutableObject<String>(null);
|
final MutableObject<Generic> calculationResult = new MutableObject<Generic>(null);
|
||||||
final MutableObject<ParseException> exception = new MutableObject<ParseException>(null);
|
final MutableObject<ParseException> exception = new MutableObject<ParseException>(null);
|
||||||
final MutableObject<Thread> calculationThread = new MutableObject<Thread>(null);
|
final MutableObject<Thread> calculationThread = new MutableObject<Thread>(null);
|
||||||
|
|
||||||
@ -188,7 +199,7 @@ public enum CalculatorEngine {
|
|||||||
//Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName());
|
//Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName());
|
||||||
//System.out.println(jsclExpression);
|
//System.out.println(jsclExpression);
|
||||||
calculationThread.setObject(thread);
|
calculationThread.setObject(thread);
|
||||||
calculationResult.setObject(finalOperation.evaluate(jsclExpression));
|
calculationResult.setObject(finalOperation.evaluateGeneric(jsclExpression));
|
||||||
} catch (ArithmeticException e) {
|
} catch (ArithmeticException e) {
|
||||||
//System.out.println(e.getMessage());
|
//System.out.println(e.getMessage());
|
||||||
exception.setObject(new ParseException(Messages.msg_1, jsclExpression, e.getMessage()));
|
exception.setObject(new ParseException(Messages.msg_1, jsclExpression, e.getMessage()));
|
||||||
@ -239,9 +250,9 @@ public enum CalculatorEngine {
|
|||||||
throw new ParseException(Messages.msg_4, jsclExpression);
|
throw new ParseException(Messages.msg_4, jsclExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = String.valueOf(calculationResult.getObject()).trim();
|
final Generic genericResult = calculationResult.getObject();
|
||||||
|
|
||||||
return new Result(operation.getFromProcessor().process(result), operation);
|
return new Result(operation.getFromProcessor().process(genericResult.toString()), operation, genericResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
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.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
@ -31,9 +30,9 @@ public class NumberBuilder {
|
|||||||
|
|
||||||
private final boolean simpleFormat;
|
private final boolean simpleFormat;
|
||||||
|
|
||||||
@Nullable
|
/*@Nullable
|
||||||
private NumeralBase nb;
|
private NumeralBase nb;
|
||||||
|
*/
|
||||||
public NumberBuilder(boolean simpleFormat) {
|
public NumberBuilder(boolean simpleFormat) {
|
||||||
this.simpleFormat = simpleFormat;
|
this.simpleFormat = simpleFormat;
|
||||||
}
|
}
|
||||||
@ -43,17 +42,17 @@ public class NumberBuilder {
|
|||||||
number = null;
|
number = null;
|
||||||
|
|
||||||
final MathType.Result possibleResult;
|
final MathType.Result possibleResult;
|
||||||
if ((CollectionsUtils.contains(mathTypeResult.getMathType(), MathType.digit, MathType.numeral_base, MathType.dot, MathType.grouping_separator, MathType.power_10) ||
|
if ((CollectionsUtils.contains(mathTypeResult.getMathType(), MathType.digit, /*MathType.numeral_base,*/ MathType.dot, MathType.grouping_separator, MathType.power_10) ||
|
||||||
isSignAfterE(mathTypeResult)) && numeralBaseCheck(mathTypeResult)) {
|
isSignAfterE(mathTypeResult)) && numeralBaseCheck(mathTypeResult)) {
|
||||||
if (numberBuilder == null) {
|
if (numberBuilder == null) {
|
||||||
numberBuilder = new StringBuilder();
|
numberBuilder = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
/*if (mathTypeResult.getMathType() != MathType.numeral_base) {*/
|
||||||
numberBuilder.append(mathTypeResult.getMatch());
|
numberBuilder.append(mathTypeResult.getMatch());
|
||||||
} else {
|
/*} else {
|
||||||
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
||||||
}
|
}*/
|
||||||
|
|
||||||
possibleResult = null;
|
possibleResult = null;
|
||||||
} else {
|
} else {
|
||||||
@ -64,7 +63,7 @@ public class NumberBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean numeralBaseCheck( @NotNull MathType.Result mathType ) {
|
private boolean numeralBaseCheck( @NotNull MathType.Result mathType ) {
|
||||||
if ( mathType.getMathType() == MathType.digit ) {
|
/*if ( mathType.getMathType() == MathType.digit ) {
|
||||||
final Character ch = mathType.getMatch().charAt(0);
|
final Character ch = mathType.getMatch().charAt(0);
|
||||||
if ( NumeralBase.hex.getAcceptableCharacters().contains(ch) && !NumeralBase.dec.getAcceptableCharacters().contains(ch) ) {
|
if ( NumeralBase.hex.getAcceptableCharacters().contains(ch) && !NumeralBase.dec.getAcceptableCharacters().contains(ch) ) {
|
||||||
if ( nb == NumeralBase.hex ) {
|
if ( nb == NumeralBase.hex ) {
|
||||||
@ -77,7 +76,8 @@ public class NumberBuilder {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSignAfterE(@NotNull MathType.Result mathTypeResult) {
|
private boolean isSignAfterE(@NotNull MathType.Result mathTypeResult) {
|
||||||
@ -113,7 +113,7 @@ public class NumberBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
numberBuilder = null;
|
numberBuilder = null;
|
||||||
nb = null;
|
/*nb = null;*/
|
||||||
} else {
|
} else {
|
||||||
number = null;
|
number = null;
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,12 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
|
|||||||
final StringBuilder result = new StringBuilder();
|
final StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
MathType.Result mathTypeResult = null;
|
MathType.Result mathTypeResult = null;
|
||||||
MathType mathTypeBefore;
|
MathType.Result mathTypeBefore = null;
|
||||||
|
|
||||||
for (int i = 0; i < s.length(); i++) {
|
for (int i = 0; i < s.length(); i++) {
|
||||||
startsWithFinder.setI(i);
|
startsWithFinder.setI(i);
|
||||||
|
|
||||||
mathTypeBefore = mathTypeResult == null ? null : mathTypeResult.getMathType();
|
mathTypeBefore = mathTypeResult == null ? null : mathTypeResult;
|
||||||
|
|
||||||
mathTypeResult = MathType.getType(s, i);
|
mathTypeResult = MathType.getType(s, i);
|
||||||
|
|
||||||
@ -49,13 +49,15 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
|
|||||||
|
|
||||||
final MathType current = mathTypeResult.getMathType();
|
final MathType current = mathTypeResult.getMathType();
|
||||||
|
|
||||||
if (current.isNeedMultiplicationSignBefore(mathTypeBefore)) {
|
if (current.isNeedMultiplicationSignBefore(mathTypeBefore.getMathType())) {
|
||||||
result.append("*");
|
result.append("*");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mathTypeBefore == MathType.function || mathTypeBefore == MathType.operator) && CollectionsUtils.find(MathType.openGroupSymbols, startsWithFinder) != null) {
|
if (mathTypeBefore != null &&
|
||||||
throw new ParseException(Messages.msg_5, i, s, mathTypeResult.getMatch());
|
(mathTypeBefore.getMathType() == MathType.function || mathTypeBefore.getMathType() == MathType.operator) &&
|
||||||
|
CollectionsUtils.find(MathType.openGroupSymbols, startsWithFinder) != null) {
|
||||||
|
throw new ParseException(Messages.msg_5, i, s, mathTypeBefore.getMatch());
|
||||||
}
|
}
|
||||||
|
|
||||||
i = mathTypeResult.processToJscl(result, i);
|
i = mathTypeResult.processToJscl(result, i);
|
||||||
|
Loading…
Reference in New Issue
Block a user