Module separation

This commit is contained in:
serso 2012-09-20 13:19:48 +04:00
parent 417cf88912
commit eb37fe495b
29 changed files with 2834 additions and 2815 deletions

View File

@ -35,6 +35,11 @@
<artifactId>jscl</artifactId> <artifactId>jscl</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.simpleframework</groupId>
<artifactId>simple-xml</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@ -4,7 +4,7 @@
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View File

@ -1,81 +1,80 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
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.Transient;
import org.simpleframework.xml.Transient;
import java.util.Date;
import java.util.Date;
/**
/** * User: serso
* User: serso * Date: 10/15/11
* Date: 10/15/11 * Time: 1:45 PM
* Time: 1:45 PM */
*/ public class AbstractHistoryState implements Cloneable{
public class AbstractHistoryState implements Cloneable{
@Element
@Element private long time = new Date().getTime();
private long time = new Date().getTime();
@Element(required = false)
@Element(required = false) @Nullable
@Nullable private String comment;
private String comment;
@Transient
@Transient private boolean saved;
private boolean saved;
@Transient
@Transient private int id = 0;
private int id = 0;
public int getId() {
public int getId() { return id;
return id; }
}
public void setId(int id) {
public void setId(int id) { this.id = id;
this.id = id; }
}
public long getTime() {
public long getTime() { return time;
return time; }
}
public void setTime(long time) {
public void setTime(long time) { this.time = time;
this.time = time; }
}
@Nullable
@Nullable public String getComment() {
public String getComment() { return comment;
return comment; }
}
public void setComment(@Nullable String comment) {
public void setComment(@Nullable String comment) { this.comment = comment;
this.comment = comment; }
}
public boolean isSaved() {
public boolean isSaved() { return saved;
return saved; }
}
public void setSaved(boolean saved) {
public void setSaved(boolean saved) { this.saved = saved;
this.saved = saved; }
}
@Override
@Override protected AbstractHistoryState clone() {
protected AbstractHistoryState clone() { AbstractHistoryState clone;
AbstractHistoryState clone;
try {
try { clone = (AbstractHistoryState)super.clone();
clone = (AbstractHistoryState)super.clone(); } catch (CloneNotSupportedException e) {
} catch (CloneNotSupportedException e) { throw new UnsupportedOperationException(e);
throw new UnsupportedOperationException(e); }
}
return clone;
return clone; }
} }
}

View File

@ -1,138 +1,138 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import jscl.math.Generic; 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.simpleframework.xml.Element; import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root; import org.simpleframework.xml.Root;
import org.simpleframework.xml.Transient; import org.simpleframework.xml.Transient;
import org.solovyev.android.calculator.ICalculatorDisplay; import org.solovyev.android.calculator.ICalculatorDisplay;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
/** /**
* User: serso * User: serso
* Date: 9/17/11 * Date: 9/17/11
* Time: 11:05 PM * Time: 11:05 PM
*/ */
@Root @Root
public class CalculatorDisplayHistoryState implements Cloneable { public class CalculatorDisplayHistoryState implements Cloneable {
@Transient @Transient
private boolean valid = true; private boolean valid = true;
@Transient @Transient
@Nullable @Nullable
private String errorMessage = null; private String errorMessage = null;
@Element @Element
@NotNull @NotNull
private EditorHistoryState editorState; private EditorHistoryState editorState;
@Element @Element
@NotNull @NotNull
private JsclOperation jsclOperation; private JsclOperation jsclOperation;
@Transient @Transient
@Nullable @Nullable
private Generic genericResult; private Generic genericResult;
private CalculatorDisplayHistoryState() { private CalculatorDisplayHistoryState() {
// for xml // for xml
} }
@NotNull @NotNull
public static CalculatorDisplayHistoryState newInstance(@NotNull ICalculatorDisplay display) { public static CalculatorDisplayHistoryState newInstance(@NotNull ICalculatorDisplay display) {
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState(); final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
result.editorState = EditorHistoryState.newInstance(display); result.editorState = EditorHistoryState.newInstance(display);
result.valid = display.isValid(); result.valid = display.isValid();
result.jsclOperation = display.getJsclOperation(); result.jsclOperation = display.getJsclOperation();
result.genericResult = display.getGenericResult(); result.genericResult = display.getGenericResult();
result.errorMessage = display.getErrorMessage(); result.errorMessage = display.getErrorMessage();
return result; return result;
} }
public void setValuesFromHistory(@NotNull ICalculatorDisplay display) { public void setValuesFromHistory(@NotNull ICalculatorDisplay display) {
this.getEditorState().setValuesFromHistory(display); this.getEditorState().setValuesFromHistory(display);
display.setValid(this.isValid()); display.setValid(this.isValid());
display.setErrorMessage(this.getErrorMessage()); display.setErrorMessage(this.getErrorMessage());
display.setJsclOperation(this.getJsclOperation()); display.setJsclOperation(this.getJsclOperation());
display.setGenericResult(this.getGenericResult()); display.setGenericResult(this.getGenericResult());
} }
public boolean isValid() { public boolean isValid() {
return valid; return valid;
} }
@NotNull @NotNull
public EditorHistoryState getEditorState() { public EditorHistoryState getEditorState() {
return editorState; return editorState;
} }
@NotNull @NotNull
public JsclOperation getJsclOperation() { public JsclOperation getJsclOperation() {
return jsclOperation; return jsclOperation;
} }
@Nullable @Nullable
public String getErrorMessage() { public String getErrorMessage() {
return errorMessage; return errorMessage;
} }
@Nullable @Nullable
public Generic getGenericResult() { public Generic getGenericResult() {
return genericResult; return genericResult;
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
CalculatorDisplayHistoryState that = (CalculatorDisplayHistoryState) o; CalculatorDisplayHistoryState that = (CalculatorDisplayHistoryState) o;
if (!editorState.equals(that.editorState)) return false; if (!editorState.equals(that.editorState)) return false;
if (jsclOperation != that.jsclOperation) return false; if (jsclOperation != that.jsclOperation) return false;
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = editorState.hashCode(); int result = editorState.hashCode();
result = 31 * result + jsclOperation.hashCode(); result = 31 * result + jsclOperation.hashCode();
return result; return result;
} }
@Override @Override
public String toString() { public String toString() {
return "CalculatorDisplayHistoryState{" + return "CalculatorDisplayHistoryState{" +
"valid=" + valid + "valid=" + valid +
", errorMessage='" + errorMessage + '\'' + ", errorMessage='" + errorMessage + '\'' +
", editorHistoryState=" + editorState + ", editorHistoryState=" + editorState +
", jsclOperation=" + jsclOperation + ", jsclOperation=" + jsclOperation +
'}'; '}';
} }
@Override @Override
protected CalculatorDisplayHistoryState clone() { protected CalculatorDisplayHistoryState clone() {
try { try {
final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone(); final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone();
clone.editorState = this.editorState.clone(); clone.editorState = this.editorState.clone();
return clone; return clone;
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
} }

View File

@ -1,33 +1,33 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import org.simpleframework.xml.ElementList; import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root; import org.simpleframework.xml.Root;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* User: serso * User: serso
* Date: 12/17/11 * Date: 12/17/11
* Time: 9:30 PM * Time: 9:30 PM
*/ */
@Root @Root
public class History { public class History {
@ElementList @ElementList
private List<CalculatorHistoryState> historyItems = new ArrayList<CalculatorHistoryState>(); private List<CalculatorHistoryState> historyItems = new ArrayList<CalculatorHistoryState>();
public History() { public History() {
} }
public List<CalculatorHistoryState> getHistoryItems() { public List<CalculatorHistoryState> getHistoryItems() {
return historyItems; return historyItems;
} }
} }

View File

@ -1,61 +1,61 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.simpleframework.xml.Serializer; import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister; import org.simpleframework.xml.core.Persister;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.List; import java.util.List;
/** /**
* User: serso * User: serso
* Date: 12/17/11 * Date: 12/17/11
* Time: 9:59 PM * Time: 9:59 PM
*/ */
class HistoryUtils { class HistoryUtils {
// not intended for instantiation // not intended for instantiation
private HistoryUtils() { private HistoryUtils() {
throw new AssertionError(); throw new AssertionError();
} }
public static void fromXml(@Nullable String xml, @NotNull List<CalculatorHistoryState> historyItems) { public static void fromXml(@Nullable String xml, @NotNull List<CalculatorHistoryState> historyItems) {
if (xml != null) { if (xml != null) {
final Serializer serializer = new Persister(); final Serializer serializer = new Persister();
try { try {
final History history = serializer.read(History.class, xml); final History history = serializer.read(History.class, xml);
for (CalculatorHistoryState historyItem : history.getHistoryItems()) { for (CalculatorHistoryState historyItem : history.getHistoryItems()) {
historyItems.add(historyItem); historyItems.add(historyItem);
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
} }
@NotNull @NotNull
public static String toXml(@NotNull List<CalculatorHistoryState> historyItems) { public static String toXml(@NotNull List<CalculatorHistoryState> historyItems) {
final History history = new History(); final History history = new History();
for (CalculatorHistoryState historyState : historyItems) { for (CalculatorHistoryState historyState : historyItems) {
if (historyState.isSaved()) { if (historyState.isSaved()) {
history.getHistoryItems().add(historyState); history.getHistoryItems().add(historyState);
} }
} }
final StringWriter xml = new StringWriter(); final StringWriter xml = new StringWriter();
final Serializer serializer = new Persister(); final Serializer serializer = new Persister();
try { try {
serializer.write(history, xml); serializer.write(history, xml);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return xml.toString(); return xml.toString();
} }
} }

View File

@ -8,8 +8,8 @@ package org.solovyev.android.calculator.jscl;
import jscl.math.Generic; import jscl.math.Generic;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
/** /**
* User: serso * User: serso

View File

@ -10,9 +10,9 @@ 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.CalculatorLocatorImpl; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.model.DummyTextProcessor; import org.solovyev.android.calculator.text.DummyTextProcessor;
import org.solovyev.android.calculator.model.FromJsclSimplifyTextProcessor; import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
public enum JsclOperation { public enum JsclOperation {

View File

@ -13,7 +13,7 @@ import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.CalculatorLocatorImpl; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.common.JPredicate; import org.solovyev.common.JPredicate;
import org.solovyev.common.StartsWithFinder; import org.solovyev.common.StartsWithFinder;
import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.common.collections.CollectionsUtils; import org.solovyev.common.collections.CollectionsUtils;
import java.util.*; import java.util.*;

View File

@ -4,10 +4,11 @@
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator.text;
import jscl.math.Generic; import jscl.math.Generic;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorParseException;
/** /**
* User: serso * User: serso

View File

@ -1,11 +1,11 @@
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator.text;
import jscl.math.Generic; 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.CalculatorLocator;
import org.solovyev.android.calculator.CalculatorLocatorImpl; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.CalculatorParseException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;

View File

@ -1,6 +1,7 @@
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator.text;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorParseException;
/** /**
* User: serso * User: serso

View File

@ -102,17 +102,6 @@
<dependency> <dependency>
<groupId>org.simpleframework</groupId> <groupId>org.simpleframework</groupId>
<artifactId>simple-xml</artifactId> <artifactId>simple-xml</artifactId>
<version>2.6.1</version>
<exclusions>
<exclusion>
<artifactId>stax-api</artifactId>
<groupId>stax</groupId>
</exclusion>
<exclusion>
<artifactId>xpp3</artifactId>
<groupId>xpp3</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -1,348 +1,347 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import android.graphics.Color; 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.NumeralBase; import jscl.NumeralBase;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.math.function.IConstant; import jscl.math.function.IConstant;
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.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.model.ToJsclTextProcessor;
import org.solovyev.android.calculator.model.ToJsclTextProcessor; import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.calculator.view.TextHighlighter; import org.solovyev.android.calculator.view.UnitConverterViewBuilder;
import org.solovyev.android.calculator.view.UnitConverterViewBuilder; import org.solovyev.android.menu.AMenuItem;
import org.solovyev.android.menu.AMenuItem; import org.solovyev.android.menu.LabeledMenuItem;
import org.solovyev.android.menu.LabeledMenuItem; import org.solovyev.android.view.AutoResizeTextView;
import org.solovyev.android.view.AutoResizeTextView; import org.solovyev.common.collections.CollectionsUtils;
import org.solovyev.common.collections.CollectionsUtils; import org.solovyev.common.text.StringUtils;
import org.solovyev.common.text.StringUtils;
import java.util.HashSet;
import java.util.HashSet; import java.util.Set;
import java.util.Set;
/**
/** * User: serso
* User: serso * Date: 9/17/11
* Date: 9/17/11 * Time: 10:58 PM
* Time: 10:58 PM */
*/ public class CalculatorDisplay extends AutoResizeTextView implements ICalculatorDisplay{
public class CalculatorDisplay extends AutoResizeTextView implements ICalculatorDisplay{
private static enum ConversionMenuItem implements AMenuItem<CalculatorDisplay> {
private static enum ConversionMenuItem implements AMenuItem<CalculatorDisplay> { convert_to_bin(NumeralBase.bin),
convert_to_bin(NumeralBase.bin), convert_to_dec(NumeralBase.dec),
convert_to_dec(NumeralBase.dec), convert_to_hex(NumeralBase.hex);
convert_to_hex(NumeralBase.hex);
@NotNull
@NotNull private final NumeralBase toNumeralBase;
private final NumeralBase toNumeralBase;
private ConversionMenuItem(@NotNull NumeralBase toNumeralBase) {
private ConversionMenuItem(@NotNull NumeralBase toNumeralBase) { this.toNumeralBase = toNumeralBase;
this.toNumeralBase = toNumeralBase; }
}
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { boolean result = false;
boolean result = false;
if (operation == JsclOperation.numeric) {
if (operation == JsclOperation.numeric) { if (generic.getConstants().isEmpty()) {
if (generic.getConstants().isEmpty()) { try {
try { convert(generic);
convert(generic);
// conversion possible => return true
// conversion possible => return true result = true;
result = true;
} catch (UnitConverterViewBuilder.ConversionException e) {
} catch (UnitConverterViewBuilder.ConversionException e) { // conversion is not possible => return false
// conversion is not possible => return false }
} }
} }
}
return result;
return result; }
}
@Override
@Override public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
String to;
String to; try {
try { to = convert(data.getGenericResult());
to = convert(data.getGenericResult());
// add prefix
// add prefix if (fromNumeralBase != toNumeralBase) {
if (fromNumeralBase != toNumeralBase) { to = toNumeralBase.getJsclPrefix() + to;
to = toNumeralBase.getJsclPrefix() + to; }
} } catch (UnitConverterViewBuilder.ConversionException e) {
} catch (UnitConverterViewBuilder.ConversionException e) { to = context.getString(R.string.c_error);
to = context.getString(R.string.c_error); }
}
data.setText(to);
data.setText(to); data.redraw();
data.redraw(); }
}
@NotNull
@NotNull private String convert(@NotNull Generic generic) throws UnitConverterViewBuilder.ConversionException {
private String convert(@NotNull Generic generic) throws UnitConverterViewBuilder.ConversionException { final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
if (fromNumeralBase != toNumeralBase) {
if (fromNumeralBase != toNumeralBase) { String from = generic.toString();
String from = generic.toString(); if (!StringUtils.isEmpty(from)) {
if (!StringUtils.isEmpty(from)) { try {
try { from = ToJsclTextProcessor.getInstance().process(from).getExpression();
from = ToJsclTextProcessor.getInstance().process(from).getExpression(); } catch (CalculatorParseException e) {
} catch (CalculatorParseException e) { // ok, problems while processing occurred
// ok, problems while processing occurred }
} }
}
return UnitConverterViewBuilder.doConversion(AndroidNumeralBase.getConverter(), from, AndroidNumeralBase.valueOf(fromNumeralBase), AndroidNumeralBase.valueOf(toNumeralBase));
return UnitConverterViewBuilder.doConversion(AndroidNumeralBase.getConverter(), from, AndroidNumeralBase.valueOf(fromNumeralBase), AndroidNumeralBase.valueOf(toNumeralBase)); } else {
} else { return generic.toString();
return generic.toString(); }
} }
} }
}
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplay> {
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplay> {
copy(R.string.c_copy) {
copy(R.string.c_copy) { @Override
@Override public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { CalculatorModel.copyResult(context, data);
CalculatorModel.copyResult(context, data); }
} },
},
convert_to_bin(R.string.convert_to_bin) {
convert_to_bin(R.string.convert_to_bin) { @Override
@Override public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { ConversionMenuItem.convert_to_bin.onClick(data, context);
ConversionMenuItem.convert_to_bin.onClick(data, context); }
}
@Override
@Override protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation); }
} },
},
convert_to_dec(R.string.convert_to_dec) {
convert_to_dec(R.string.convert_to_dec) { @Override
@Override public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { ConversionMenuItem.convert_to_dec.onClick(data, context);
ConversionMenuItem.convert_to_dec.onClick(data, context); }
}
@Override
@Override protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation); }
} },
},
convert_to_hex(R.string.convert_to_hex) {
convert_to_hex(R.string.convert_to_hex) { @Override
@Override public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { ConversionMenuItem.convert_to_hex.onClick(data, context);
ConversionMenuItem.convert_to_hex.onClick(data, context); }
}
@Override
@Override protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation); }
} },
},
convert(R.string.c_convert) {
convert(R.string.c_convert) { @Override
@Override public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { new NumeralBaseConverterDialog(data.getGenericResult().toString()).show(context);
new NumeralBaseConverterDialog(data.getGenericResult().toString()).show(context); }
}
@Override
@Override protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
return operation == JsclOperation.numeric && generic.getConstants().isEmpty(); }
} },
},
plot(R.string.c_plot) {
plot(R.string.c_plot) { @Override
@Override public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { final Generic generic = data.getGenericResult();
final Generic generic = data.getGenericResult(); assert generic != null;
assert generic != null;
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic)); assert constant != null;
assert constant != null; CalculatorActivityLauncher.plotGraph(context, generic, constant);
CalculatorActivityLauncher.plotGraph(context, generic, constant); }
}
@Override
@Override protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { boolean result = false;
boolean result = false;
if (operation == JsclOperation.simplify) {
if (operation == JsclOperation.simplify) { if (getNotSystemConstants(generic).size() == 1) {
if (getNotSystemConstants(generic).size() == 1) { result = true;
result = true; }
} }
}
return result;
return result; }
}
@NotNull
@NotNull private Set<Constant> getNotSystemConstants(@NotNull Generic generic) {
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) { final Set<Constant> notSystemConstants = new HashSet<Constant>();
final Set<Constant> notSystemConstants = new HashSet<Constant>();
for (Constant constant : generic.getConstants()) {
for (Constant constant : generic.getConstants()) { IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName());
IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName()); if (var != null && !var.isSystem() && !var.isDefined()) {
if (var != null && !var.isSystem() && !var.isDefined()) { notSystemConstants.add(constant);
notSystemConstants.add(constant); }
} }
}
return notSystemConstants;
return notSystemConstants; }
} };
};
private final int captionId;
private final int captionId;
MenuItem(int captionId) {
MenuItem(int captionId) { this.captionId = captionId;
this.captionId = captionId; }
}
public final boolean isItemVisible(@NotNull CalculatorDisplay display) {
public final boolean isItemVisible(@NotNull CalculatorDisplay display) { //noinspection ConstantConditions
//noinspection ConstantConditions return display.isValid() && display.getGenericResult() != null && isItemVisibleFor(display.getGenericResult(), display.getJsclOperation());
return display.isValid() && display.getGenericResult() != null && isItemVisibleFor(display.getGenericResult(), display.getJsclOperation()); }
}
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { return true;
return true; }
}
@NotNull
@NotNull @Override
@Override public String getCaption(@NotNull Context context) {
public String getCaption(@NotNull Context context) { return context.getString(captionId);
return context.getString(captionId); }
} }
}
private boolean valid = true;
private boolean valid = true;
@Nullable
@Nullable private String errorMessage;
private String errorMessage;
@NotNull
@NotNull private JsclOperation jsclOperation = JsclOperation.numeric;
private JsclOperation jsclOperation = JsclOperation.numeric;
@NotNull
@NotNull private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
@Nullable
@Nullable private Generic genericResult;
private Generic genericResult;
public CalculatorDisplay(Context context) {
public CalculatorDisplay(Context context) { super(context);
super(context); }
}
public CalculatorDisplay(Context context, AttributeSet attrs) {
public CalculatorDisplay(Context context, AttributeSet attrs) { super(context, attrs);
super(context, attrs); }
}
public CalculatorDisplay(Context context, AttributeSet attrs, int defStyle) {
public CalculatorDisplay(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle);
super(context, attrs, defStyle); }
}
@Override
@Override public boolean isValid() {
public boolean isValid() { return valid;
return valid; }
}
@Override
@Override public void setValid(boolean valid) {
public void setValid(boolean valid) { this.valid = valid;
this.valid = valid; if (valid) {
if (valid) { errorMessage = null;
errorMessage = null; setTextColor(getResources().getColor(R.color.default_text_color));
setTextColor(getResources().getColor(R.color.default_text_color)); } else {
} else { setTextColor(getResources().getColor(R.color.display_error_text_color));
setTextColor(getResources().getColor(R.color.display_error_text_color)); }
} }
}
@Override
@Override @Nullable
@Nullable public String getErrorMessage() {
public String getErrorMessage() { return errorMessage;
return errorMessage; }
}
@Override
@Override public void setErrorMessage(@Nullable String errorMessage) {
public void setErrorMessage(@Nullable String errorMessage) { this.errorMessage = errorMessage;
this.errorMessage = errorMessage; }
}
@Override
@Override public void setJsclOperation(@NotNull JsclOperation jsclOperation) {
public void setJsclOperation(@NotNull JsclOperation jsclOperation) { this.jsclOperation = jsclOperation;
this.jsclOperation = jsclOperation; }
}
@Override
@Override @NotNull
@NotNull public JsclOperation getJsclOperation() {
public JsclOperation getJsclOperation() { return jsclOperation;
return jsclOperation; }
}
@Override
@Override public void setText(CharSequence text, BufferType type) {
public void setText(CharSequence text, BufferType type) { super.setText(text, type);
super.setText(text, type);
setValid(true);
setValid(true); }
}
public synchronized void redraw() {
public synchronized void redraw() { if (isValid()) {
if (isValid()) { String text = getText().toString();
String text = getText().toString();
Log.d(this.getClass().getName(), text);
Log.d(this.getClass().getName(), text);
try {
try { TextHighlighter.Result result = textHighlighter.process(text);
TextHighlighter.Result result = textHighlighter.process(text); text = result.toString();
text = result.toString(); } catch (CalculatorParseException e) {
} catch (CalculatorParseException e) { Log.e(this.getClass().getName(), e.getMessage(), e);
Log.e(this.getClass().getName(), e.getMessage(), e); }
}
Log.d(this.getClass().getName(), text);
Log.d(this.getClass().getName(), text); super.setText(Html.fromHtml(text), BufferType.EDITABLE);
super.setText(Html.fromHtml(text), BufferType.EDITABLE); }
}
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize()) setAddEllipsis(false);
setAddEllipsis(false); setMinTextSize(10);
setMinTextSize(10); resizeText();
resizeText(); }
}
@Override
@Override public void setGenericResult(@Nullable Generic genericResult) {
public void setGenericResult(@Nullable Generic genericResult) { this.genericResult = genericResult;
this.genericResult = genericResult; }
}
@Override
@Override @Nullable
@Nullable public Generic getGenericResult() {
public Generic getGenericResult() { return genericResult;
return genericResult; }
}
@Override
@Override public int getSelection() {
public int getSelection() { return this.getSelectionStart();
return this.getSelectionStart(); }
}
@Override
@Override public void setSelection(int selection) {
public void setSelection(int selection) { // not supported by TextView
// not supported by TextView }
} }
}

View File

@ -1,166 +1,165 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
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 android.view.ContextMenu; import android.view.ContextMenu;
import android.widget.EditText; import android.widget.EditText;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.calculator.view.TextHighlighter; import org.solovyev.common.collections.CollectionsUtils;
import org.solovyev.common.collections.CollectionsUtils;
/**
/** * User: serso
* User: serso * Date: 9/17/11
* Date: 9/17/11 * Time: 12:25 AM
* Time: 12:25 AM */
*/ public class CalculatorEditor extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener {
public class CalculatorEditor extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String CALC_COLOR_DISPLAY_KEY = "org.solovyev.android.calculator.CalculatorModel_color_display";
private static final String CALC_COLOR_DISPLAY_KEY = "org.solovyev.android.calculator.CalculatorModel_color_display"; private static final boolean CALC_COLOR_DISPLAY_DEFAULT = true;
private static final boolean CALC_COLOR_DISPLAY_DEFAULT = true;
private boolean highlightText = true;
private boolean highlightText = true;
@NotNull
@NotNull private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
public CalculatorEditor(Context context) {
public CalculatorEditor(Context context) { super(context);
super(context); init();
init(); }
}
public CalculatorEditor(Context context, AttributeSet attrs) {
public CalculatorEditor(Context context, AttributeSet attrs) { super(context, attrs);
super(context, attrs); init();
init(); }
}
private void init() {
private void init() { // NOTE: in this solution cursor is missing
// NOTE: in this solution cursor is missing
/*this.setOnTouchListener(new OnTouchListener() {
/*this.setOnTouchListener(new OnTouchListener() { @Override
@Override public boolean onTouch(View v, MotionEvent event) {
public boolean onTouch(View v, MotionEvent event) { final TextView textView = (TextView)v;
final TextView textView = (TextView)v; // backup the input type
// backup the input type int inputType = textView.getInputType();
int inputType = textView.getInputType();
// disable soft input
// disable soft input textView.setInputType(InputType.TYPE_NULL);
textView.setInputType(InputType.TYPE_NULL);
// call native handler
// call native handler textView.onTouchEvent(event);
textView.onTouchEvent(event);
// restore input type
// restore input type textView.setInputType(inputType);
textView.setInputType(inputType);
// consume touch even
// consume touch even return true;
return true; }
} });*/
});*/ }
}
@Override
@Override public boolean onCheckIsTextEditor() {
public boolean onCheckIsTextEditor() { // NOTE: code below can be used carefully and should not be copied without special intention
// NOTE: code below can be used carefully and should not be copied without special intention // The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc
// The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc
if ( Build.VERSION.SDK_INT >= 11 ) {
if ( Build.VERSION.SDK_INT >= 11 ) { // fix for missing cursor in android 3 and higher
// fix for missing cursor in android 3 and higher try {
try { // IDEA: return false always except if method was called from TextView.isCursorVisible() method
// IDEA: return false always except if method was called from TextView.isCursorVisible() method for (StackTraceElement stackTraceElement : CollectionsUtils.asList(Thread.currentThread().getStackTrace())) {
for (StackTraceElement stackTraceElement : CollectionsUtils.asList(Thread.currentThread().getStackTrace())) { if ( "isCursorVisible".equals(stackTraceElement.getMethodName()) ) {
if ( "isCursorVisible".equals(stackTraceElement.getMethodName()) ) { return true;
return true; }
} }
} } catch (RuntimeException e) {
} catch (RuntimeException e) { // just in case...
// just in case... }
}
return false;
return false; } else {
} else { return false;
return false; }
} }
}
public CalculatorEditor(Context context, AttributeSet attrs, int defStyle) {
public CalculatorEditor(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle);
super(context, attrs, defStyle); init();
init(); }
}
@Override
@Override protected void onCreateContextMenu(ContextMenu menu) {
protected void onCreateContextMenu(ContextMenu menu) { super.onCreateContextMenu(menu);
super.onCreateContextMenu(menu);
menu.removeItem(android.R.id.selectAll);
menu.removeItem(android.R.id.selectAll); }
}
@Override
@Override public void setText(CharSequence text, BufferType type) {
public void setText(CharSequence text, BufferType type) { super.setText(text, type);
super.setText(text, type); }
}
public synchronized void redraw() {
public synchronized void redraw() { String text = getText().toString();
String text = getText().toString();
int selectionStart = getSelectionStart();
int selectionStart = getSelectionStart(); int selectionEnd = getSelectionEnd();
int selectionEnd = getSelectionEnd();
if (highlightText) {
if (highlightText) {
Log.d(this.getClass().getName(), text);
Log.d(this.getClass().getName(), text);
try {
try { final TextHighlighter.Result result = textHighlighter.process(text);
final TextHighlighter.Result result = textHighlighter.process(text); selectionStart += result.getOffset();
selectionStart += result.getOffset(); selectionEnd += result.getOffset();
selectionEnd += result.getOffset(); text = result.toString();
text = result.toString(); } catch (CalculatorParseException e) {
} catch (CalculatorParseException e) { Log.e(this.getClass().getName(), e.getMessage(), e);
Log.e(this.getClass().getName(), e.getMessage(), e); }
}
Log.d(this.getClass().getName(), text);
Log.d(this.getClass().getName(), text); super.setText(Html.fromHtml(text), BufferType.EDITABLE);
super.setText(Html.fromHtml(text), BufferType.EDITABLE); } else {
} else { super.setText(text, BufferType.EDITABLE);
super.setText(text, BufferType.EDITABLE); }
}
Log.d(this.getClass().getName(), getText().toString());
Log.d(this.getClass().getName(), getText().toString());
int length = getText().length();
int length = getText().length(); setSelection(Math.max(Math.min(length, selectionStart), 0), Math.max(Math.min(length, selectionEnd), 0));
setSelection(Math.max(Math.min(length, selectionStart), 0), Math.max(Math.min(length, selectionEnd), 0)); }
}
public boolean isHighlightText() {
public boolean isHighlightText() { return highlightText;
return highlightText; }
}
public void setHighlightText(boolean highlightText) {
public void setHighlightText(boolean highlightText) { this.highlightText = highlightText;
this.highlightText = highlightText; redraw();
redraw(); }
}
@Override
@Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (CALC_COLOR_DISPLAY_KEY.equals(key)) {
if (CALC_COLOR_DISPLAY_KEY.equals(key)) { this.setHighlightText(preferences.getBoolean(CALC_COLOR_DISPLAY_KEY, CALC_COLOR_DISPLAY_DEFAULT));
this.setHighlightText(preferences.getBoolean(CALC_COLOR_DISPLAY_KEY, CALC_COLOR_DISPLAY_DEFAULT)); }
} }
}
public void init(@NotNull SharedPreferences preferences) {
public void init(@NotNull SharedPreferences preferences) { onSharedPreferenceChanged(preferences, CALC_COLOR_DISPLAY_KEY);
onSharedPreferenceChanged(preferences, CALC_COLOR_DISPLAY_KEY); }
} }
}

View File

@ -1,411 +1,410 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; 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.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 org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.CursorControl; import org.solovyev.android.CursorControl;
import org.solovyev.android.calculator.history.CalculatorHistory; import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.history.TextViewEditorAdapter; import org.solovyev.android.calculator.history.TextViewEditorAdapter;
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.CalculatorEvalException; import org.solovyev.android.calculator.model.CalculatorEvalException;
import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.history.HistoryControl;
import org.solovyev.android.history.HistoryControl; import org.solovyev.android.menu.AMenuBuilder;
import org.solovyev.android.menu.AMenuBuilder; import org.solovyev.android.menu.MenuImpl;
import org.solovyev.android.menu.MenuImpl; import org.solovyev.common.MutableObject;
import org.solovyev.common.MutableObject; import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.Message; import org.solovyev.common.text.StringUtils;
import org.solovyev.common.text.StringUtils;
import java.util.ArrayList;
import java.util.ArrayList; import java.util.List;
import java.util.List;
/**
/** * User: serso
* User: serso * Date: 9/12/11
* Date: 9/12/11 * Time: 11:15 PM
* Time: 11:15 PM */
*/ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorHistoryState>, CalculatorEngineControl {
public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorHistoryState>, CalculatorEngineControl {
instance;
instance;
// millis to wait before evaluation after user edit action
// millis to wait before evaluation after user edit action public static final int EVAL_DELAY_MILLIS = 0;
public static final int EVAL_DELAY_MILLIS = 0;
@NotNull
@NotNull private CalculatorEditor editor;
private CalculatorEditor editor;
@NotNull
@NotNull private CalculatorDisplay display;
private CalculatorDisplay display;
@NotNull
@NotNull private CalculatorEngine calculatorEngine;
private CalculatorEngine calculatorEngine;
public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) {
public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) { Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity);
Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity); this.calculatorEngine = calculator;
this.calculatorEngine = calculator;
this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor);
this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor); this.editor.init(preferences);
this.editor.init(preferences); preferences.registerOnSharedPreferenceChangeListener(editor);
preferences.registerOnSharedPreferenceChangeListener(editor);
this.display = (CalculatorDisplay) activity.findViewById(R.id.calculatorDisplay);
this.display = (CalculatorDisplay) activity.findViewById(R.id.calculatorDisplay); this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
final CalculatorHistoryState lastState = CalculatorHistory.instance.getLastHistoryState();
final CalculatorHistoryState lastState = CalculatorHistory.instance.getLastHistoryState(); if (lastState == null) {
if (lastState == null) { saveHistoryState();
saveHistoryState(); } else {
} else { setCurrentHistoryState(lastState);
setCurrentHistoryState(lastState); }
}
return this;
return this; }
}
private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) {
private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) { final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null); ((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
((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(errorMessageView);
.setView(errorMessageView);
builder.create().show();
builder.create().show(); }
}
public void copyResult(@NotNull Context context) {
public void copyResult(@NotNull Context context) { copyResult(context, display);
copyResult(context, display); }
}
public static 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 = 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()); Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); }
} }
} }
}
private void saveHistoryState() {
private void saveHistoryState() { CalculatorHistory.instance.addState(getCurrentHistoryState());
CalculatorHistory.instance.addState(getCurrentHistoryState()); }
}
public void setCursorOnStart() {
public void setCursorOnStart() { editor.setSelection(0);
editor.setSelection(0); }
}
public void setCursorOnEnd() {
public void setCursorOnEnd() { editor.setSelection(editor.getText().length());
editor.setSelection(editor.getText().length()); }
}
public void moveCursorLeft() {
public void moveCursorLeft() { if (editor.getSelectionStart() > 0) {
if (editor.getSelectionStart() > 0) { editor.setSelection(editor.getSelectionStart() - 1);
editor.setSelection(editor.getSelectionStart() - 1); }
} }
}
public void moveCursorRight() {
public void moveCursorRight() { if (editor.getSelectionStart() < editor.getText().length()) {
if (editor.getSelectionStart() < editor.getText().length()) { editor.setSelection(editor.getSelectionStart() + 1);
editor.setSelection(editor.getSelectionStart() + 1); }
} }
}
public void doTextOperation(@NotNull TextOperation operation) {
public void doTextOperation(@NotNull TextOperation operation) { doTextOperation(operation, true);
doTextOperation(operation, true); }
}
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate) {
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate) { doTextOperation(operation, delayEvaluate, JsclOperation.numeric, false);
doTextOperation(operation, delayEvaluate, JsclOperation.numeric, false); }
}
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate, @NotNull JsclOperation jsclOperation, boolean forceEval) {
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate, @NotNull JsclOperation jsclOperation, boolean forceEval) { final String editorStateBefore = this.editor.getText().toString();
final String editorStateBefore = this.editor.getText().toString();
Log.d(CalculatorModel.class.getName(), "Editor state changed before '" + editorStateBefore + "'");
Log.d(CalculatorModel.class.getName(), "Editor state changed before '" + editorStateBefore + "'"); operation.doOperation(this.editor);
operation.doOperation(this.editor); //Log.d(CalculatorModel.class.getName(), "Doing text operation" + StringUtils.fromStackTrace(Thread.currentThread().getStackTrace()));
//Log.d(CalculatorModel.class.getName(), "Doing text operation" + StringUtils.fromStackTrace(Thread.currentThread().getStackTrace()));
final String editorStateAfter = this.editor.getText().toString();
final String editorStateAfter = this.editor.getText().toString(); if (forceEval ||!editorStateBefore.equals(editorStateAfter)) {
if (forceEval ||!editorStateBefore.equals(editorStateAfter)) {
editor.redraw();
editor.redraw();
evaluate(delayEvaluate, editorStateAfter, jsclOperation, null);
evaluate(delayEvaluate, editorStateAfter, jsclOperation, null); }
} }
}
@NotNull
@NotNull private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
private void evaluate(boolean delayEvaluate,
private void evaluate(boolean delayEvaluate, @NotNull final String expression,
@NotNull final String expression, @NotNull final JsclOperation operation,
@NotNull final JsclOperation operation, @Nullable CalculatorHistoryState historyState) {
@Nullable CalculatorHistoryState historyState) {
final CalculatorHistoryState localHistoryState;
final CalculatorHistoryState localHistoryState; if (historyState == null) {
if (historyState == null) { //this.display.setText("");
//this.display.setText(""); localHistoryState = getCurrentHistoryState();
localHistoryState = getCurrentHistoryState(); } else {
} else { this.display.setText(historyState.getDisplayState().getEditorState().getText());
this.display.setText(historyState.getDisplayState().getEditorState().getText()); localHistoryState = historyState;
localHistoryState = historyState; }
}
pendingOperation.setObject(new Runnable() {
pendingOperation.setObject(new Runnable() { @Override
@Override public void run() {
public void run() { // allow only one runner at one time
// allow only one runner at one time synchronized (pendingOperation) {
synchronized (pendingOperation) { //lock all operations with history
//lock all operations with history if (pendingOperation.getObject() == this) {
if (pendingOperation.getObject() == this) { // actually nothing shall be logged while text operations are done
// actually nothing shall be logged while text operations are done evaluate(expression, operation, this);
evaluate(expression, operation, this);
if (pendingOperation.getObject() == this) {
if (pendingOperation.getObject() == this) { // todo serso: of course there is small probability that someone will set pendingOperation after if statement but before .setObject(null)
// todo serso: of course there is small probability that someone will set pendingOperation after if statement but before .setObject(null) pendingOperation.setObject(null);
pendingOperation.setObject(null); localHistoryState.setDisplayState(getCurrentHistoryState().getDisplayState());
localHistoryState.setDisplayState(getCurrentHistoryState().getDisplayState()); }
} }
} }
} }
} });
});
if (delayEvaluate) {
if (delayEvaluate) { if (historyState == null) {
if (historyState == null) { CalculatorHistory.instance.addState(localHistoryState);
CalculatorHistory.instance.addState(localHistoryState); }
} // todo serso: this is not correct - operation is processing still in the same thread
// todo serso: this is not correct - operation is processing still in the same thread new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS);
new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS); } else {
} else { pendingOperation.getObject().run();
pendingOperation.getObject().run(); if (historyState == null) {
if (historyState == null) { CalculatorHistory.instance.addState(localHistoryState);
CalculatorHistory.instance.addState(localHistoryState); }
} }
} }
}
@Override
@Override public void evaluate() {
public void evaluate() { evaluate(false, this.editor.getText().toString(), JsclOperation.numeric, null);
evaluate(false, this.editor.getText().toString(), JsclOperation.numeric, null); }
}
public void evaluate(@NotNull JsclOperation operation) {
public void evaluate(@NotNull JsclOperation operation) { evaluate(false, this.editor.getText().toString(), operation, null);
evaluate(false, this.editor.getText().toString(), operation, null); }
}
@Override
@Override public void simplify() {
public void simplify() { evaluate(false, this.editor.getText().toString(), JsclOperation.simplify, null);
evaluate(false, this.editor.getText().toString(), JsclOperation.simplify, null); }
}
private void evaluate(@Nullable final String expression,
private void evaluate(@Nullable final String expression, @NotNull JsclOperation operation,
@NotNull JsclOperation operation, @NotNull Runnable currentRunner) {
@NotNull Runnable currentRunner) {
if (!StringUtils.isEmpty(expression)) {
if (!StringUtils.isEmpty(expression)) { try {
try { Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/);
Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/); final CalculatorEngine.Result result = calculatorEngine.evaluate(operation, expression);
final CalculatorEngine.Result result = calculatorEngine.evaluate(operation, expression);
// todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter
// todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) {
if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) { display.setText(result.getResult());
display.setText(result.getResult()); } else {
} else { display.setText("");
display.setText(""); }
} display.setJsclOperation(result.getUserOperation());
display.setJsclOperation(result.getUserOperation()); display.setGenericResult(result.getGenericResult());
display.setGenericResult(result.getGenericResult()); } catch (CalculatorParseException e) {
} catch (CalculatorParseException e) { handleEvaluationException(expression, display, operation, e);
handleEvaluationException(expression, display, operation, e); } catch (CalculatorEvalException e) {
} catch (CalculatorEvalException 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);
this.display.setGenericResult(null); }
}
this.display.redraw();
this.display.redraw(); }
}
private void handleEvaluationException(@NotNull String expression,
private void handleEvaluationException(@NotNull String expression, @NotNull CalculatorDisplay localDisplay,
@NotNull CalculatorDisplay localDisplay, @NotNull JsclOperation operation,
@NotNull JsclOperation operation, @NotNull Message e) {
@NotNull Message e) { Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e);
Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e); if ( StringUtils.isEmpty(localDisplay.getText()) ) {
if ( StringUtils.isEmpty(localDisplay.getText()) ) { // if previous display state was empty -> show error
// if previous display state was empty -> show error localDisplay.setText(R.string.c_syntax_error);
localDisplay.setText(R.string.c_syntax_error); } else {
} else { // show previous result instead of error caption (actually previous result will be greyed)
// show previous result instead of error caption (actually previous result will be greyed) }
} localDisplay.setJsclOperation(operation);
localDisplay.setJsclOperation(operation); localDisplay.setGenericResult(null);
localDisplay.setGenericResult(null); localDisplay.setValid(false);
localDisplay.setValid(false); localDisplay.setErrorMessage(e.getLocalizedMessage());
localDisplay.setErrorMessage(e.getLocalizedMessage()); }
}
public void clear() {
public void clear() { if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(display.getText())) {
if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(display.getText())) { editor.getText().clear();
editor.getText().clear(); display.setText("");
display.setText(""); saveHistoryState();
saveHistoryState(); }
} }
}
public void processDigitButtonAction(@Nullable final String text) {
public void processDigitButtonAction(@Nullable final String text) { processDigitButtonAction(text, true);
processDigitButtonAction(text, true); }
}
public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) {
public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) {
if (!StringUtils.isEmpty(text)) {
if (!StringUtils.isEmpty(text)) { doTextOperation(new CalculatorModel.TextOperation() {
doTextOperation(new CalculatorModel.TextOperation() {
@Override
@Override public void doOperation(@NotNull EditText editor) {
public void doOperation(@NotNull EditText editor) { int cursorPositionOffset = 0;
int cursorPositionOffset = 0; final StringBuilder textToBeInserted = new StringBuilder(text);
final StringBuilder textToBeInserted = new StringBuilder(text);
final MathType.Result mathType = MathType.getType(text, 0, false);
final MathType.Result mathType = MathType.getType(text, 0, false); switch (mathType.getMathType()) {
switch (mathType.getMathType()) { case function:
case function: textToBeInserted.append("()");
textToBeInserted.append("()"); cursorPositionOffset = -1;
cursorPositionOffset = -1; break;
break; case operator:
case operator: textToBeInserted.append("()");
textToBeInserted.append("()"); cursorPositionOffset = -1;
cursorPositionOffset = -1; break;
break; case comma:
case comma: textToBeInserted.append(" ");
textToBeInserted.append(" "); break;
break; }
}
if (cursorPositionOffset == 0) {
if (cursorPositionOffset == 0) { if (MathType.openGroupSymbols.contains(text)) {
if (MathType.openGroupSymbols.contains(text)) { cursorPositionOffset = -1;
cursorPositionOffset = -1; }
} }
}
editor.getText().insert(editor.getSelectionStart(), textToBeInserted.toString());
editor.getText().insert(editor.getSelectionStart(), textToBeInserted.toString()); editor.setSelection(editor.getSelectionStart() + cursorPositionOffset, editor.getSelectionEnd() + cursorPositionOffset);
editor.setSelection(editor.getSelectionStart() + cursorPositionOffset, editor.getSelectionEnd() + cursorPositionOffset); }
} }, delayEvaluate);
}, delayEvaluate); }
} }
}
public static interface TextOperation {
public static interface TextOperation {
void doOperation(@NotNull EditText editor);
void doOperation(@NotNull EditText editor);
}
}
@Override
@Override public void doHistoryAction(@NotNull HistoryAction historyAction) {
public void doHistoryAction(@NotNull HistoryAction historyAction) { synchronized (CalculatorHistory.instance) {
synchronized (CalculatorHistory.instance) { if (CalculatorHistory.instance.isActionAvailable(historyAction)) {
if (CalculatorHistory.instance.isActionAvailable(historyAction)) { final CalculatorHistoryState newState = CalculatorHistory.instance.doAction(historyAction, getCurrentHistoryState());
final CalculatorHistoryState newState = CalculatorHistory.instance.doAction(historyAction, getCurrentHistoryState()); if (newState != null) {
if (newState != null) { setCurrentHistoryState(newState);
setCurrentHistoryState(newState); }
} }
} }
} }
}
@Override
@Override public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { synchronized (CalculatorHistory.instance) {
synchronized (CalculatorHistory.instance) { Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState);
Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState);
editorHistoryState.setValuesFromHistory(new TextViewEditorAdapter(this.editor), this.display);
editorHistoryState.setValuesFromHistory(new TextViewEditorAdapter(this.editor), this.display);
final String expression = this.editor.getText().toString();
final String expression = this.editor.getText().toString(); if ( !StringUtils.isEmpty(expression) ) {
if ( !StringUtils.isEmpty(expression) ) { if ( StringUtils.isEmpty(this.display.getText().toString()) ) {
if ( StringUtils.isEmpty(this.display.getText().toString()) ) { evaluate(false, expression, this.display.getJsclOperation(), editorHistoryState);
evaluate(false, expression, this.display.getJsclOperation(), editorHistoryState); }
} }
}
editor.redraw();
editor.redraw(); display.redraw();
display.redraw(); }
} }
}
@Override
@Override @NotNull
@NotNull public CalculatorHistoryState getCurrentHistoryState() {
public CalculatorHistoryState getCurrentHistoryState() { synchronized (CalculatorHistory.instance) {
synchronized (CalculatorHistory.instance) { return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display);
return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display); }
} }
}
@NotNull
@NotNull public CalculatorDisplay getDisplay() {
public CalculatorDisplay getDisplay() { return display;
return display; }
}
private static class CalculatorDisplayOnClickListener implements View.OnClickListener {
private static class CalculatorDisplayOnClickListener implements View.OnClickListener {
@NotNull
@NotNull private final Activity activity;
private final Activity activity;
public CalculatorDisplayOnClickListener(@NotNull Activity activity) {
public CalculatorDisplayOnClickListener(@NotNull Activity activity) { this.activity = activity;
this.activity = activity; }
}
@Override
@Override public void onClick(View v) {
public void onClick(View v) { if (v instanceof CalculatorDisplay) {
if (v instanceof CalculatorDisplay) { final CalculatorDisplay cd = (CalculatorDisplay) v;
final CalculatorDisplay cd = (CalculatorDisplay) v;
if (cd.isValid()) {
if (cd.isValid()) { final List<CalculatorDisplay.MenuItem> filteredMenuItems = new ArrayList<CalculatorDisplay.MenuItem>(CalculatorDisplay.MenuItem.values().length);
final List<CalculatorDisplay.MenuItem> filteredMenuItems = new ArrayList<CalculatorDisplay.MenuItem>(CalculatorDisplay.MenuItem.values().length); for (CalculatorDisplay.MenuItem menuItem : CalculatorDisplay.MenuItem.values()) {
for (CalculatorDisplay.MenuItem menuItem : CalculatorDisplay.MenuItem.values()) { if (menuItem.isItemVisible(cd)) {
if (menuItem.isItemVisible(cd)) { filteredMenuItems.add(menuItem);
filteredMenuItems.add(menuItem); }
} }
}
if (!filteredMenuItems.isEmpty()) {
if (!filteredMenuItems.isEmpty()) { AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(cd).show();
AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(cd).show(); }
}
} else {
} else { final String errorMessage = cd.getErrorMessage();
final String errorMessage = cd.getErrorMessage(); if (errorMessage != null) {
if (errorMessage != null) { showEvaluationError(activity, errorMessage);
showEvaluationError(activity, errorMessage); }
} }
} }
} }
} }
} }
}

View File

@ -16,9 +16,11 @@ 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.CalculatorApplication; import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.JCalculatorEngine; import org.solovyev.android.calculator.JCalculatorEngine;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.msg.AndroidMessage; import org.solovyev.android.msg.AndroidMessage;
import org.solovyev.android.prefs.BooleanPreference; import org.solovyev.android.prefs.BooleanPreference;
import org.solovyev.android.prefs.Preference; import org.solovyev.android.prefs.Preference;

View File

@ -9,7 +9,9 @@ package org.solovyev.android.calculator.model;
import jscl.math.function.IConstant; import jscl.math.function.IConstant;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorApplication; import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.msg.AndroidMessage; import org.solovyev.android.msg.AndroidMessage;
import org.solovyev.common.StartsWithFinder; import org.solovyev.common.StartsWithFinder;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;

View File

@ -1,360 +1,360 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.plot; package org.solovyev.android.calculator.plot;
import android.app.Activity; import android.app.Activity;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.widget.Toast; import android.widget.Toast;
import jscl.math.Expression; import jscl.math.Expression;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.text.ParseException; import jscl.text.ParseException;
import org.achartengine.ChartFactory; import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView; import org.achartengine.GraphicalView;
import org.achartengine.chart.CubicLineChart; import org.achartengine.chart.CubicLineChart;
import org.achartengine.chart.PointStyle; import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart; import org.achartengine.chart.XYChart;
import org.achartengine.model.XYMultipleSeriesDataset; import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries; import org.achartengine.model.XYSeries;
import org.achartengine.renderer.BasicStroke; import org.achartengine.renderer.BasicStroke;
import org.achartengine.renderer.XYMultipleSeriesRenderer; import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer; import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.tools.PanListener; import org.achartengine.tools.PanListener;
import org.achartengine.tools.ZoomEvent; import org.achartengine.tools.ZoomEvent;
import org.achartengine.tools.ZoomListener; import org.achartengine.tools.ZoomListener;
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.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.model.PreparedExpression; import org.solovyev.android.calculator.model.PreparedExpression;
import org.solovyev.android.calculator.model.ToJsclTextProcessor; import org.solovyev.android.calculator.model.ToJsclTextProcessor;
import org.solovyev.common.MutableObject; import org.solovyev.common.MutableObject;
import java.io.Serializable; import java.io.Serializable;
/** /**
* User: serso * User: serso
* Date: 12/1/11 * Date: 12/1/11
* Time: 12:40 AM * Time: 12:40 AM
*/ */
public class CalculatorPlotActivity extends Activity { public class CalculatorPlotActivity extends Activity {
private static final String TAG = CalculatorPlotActivity.class.getSimpleName(); private static final String TAG = CalculatorPlotActivity.class.getSimpleName();
private static final int DEFAULT_NUMBER_OF_STEPS = 100; private static final int DEFAULT_NUMBER_OF_STEPS = 100;
private static final int DEFAULT_MIN_NUMBER = -10; private static final int DEFAULT_MIN_NUMBER = -10;
private static final int DEFAULT_MAX_NUMBER = 10; private static final int DEFAULT_MAX_NUMBER = 10;
public static final String INPUT = "org.solovyev.android.calculator.CalculatorPlotActivity_input"; public static final String INPUT = "org.solovyev.android.calculator.CalculatorPlotActivity_input";
public static final long EVAL_DELAY_MILLIS = 200; public static final long EVAL_DELAY_MILLIS = 200;
private XYChart chart; private XYChart chart;
/** /**
* The encapsulated graphical view. * The encapsulated graphical view.
*/ */
private GraphicalView graphicalView; private GraphicalView graphicalView;
@NotNull @NotNull
private Generic expression; private Generic expression;
@NotNull @NotNull
private Constant variable; private Constant variable;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras(); Bundle extras = getIntent().getExtras();
final Input input = (Input) extras.getSerializable(INPUT); final Input input = (Input) extras.getSerializable(INPUT);
try { try {
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression()); final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
this.expression = Expression.valueOf(preparedExpression.getExpression()); this.expression = Expression.valueOf(preparedExpression.getExpression());
this.variable = new Constant(input.getVariableName()); this.variable = new Constant(input.getVariableName());
String title = extras.getString(ChartFactory.TITLE); String title = extras.getString(ChartFactory.TITLE);
if (title == null) { if (title == null) {
requestWindowFeature(Window.FEATURE_NO_TITLE); requestWindowFeature(Window.FEATURE_NO_TITLE);
} else if (title.length() > 0) { } else if (title.length() > 0) {
setTitle(title); setTitle(title);
} }
setContentView(R.layout.calc_plot_view); setContentView(R.layout.calc_plot_view);
final Object lastNonConfigurationInstance = getLastNonConfigurationInstance(); final Object lastNonConfigurationInstance = getLastNonConfigurationInstance();
setGraphicalView(lastNonConfigurationInstance instanceof PlotBoundaries ? (PlotBoundaries)lastNonConfigurationInstance : null); setGraphicalView(lastNonConfigurationInstance instanceof PlotBoundaries ? (PlotBoundaries)lastNonConfigurationInstance : null);
} catch (ParseException e) { } catch (ParseException e) {
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
finish(); finish();
} catch (ArithmeticException e) { } catch (ArithmeticException e) {
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
finish(); finish();
} catch (CalculatorParseException e) { } catch (CalculatorParseException e) {
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
finish(); finish();
} }
} }
private void setGraphicalView(@Nullable PlotBoundaries plotBoundaries) { private void setGraphicalView(@Nullable PlotBoundaries plotBoundaries) {
double minValue = plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.xMin; double minValue = plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.xMin;
double maxValue = plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.xMax; double maxValue = plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.xMax;
final ViewGroup graphContainer = (ViewGroup) findViewById(R.id.plot_view_container); final ViewGroup graphContainer = (ViewGroup) findViewById(R.id.plot_view_container);
if (graphicalView != null) { if (graphicalView != null) {
graphContainer.removeView(graphicalView); graphContainer.removeView(graphicalView);
} }
chart = prepareChart(minValue, maxValue, expression, variable); chart = prepareChart(minValue, maxValue, expression, variable);
// reverting boundaries (as in prepareChart() we add some cached values ) // reverting boundaries (as in prepareChart() we add some cached values )
double minX = Double.MAX_VALUE; double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE; double minY = Double.MAX_VALUE;
double maxX = Double.MIN_VALUE; double maxX = Double.MIN_VALUE;
double maxY = Double.MIN_VALUE; double maxY = Double.MIN_VALUE;
for (XYSeries series : chart.getDataset().getSeries()) { for (XYSeries series : chart.getDataset().getSeries()) {
minX = Math.min(minX, series.getMinX()); minX = Math.min(minX, series.getMinX());
minY = Math.min(minY, series.getMinY()); minY = Math.min(minY, series.getMinY());
maxX = Math.max(maxX, series.getMaxX()); maxX = Math.max(maxX, series.getMaxX());
maxY = Math.max(maxY, series.getMaxY()); maxY = Math.max(maxY, series.getMaxY());
} }
Log.d(CalculatorPlotActivity.class.getName(), "min x: " + minX + ", min y: " + minY + ", max x: " + maxX + ", max y: " + maxY); Log.d(CalculatorPlotActivity.class.getName(), "min x: " + minX + ", min y: " + minY + ", max x: " + maxX + ", max y: " + maxY);
Log.d(CalculatorPlotActivity.class.getName(), "Plot boundaries are " + plotBoundaries); Log.d(CalculatorPlotActivity.class.getName(), "Plot boundaries are " + plotBoundaries);
if (plotBoundaries == null) { if (plotBoundaries == null) {
chart.getRenderer().setXAxisMin(Math.max(minX, minValue)); chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
chart.getRenderer().setYAxisMin(Math.max(minY, minValue)); chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue)); chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue)); chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
} else { } else {
chart.getRenderer().setXAxisMin(plotBoundaries.xMin); chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
chart.getRenderer().setYAxisMin(plotBoundaries.yMin); chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
chart.getRenderer().setXAxisMax(plotBoundaries.xMax); chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
chart.getRenderer().setYAxisMax(plotBoundaries.yMax); chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
} }
graphicalView = new GraphicalView(this, chart); graphicalView = new GraphicalView(this, chart);
graphicalView.addZoomListener(new ZoomListener() { graphicalView.addZoomListener(new ZoomListener() {
@Override @Override
public void zoomApplied(ZoomEvent e) { public void zoomApplied(ZoomEvent e) {
updateDataSets(chart); updateDataSets(chart);
} }
@Override @Override
public void zoomReset() { public void zoomReset() {
updateDataSets(chart); updateDataSets(chart);
} }
}, true, true); }, true, true);
graphicalView.addPanListener(new PanListener() { graphicalView.addPanListener(new PanListener() {
@Override @Override
public void panApplied() { public void panApplied() {
Log.d(TAG, "org.achartengine.tools.PanListener.panApplied"); Log.d(TAG, "org.achartengine.tools.PanListener.panApplied");
updateDataSets(chart); updateDataSets(chart);
} }
}); });
graphContainer.addView(graphicalView); graphContainer.addView(graphicalView);
updateDataSets(chart, 50); updateDataSets(chart, 50);
} }
private void updateDataSets(@NotNull final XYChart chart) { private void updateDataSets(@NotNull final XYChart chart) {
updateDataSets(chart, EVAL_DELAY_MILLIS); updateDataSets(chart, EVAL_DELAY_MILLIS);
} }
private void updateDataSets(@NotNull final XYChart chart, long millisToWait) { private void updateDataSets(@NotNull final XYChart chart, long millisToWait) {
pendingOperation.setObject(new Runnable() { pendingOperation.setObject(new Runnable() {
@Override @Override
public void run() { public void run() {
// allow only one runner at one time // allow only one runner at one time
synchronized (pendingOperation) { synchronized (pendingOperation) {
//lock all operations with history //lock all operations with history
if (pendingOperation.getObject() == this) { if (pendingOperation.getObject() == this) {
Log.d(TAG, "org.solovyev.android.calculator.plot.CalculatorPlotActivity.updateDataSets"); Log.d(TAG, "org.solovyev.android.calculator.plot.CalculatorPlotActivity.updateDataSets");
final XYMultipleSeriesRenderer dr = chart.getRenderer(); final XYMultipleSeriesRenderer dr = chart.getRenderer();
//Log.d(CalculatorPlotActivity.class.getName(), "x = [" + dr.getXAxisMin() + ", " + dr.getXAxisMax() + "], y = [" + dr.getYAxisMin() + ", " + dr.getYAxisMax() + "]"); //Log.d(CalculatorPlotActivity.class.getName(), "x = [" + dr.getXAxisMin() + ", " + dr.getXAxisMax() + "], y = [" + dr.getYAxisMin() + ", " + dr.getYAxisMax() + "]");
final MyXYSeries realSeries = (MyXYSeries)chart.getDataset().getSeriesAt(0); final MyXYSeries realSeries = (MyXYSeries)chart.getDataset().getSeriesAt(0);
final MyXYSeries imagSeries; final MyXYSeries imagSeries;
if (chart.getDataset().getSeriesCount() > 1) { if (chart.getDataset().getSeriesCount() > 1) {
imagSeries = (MyXYSeries)chart.getDataset().getSeriesAt(1); imagSeries = (MyXYSeries)chart.getDataset().getSeriesAt(1);
} else { } else {
imagSeries = new MyXYSeries(getImagFunctionName(CalculatorPlotActivity.this.variable), DEFAULT_NUMBER_OF_STEPS * 2); imagSeries = new MyXYSeries(getImagFunctionName(CalculatorPlotActivity.this.variable), DEFAULT_NUMBER_OF_STEPS * 2);
} }
try { try {
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, DEFAULT_NUMBER_OF_STEPS)) { if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, DEFAULT_NUMBER_OF_STEPS)) {
if (chart.getDataset().getSeriesCount() <= 1) { if (chart.getDataset().getSeriesCount() <= 1) {
chart.getDataset().addSeries(imagSeries); chart.getDataset().addSeries(imagSeries);
chart.getRenderer().addSeriesRenderer(createImagRenderer()); chart.getRenderer().addSeriesRenderer(createImagRenderer());
} }
} }
} catch (ArithmeticException e) { } catch (ArithmeticException e) {
// todo serso: translate // todo serso: translate
Toast.makeText(CalculatorPlotActivity.this, "Arithmetic error: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); Toast.makeText(CalculatorPlotActivity.this, "Arithmetic error: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
CalculatorPlotActivity.this.finish(); CalculatorPlotActivity.this.finish();
} }
if (pendingOperation.getObject() == this) { if (pendingOperation.getObject() == this) {
graphicalView.repaint(); graphicalView.repaint();
} }
} }
} }
} }
}); });
new Handler().postDelayed(pendingOperation.getObject(), millisToWait); new Handler().postDelayed(pendingOperation.getObject(), millisToWait);
} }
@NotNull @NotNull
private static String getImagFunctionName(@NotNull Constant variable) { private static String getImagFunctionName(@NotNull Constant variable) {
return "g(" + variable.getName() +")" + " = " + "Im(ƒ(" + variable.getName() +"))"; return "g(" + variable.getName() +")" + " = " + "Im(ƒ(" + variable.getName() +"))";
} }
@NotNull @NotNull
private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) { private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) {
return "ƒ(" + variable.getName() +")" + " = " + expression.toString(); return "ƒ(" + variable.getName() +")" + " = " + expression.toString();
} }
@NotNull @NotNull
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>(); private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
private static XYChart prepareChart(final double minValue, final double maxValue, @NotNull final Generic expression, @NotNull final Constant variable) { private static XYChart prepareChart(final double minValue, final double maxValue, @NotNull final Generic expression, @NotNull final Constant variable) {
final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2); final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2);
final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2); final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2);
boolean imagExists = PlotUtils.addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS); boolean imagExists = PlotUtils.addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS);
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset(); final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
data.addSeries(realSeries); data.addSeries(realSeries);
if (imagExists) { if (imagExists) {
data.addSeries(imagSeries); data.addSeries(imagSeries);
} }
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(); final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.setShowGrid(true); renderer.setShowGrid(true);
renderer.setXTitle(variable.getName()); renderer.setXTitle(variable.getName());
renderer.setYTitle("f(" + variable.getName() + ")"); renderer.setYTitle("f(" + variable.getName() + ")");
renderer.setChartTitleTextSize(20); renderer.setChartTitleTextSize(20);
renderer.setZoomEnabled(true); renderer.setZoomEnabled(true);
renderer.setZoomButtonsVisible(true); renderer.setZoomButtonsVisible(true);
renderer.addSeriesRenderer(createCommonRenderer()); renderer.addSeriesRenderer(createCommonRenderer());
if (imagExists) { if (imagExists) {
renderer.addSeriesRenderer(createImagRenderer()); renderer.addSeriesRenderer(createImagRenderer());
} }
return new CubicLineChart(data, renderer, 0.1f); return new CubicLineChart(data, renderer, 0.1f);
} }
private static XYSeriesRenderer createImagRenderer() { private static XYSeriesRenderer createImagRenderer() {
final XYSeriesRenderer imagRenderer = createCommonRenderer(); final XYSeriesRenderer imagRenderer = createCommonRenderer();
imagRenderer.setStroke(BasicStroke.DASHED); imagRenderer.setStroke(BasicStroke.DASHED);
imagRenderer.setColor(Color.LTGRAY); imagRenderer.setColor(Color.LTGRAY);
return imagRenderer; return imagRenderer;
} }
@Override @Override
public Object onRetainNonConfigurationInstance() { public Object onRetainNonConfigurationInstance() {
return new PlotBoundaries(chart.getRenderer()); return new PlotBoundaries(chart.getRenderer());
} }
private static final class PlotBoundaries implements Serializable { private static final class PlotBoundaries implements Serializable {
private final double xMin; private final double xMin;
private final double xMax; private final double xMax;
private final double yMin; private final double yMin;
private final double yMax; private final double yMax;
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) { public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
this.xMin = renderer.getXAxisMin(); this.xMin = renderer.getXAxisMin();
this.yMin = renderer.getYAxisMin(); this.yMin = renderer.getYAxisMin();
this.xMax = renderer.getXAxisMax(); this.xMax = renderer.getXAxisMax();
this.yMax = renderer.getYAxisMax(); this.yMax = renderer.getYAxisMax();
} }
@Override @Override
public String toString() { public String toString() {
return "PlotBoundaries{" + return "PlotBoundaries{" +
"yMax=" + yMax + "yMax=" + yMax +
", yMin=" + yMin + ", yMin=" + yMin +
", xMax=" + xMax + ", xMax=" + xMax +
", xMin=" + xMin + ", xMin=" + xMin +
'}'; '}';
} }
} }
@NotNull @NotNull
private static XYSeriesRenderer createCommonRenderer() { private static XYSeriesRenderer createCommonRenderer() {
final XYSeriesRenderer renderer = new XYSeriesRenderer(); final XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setFillPoints(true); renderer.setFillPoints(true);
renderer.setPointStyle(PointStyle.POINT); renderer.setPointStyle(PointStyle.POINT);
renderer.setLineWidth(3); renderer.setLineWidth(3);
renderer.setColor(Color.WHITE); renderer.setColor(Color.WHITE);
renderer.setStroke(BasicStroke.SOLID); renderer.setStroke(BasicStroke.SOLID);
return renderer; return renderer;
} }
public void zoomInClickHandler(@NotNull View v) { public void zoomInClickHandler(@NotNull View v) {
this.graphicalView.zoomIn(); this.graphicalView.zoomIn();
} }
public void zoomOutClickHandler(@NotNull View v) { public void zoomOutClickHandler(@NotNull View v) {
this.graphicalView.zoomOut(); this.graphicalView.zoomOut();
} }
public static class Input implements Serializable { public static class Input implements Serializable {
@NotNull @NotNull
private String expression; private String expression;
@NotNull @NotNull
private String variableName; private String variableName;
public Input(@NotNull String expression, @NotNull String variableName) { public Input(@NotNull String expression, @NotNull String variableName) {
this.expression = expression; this.expression = expression;
this.variableName = variableName; this.variableName = variableName;
} }
@NotNull @NotNull
public String getExpression() { public String getExpression() {
return expression; return expression;
} }
@NotNull @NotNull
public String getVariableName() { public String getVariableName() {
return variableName; return variableName;
} }
} }
} }

View File

@ -12,7 +12,7 @@ import org.solovyev.android.calculator.AndroidNumeralBase;
import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.CalculatorModel;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.model.ToJsclTextProcessor; import org.solovyev.android.calculator.model.ToJsclTextProcessor;
import org.solovyev.common.MutableObject; import org.solovyev.common.MutableObject;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.text.StringUtils;

View File

@ -1,238 +1,240 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.view; package org.solovyev.android.calculator.view;
import jscl.MathContext; import jscl.MathContext;
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.CalculatorParseException;
import org.solovyev.android.calculator.model.*; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.common.MutableObject; import org.solovyev.android.calculator.model.*;
import org.solovyev.android.calculator.text.TextProcessor;
import java.util.HashMap; import org.solovyev.common.MutableObject;
import java.util.Map;
import java.util.HashMap;
/** import java.util.Map;
* User: serso
* Date: 10/12/11 /**
* Time: 9:47 PM * User: serso
*/ * Date: 10/12/11
public class TextHighlighter implements TextProcessor<TextHighlighter.Result, String> { * Time: 9:47 PM
*/
private static final Map<String, String> nbFontAttributes = new HashMap<String, String>(); public class TextHighlighter implements TextProcessor<TextHighlighter.Result, String> {
static { private static final Map<String, String> nbFontAttributes = new HashMap<String, String>();
nbFontAttributes.put("color", "#008000");
} static {
nbFontAttributes.put("color", "#008000");
@NotNull }
public final MathContext mathContext;
@NotNull
public static class Result implements CharSequence { public final MathContext mathContext;
@NotNull public static class Result implements CharSequence {
private final String string;
@NotNull
private final int offset; private final String string;
public Result(@NotNull String string, int offset) { private final int offset;
this.string = string;
this.offset = offset; public Result(@NotNull String string, int offset) {
} this.string = string;
this.offset = offset;
@Override }
public int length() {
return string.length(); @Override
} public int length() {
return string.length();
@Override }
public char charAt(int i) {
return string.charAt(i); @Override
} public char charAt(int i) {
return string.charAt(i);
@Override }
public CharSequence subSequence(int i, int i1) {
return string.subSequence(i, i1); @Override
} public CharSequence subSequence(int i, int i1) {
return string.subSequence(i, i1);
@Override }
public String toString() {
return string; @Override
} public String toString() {
return string;
public int getOffset() { }
return offset;
} public int getOffset() {
} return offset;
}
private final int color; }
private final int colorRed;
private final int colorGreen; private final int color;
private final int colorBlue; private final int colorRed;
private final boolean formatNumber; private final int colorGreen;
private final int colorBlue;
public TextHighlighter(int baseColor, boolean formatNumber, @NotNull MathContext mathContext) { private final boolean formatNumber;
this.color = baseColor;
this.formatNumber = formatNumber; public TextHighlighter(int baseColor, boolean formatNumber, @NotNull MathContext mathContext) {
this.mathContext = mathContext; this.color = baseColor;
//this.colorRed = Color.red(baseColor); this.formatNumber = formatNumber;
this.colorRed = (baseColor >> 16) & 0xFF; this.mathContext = mathContext;
//this.colorGreen = Color.green(baseColor); //this.colorRed = Color.red(baseColor);
this.colorGreen = (color >> 8) & 0xFF; this.colorRed = (baseColor >> 16) & 0xFF;
//this.colorBlue = Color.blue(baseColor); //this.colorGreen = Color.green(baseColor);
this.colorBlue = color & 0xFF; this.colorGreen = (color >> 8) & 0xFF;
} //this.colorBlue = Color.blue(baseColor);
this.colorBlue = color & 0xFF;
@NotNull }
@Override
public Result process(@NotNull String text) throws CalculatorParseException { @NotNull
final String result; @Override
public Result process(@NotNull String text) throws CalculatorParseException {
int maxNumberOfOpenGroupSymbols = 0; final String result;
int numberOfOpenGroupSymbols = 0;
int maxNumberOfOpenGroupSymbols = 0;
final StringBuilder text1 = new StringBuilder(); int numberOfOpenGroupSymbols = 0;
int resultOffset = 0; final StringBuilder text1 = new StringBuilder();
final AbstractNumberBuilder numberBuilder; int resultOffset = 0;
if (!formatNumber) {
numberBuilder = new LiteNumberBuilder(CalculatorEngine.instance.getEngine()); final AbstractNumberBuilder numberBuilder;
} else { if (!formatNumber) {
numberBuilder = new NumberBuilder(CalculatorEngine.instance.getEngine()); numberBuilder = new LiteNumberBuilder(CalculatorEngine.instance.getEngine());
} } else {
for (int i = 0; i < text.length(); i++) { numberBuilder = new NumberBuilder(CalculatorEngine.instance.getEngine());
MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode()); }
for (int i = 0; i < text.length(); i++) {
if (numberBuilder instanceof NumberBuilder) { MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode());
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
((NumberBuilder) numberBuilder).process(text1, mathType, numberOffset); if (numberBuilder instanceof NumberBuilder) {
resultOffset += numberOffset.getObject(); final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
} else { ((NumberBuilder) numberBuilder).process(text1, mathType, numberOffset);
((LiteNumberBuilder) numberBuilder).process(mathType); resultOffset += numberOffset.getObject();
} } else {
((LiteNumberBuilder) numberBuilder).process(mathType);
final String match = mathType.getMatch(); }
switch (mathType.getMathType()) {
case open_group_symbol: final String match = mathType.getMatch();
numberOfOpenGroupSymbols++; switch (mathType.getMathType()) {
maxNumberOfOpenGroupSymbols = Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols); case open_group_symbol:
text1.append(text.charAt(i)); numberOfOpenGroupSymbols++;
break; maxNumberOfOpenGroupSymbols = Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols);
case close_group_symbol: text1.append(text.charAt(i));
numberOfOpenGroupSymbols--; break;
text1.append(text.charAt(i)); case close_group_symbol:
break; numberOfOpenGroupSymbols--;
case operator: text1.append(text.charAt(i));
text1.append(match); break;
if (match.length() > 1) { case operator:
i += match.length() - 1; text1.append(match);
} if (match.length() > 1) {
break; i += match.length() - 1;
case function: }
i = processHighlightedText(text1, i, match, "i", null); break;
break; case function:
case constant: i = processHighlightedText(text1, i, match, "i", null);
i = processHighlightedText(text1, i, match, "b", null); break;
break; case constant:
case numeral_base: i = processHighlightedText(text1, i, match, "b", null);
i = processHighlightedText(text1, i, match, "b", null); break;
break; case numeral_base:
default: i = processHighlightedText(text1, i, match, "b", null);
if (mathType.getMathType() == MathType.text || match.length() <= 1) { break;
text1.append(text.charAt(i)); default:
} else { if (mathType.getMathType() == MathType.text || match.length() <= 1) {
text1.append(match); text1.append(text.charAt(i));
i += match.length() - 1; } else {
} text1.append(match);
} i += match.length() - 1;
} }
}
if (numberBuilder instanceof NumberBuilder) { }
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
((NumberBuilder) numberBuilder).processNumber(text1, numberOffset); if (numberBuilder instanceof NumberBuilder) {
resultOffset += numberOffset.getObject(); final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
} ((NumberBuilder) numberBuilder).processNumber(text1, numberOffset);
resultOffset += numberOffset.getObject();
if (maxNumberOfOpenGroupSymbols > 0) { }
final StringBuilder text2 = new StringBuilder(); if (maxNumberOfOpenGroupSymbols > 0) {
String s = text1.toString(); final StringBuilder text2 = new StringBuilder();
int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
for (; i < s.length(); i++) { String s = text1.toString();
text2.append(s.charAt(i)); int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
} for (; i < s.length(); i++) {
text2.append(s.charAt(i));
//Log.d(CalculatorEditor.class.getName(), text2.toString()); }
result = text2.toString(); //Log.d(CalculatorEditor.class.getName(), text2.toString());
} else {
result = text1.toString(); result = text2.toString();
} } else {
result = text1.toString();
return new Result(result, resultOffset); }
}
return new Result(result, resultOffset);
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String match, @NotNull String tag, @Nullable Map<String, String> tagAttributes) { }
result.append("<").append(tag);
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String match, @NotNull String tag, @Nullable Map<String, String> tagAttributes) {
if (tagAttributes != null) { result.append("<").append(tag);
for (Map.Entry<String, String> entry : tagAttributes.entrySet()) {
// attr1="attr1_value" attr2="attr2_value" if (tagAttributes != null) {
result.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\""); for (Map.Entry<String, String> entry : tagAttributes.entrySet()) {
} // attr1="attr1_value" attr2="attr2_value"
} result.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
}
result.append(">").append(match).append("</").append(tag).append(">"); }
if (match.length() > 1) {
return i + match.length() - 1; result.append(">").append(match).append("</").append(tag).append(">");
} else { if (match.length() > 1) {
return i; return i + match.length() - 1;
} } else {
} return i;
}
private int processBracketGroup(@NotNull StringBuilder result, @NotNull String s, int i, int numberOfOpenings, int maxNumberOfGroups) { }
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">"); private int processBracketGroup(@NotNull StringBuilder result, @NotNull String s, int i, int numberOfOpenings, int maxNumberOfGroups) {
for (; i < s.length(); i++) { result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
char ch = s.charAt(i);
for (; i < s.length(); i++) {
if (MathType.open_group_symbol.getTokens().contains(String.valueOf(ch))) { char ch = s.charAt(i);
result.append(ch);
result.append("</font>"); if (MathType.open_group_symbol.getTokens().contains(String.valueOf(ch))) {
i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups); result.append(ch);
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">"); result.append("</font>");
if (i < s.length() && MathType.close_group_symbol.getTokens().contains(String.valueOf(s.charAt(i)))) { i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups);
result.append(s.charAt(i)); result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
} if (i < s.length() && MathType.close_group_symbol.getTokens().contains(String.valueOf(s.charAt(i)))) {
} else if (MathType.close_group_symbol.getTokens().contains(String.valueOf(ch))) { result.append(s.charAt(i));
break; }
} else { } else if (MathType.close_group_symbol.getTokens().contains(String.valueOf(ch))) {
result.append(ch); break;
} } else {
} result.append(ch);
}
result.append("</font>"); }
result.append("</font>");
return i;
}
return i;
private String getColor(int totalNumberOfOpenings, int numberOfOpenings) { }
double c = 0.8;
private String getColor(int totalNumberOfOpenings, int numberOfOpenings) {
int offset = ((int) (255 * c)) * numberOfOpenings / (totalNumberOfOpenings + 1); double c = 0.8;
// for tests: int offset = ((int) (255 * c)) * numberOfOpenings / (totalNumberOfOpenings + 1);
// innt result = Color.rgb(BASE_COLOUR_RED_COMPONENT - offset, BASE_COLOUR_GREEN_COMPONENT - offset, BASE_COLOUR_BLUE_COMPONENT - offset);
int result = (0xFF << 24) | ((colorRed - offset) << 16) | ((colorGreen - offset) << 8) | (colorBlue - offset); // for tests:
// innt result = Color.rgb(BASE_COLOUR_RED_COMPONENT - offset, BASE_COLOUR_GREEN_COMPONENT - offset, BASE_COLOUR_BLUE_COMPONENT - offset);
return "#" + Integer.toHexString(result).substring(2); int result = (0xFF << 24) | ((colorRed - offset) << 16) | ((colorGreen - offset) << 8) | (colorBlue - offset);
}
} return "#" + Integer.toHexString(result).substring(2);
}
}

View File

@ -1,137 +1,137 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.MathEngine; import jscl.MathEngine;
import jscl.NumeralBase; import jscl.NumeralBase;
import junit.framework.Assert; import junit.framework.Assert;
import org.junit.Test; import org.junit.Test;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.view.TextHighlighter; import org.solovyev.android.calculator.view.TextHighlighter;
import java.util.Date; import java.util.Date;
import java.util.Random; import java.util.Random;
/** /**
* User: serso * User: serso
* Date: 10/12/11 * Date: 10/12/11
* Time: 10:07 PM * Time: 10:07 PM
*/ */
public class TextHighlighterTest { public class TextHighlighterTest {
@Test @Test
public void testProcess() throws Exception { public void testProcess() throws Exception {
TextProcessor<?, String> textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance); TextProcessor<?, String> textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
final Random random = new Random(new Date().getTime()); final Random random = new Random(new Date().getTime());
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
for (int j = 0; j < 1000; j++) { for (int j = 0; j < 1000; j++) {
sb.append(random.nextBoolean() ? "(" : ")"); sb.append(random.nextBoolean() ? "(" : ")");
} }
try { try {
textHighlighter.process(sb.toString()); textHighlighter.process(sb.toString());
} catch (Exception e) { } catch (Exception e) {
System.out.println(sb.toString()); System.out.println(sb.toString());
throw e; throw e;
} }
} }
Assert.assertEquals("<font color=\"#000000\"></font>)(((())())", textHighlighter.process(")(((())())").toString()); Assert.assertEquals("<font color=\"#000000\"></font>)(((())())", textHighlighter.process(")(((())())").toString());
Assert.assertEquals(")", textHighlighter.process(")").toString()); Assert.assertEquals(")", textHighlighter.process(")").toString());
Assert.assertEquals(")()(", textHighlighter.process(")()(").toString()); Assert.assertEquals(")()(", textHighlighter.process(")()(").toString());
textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance); textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance);
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString()); Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString()); Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString()); Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString());
Assert.assertEquals("1E3", textHighlighter.process("1E3").toString()); Assert.assertEquals("1E3", textHighlighter.process("1E3").toString());
Assert.assertEquals("2<b>0x:</b>", textHighlighter.process("20x:").toString()); Assert.assertEquals("2<b>0x:</b>", textHighlighter.process("20x:").toString());
Assert.assertEquals("20g", textHighlighter.process("20g").toString()); Assert.assertEquals("20g", textHighlighter.process("20g").toString());
Assert.assertEquals("22g", textHighlighter.process("22g").toString()); Assert.assertEquals("22g", textHighlighter.process("22g").toString());
Assert.assertEquals("20ю", textHighlighter.process("20ю").toString()); Assert.assertEquals("20ю", textHighlighter.process("20ю").toString());
Assert.assertEquals("20ъ", textHighlighter.process("20ъ").toString()); Assert.assertEquals("20ъ", textHighlighter.process("20ъ").toString());
Assert.assertEquals("3!!", textHighlighter.process("3!!").toString()); Assert.assertEquals("3!!", textHighlighter.process("3!!").toString());
Assert.assertEquals("2", textHighlighter.process("2").toString()); Assert.assertEquals("2", textHighlighter.process("2").toString());
Assert.assertEquals("21", textHighlighter.process("21").toString()); Assert.assertEquals("21", textHighlighter.process("21").toString());
Assert.assertEquals("214", textHighlighter.process("214").toString()); Assert.assertEquals("214", textHighlighter.process("214").toString());
Assert.assertEquals("2 145", textHighlighter.process("2 145").toString()); Assert.assertEquals("2 145", textHighlighter.process("2 145").toString());
Assert.assertEquals("1 000 000E3", textHighlighter.process("1000000E3").toString()); Assert.assertEquals("1 000 000E3", textHighlighter.process("1000000E3").toString());
Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString()); Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString());
Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString()); Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString());
Assert.assertEquals("-1 000 000E-30000", textHighlighter.process("-1000000E-30000").toString()); Assert.assertEquals("-1 000 000E-30000", textHighlighter.process("-1000000E-30000").toString());
textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance); textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
textHighlighter.process("cannot calculate 3^10^10 !!!\n" + textHighlighter.process("cannot calculate 3^10^10 !!!\n" +
" unable to enter 0. FIXED\n" + " unable to enter 0. FIXED\n" +
" empty display in Xperia Rayo\n" + " empty display in Xperia Rayo\n" +
" check привиденная FIXED\n" + " check привиденная FIXED\n" +
" set display result only if text in editor was not changed FIXED\n" + " set display result only if text in editor was not changed FIXED\n" +
" shift M text to the left\n" + " shift M text to the left\n" +
" do not show SYNTAX ERROR always (may be show send clock?q) FIXED\n" + " do not show SYNTAX ERROR always (may be show send clock?q) FIXED\n" +
" ln(8)*log(8) => ln(8)*og(8) FIXED\n" + " ln(8)*log(8) => ln(8)*og(8) FIXED\n" +
" copy/paste ln(8)*log(8)\n" + " copy/paste ln(8)*log(8)\n" +
" 6!^2 ERROR"); " 6!^2 ERROR");
Assert.assertEquals("<font color=\"#000000\"><i>sin</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("sin(2)").toString()); Assert.assertEquals("<font color=\"#000000\"><i>sin</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("sin(2)").toString());
Assert.assertEquals("<font color=\"#000000\"><i>atanh</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("atanh(2)").toString()); Assert.assertEquals("<font color=\"#000000\"><i>atanh</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("atanh(2)").toString());
Assert.assertEquals("<b>0x:</b>E", textHighlighter.process("0x:E").toString()); Assert.assertEquals("<b>0x:</b>E", textHighlighter.process("0x:E").toString());
Assert.assertEquals("<b>0x:</b>6F", textHighlighter.process("0x:6F").toString()); Assert.assertEquals("<b>0x:</b>6F", textHighlighter.process("0x:6F").toString());
Assert.assertEquals("<b>0x:</b>6F.", textHighlighter.process("0x:6F.").toString()); Assert.assertEquals("<b>0x:</b>6F.", textHighlighter.process("0x:6F.").toString());
Assert.assertEquals("<b>0x:</b>6F.2", textHighlighter.process("0x:6F.2").toString()); Assert.assertEquals("<b>0x:</b>6F.2", textHighlighter.process("0x:6F.2").toString());
Assert.assertEquals("<b>0x:</b>6F.B", textHighlighter.process("0x:6F.B").toString()); Assert.assertEquals("<b>0x:</b>6F.B", textHighlighter.process("0x:6F.B").toString());
Assert.assertEquals("<b>0x:</b>006F.B", textHighlighter.process("0x:006F.B").toString()); Assert.assertEquals("<b>0x:</b>006F.B", textHighlighter.process("0x:006F.B").toString());
Assert.assertEquals("<b>0x:</b>0", textHighlighter.process("0x:0").toString()); Assert.assertEquals("<b>0x:</b>0", textHighlighter.process("0x:0").toString());
Assert.assertEquals("<b>0x:</b>FF33233FFE", textHighlighter.process("0x:FF33233FFE").toString()); Assert.assertEquals("<b>0x:</b>FF33233FFE", textHighlighter.process("0x:FF33233FFE").toString());
Assert.assertEquals("<b>0x:</b>FF33 233 FFE", textHighlighter.process("0x:FF33 233 FFE").toString()); Assert.assertEquals("<b>0x:</b>FF33 233 FFE", textHighlighter.process("0x:FF33 233 FFE").toString());
final MathEngine me = CalculatorEngine.instance.getEngine(); final MathEngine me = CalculatorEngine.instance.getEngine();
try { try {
me.setNumeralBase(NumeralBase.hex); me.setNumeralBase(NumeralBase.hex);
Assert.assertEquals("E", textHighlighter.process("E").toString()); Assert.assertEquals("E", textHighlighter.process("E").toString());
Assert.assertEquals(".E", textHighlighter.process(".E").toString()); Assert.assertEquals(".E", textHighlighter.process(".E").toString());
Assert.assertEquals("E+", textHighlighter.process("E+").toString()); Assert.assertEquals("E+", textHighlighter.process("E+").toString());
Assert.assertEquals("E.", textHighlighter.process("E.").toString()); Assert.assertEquals("E.", textHighlighter.process("E.").toString());
Assert.assertEquals(".E.", textHighlighter.process(".E.").toString()); Assert.assertEquals(".E.", textHighlighter.process(".E.").toString());
Assert.assertEquals("6F", textHighlighter.process("6F").toString()); Assert.assertEquals("6F", textHighlighter.process("6F").toString());
Assert.assertEquals("6F", textHighlighter.process("6F").toString()); Assert.assertEquals("6F", textHighlighter.process("6F").toString());
Assert.assertEquals("6F.", textHighlighter.process("6F.").toString()); Assert.assertEquals("6F.", textHighlighter.process("6F.").toString());
Assert.assertEquals("6F.2", textHighlighter.process("6F.2").toString()); Assert.assertEquals("6F.2", textHighlighter.process("6F.2").toString());
Assert.assertEquals("6F.B", textHighlighter.process("6F.B").toString()); Assert.assertEquals("6F.B", textHighlighter.process("6F.B").toString());
Assert.assertEquals("006F.B", textHighlighter.process("006F.B").toString()); Assert.assertEquals("006F.B", textHighlighter.process("006F.B").toString());
} finally { } finally {
me.setNumeralBase(NumeralBase.dec); me.setNumeralBase(NumeralBase.dec);
} }
Assert.assertEquals("<b>0b:</b>110101", textHighlighter.process("0b:110101").toString()); Assert.assertEquals("<b>0b:</b>110101", textHighlighter.process("0b:110101").toString());
Assert.assertEquals("<b>0b:</b>110101.", textHighlighter.process("0b:110101.").toString()); Assert.assertEquals("<b>0b:</b>110101.", textHighlighter.process("0b:110101.").toString());
Assert.assertEquals("<b>0b:</b>110101.101", textHighlighter.process("0b:110101.101").toString()); Assert.assertEquals("<b>0b:</b>110101.101", textHighlighter.process("0b:110101.101").toString());
Assert.assertEquals("<b>0b:</b>11010100.1", textHighlighter.process("0b:11010100.1").toString()); Assert.assertEquals("<b>0b:</b>11010100.1", textHighlighter.process("0b:11010100.1").toString());
Assert.assertEquals("<b>0b:</b>110101.0", textHighlighter.process("0b:110101.0").toString()); Assert.assertEquals("<b>0b:</b>110101.0", textHighlighter.process("0b:110101.0").toString());
Assert.assertEquals("<b>0b:</b>0", textHighlighter.process("0b:0").toString()); Assert.assertEquals("<b>0b:</b>0", textHighlighter.process("0b:0").toString());
Assert.assertEquals("<b>0b:</b>1010100101111010101001", textHighlighter.process("0b:1010100101111010101001").toString()); Assert.assertEquals("<b>0b:</b>1010100101111010101001", textHighlighter.process("0b:1010100101111010101001").toString());
Assert.assertEquals("<b>0b:</b>101 010 01 0 111 1 0 10101001", textHighlighter.process("0b:101 010 01 0 111 1 0 10101001").toString()); Assert.assertEquals("<b>0b:</b>101 010 01 0 111 1 0 10101001", textHighlighter.process("0b:101 010 01 0 111 1 0 10101001").toString());
try { try {
me.setNumeralBase(NumeralBase.bin); me.setNumeralBase(NumeralBase.bin);
Assert.assertEquals("110101", textHighlighter.process("110101").toString()); Assert.assertEquals("110101", textHighlighter.process("110101").toString());
Assert.assertEquals("110101.", textHighlighter.process("110101.").toString()); Assert.assertEquals("110101.", textHighlighter.process("110101.").toString());
Assert.assertEquals("110101.101", textHighlighter.process("110101.101").toString()); Assert.assertEquals("110101.101", textHighlighter.process("110101.101").toString());
Assert.assertEquals("11010100.1", textHighlighter.process("11010100.1").toString()); Assert.assertEquals("11010100.1", textHighlighter.process("11010100.1").toString());
Assert.assertEquals("110101.0", textHighlighter.process("110101.0").toString()); Assert.assertEquals("110101.0", textHighlighter.process("110101.0").toString());
Assert.assertEquals("0", textHighlighter.process("0").toString()); Assert.assertEquals("0", textHighlighter.process("0").toString());
Assert.assertEquals("1010100101111010101001", textHighlighter.process("1010100101111010101001").toString()); Assert.assertEquals("1010100101111010101001", textHighlighter.process("1010100101111010101001").toString());
Assert.assertEquals("101 010 01 0 111 1 0 10101001", textHighlighter.process("101 010 01 0 111 1 0 10101001").toString()); Assert.assertEquals("101 010 01 0 111 1 0 10101001", textHighlighter.process("101 010 01 0 111 1 0 10101001").toString());
} finally { } finally {
me.setNumeralBase(NumeralBase.dec); me.setNumeralBase(NumeralBase.dec);
} }
} }
} }

View File

@ -1,443 +1,444 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator.model;
import jscl.AngleUnit; import jscl.AngleUnit;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.NumeralBase; import jscl.NumeralBase;
import jscl.math.Expression; import jscl.math.Expression;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.math.function.CustomFunction; import jscl.math.function.CustomFunction;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.jscl.JsclOperation;
import java.text.DecimalFormatSymbols;
import java.util.Locale; import java.text.DecimalFormatSymbols;
import java.util.Locale;
import static junit.framework.Assert.fail;
import static junit.framework.Assert.fail;
/**
* User: serso /**
* Date: 9/17/11 * User: serso
* Time: 9:47 PM * Date: 9/17/11
*/ * Time: 9:47 PM
*/
public class CalculatorEngineTest {
public class CalculatorEngineTest {
@BeforeClass
public static void setUp() throws Exception { @BeforeClass
CalculatorEngine.instance.init(null, null); public static void setUp() throws Exception {
CalculatorEngine.instance.setPrecision(3); CalculatorEngine.instance.init(null, null);
CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl()); CalculatorEngine.instance.setPrecision(3);
} CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl());
}
@Test
public void testDegrees() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testDegrees() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
try { final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
cm.getEngine().setAngleUnits(AngleUnit.rad); try {
cm.setPrecision(3); cm.getEngine().setAngleUnits(AngleUnit.rad);
try { cm.setPrecision(3);
Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "°")); try {
fail(); Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "°"));
} catch (CalculatorParseException e) { fail();
} catch (CalculatorParseException e) {
}
}
Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "").getResult());
Assert.assertEquals("0.349", cm.evaluate(JsclOperation.numeric, "20.0°").getResult()); Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "").getResult());
Assert.assertEquals("0.5", cm.evaluate(JsclOperation.numeric, "sin(30°)").getResult()); Assert.assertEquals("0.349", cm.evaluate(JsclOperation.numeric, "20.0°").getResult());
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(sin(30°))").getResult()); Assert.assertEquals("0.5", cm.evaluate(JsclOperation.numeric, "sin(30°)").getResult());
Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.numeric, "∂(cos(t),t,t,1°)").getResult()); Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(sin(30°))").getResult());
Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.numeric, "∂(cos(t),t,t,1°)").getResult());
Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.simplify, "∂(cos(t),t,t,1°)").getResult());
} finally { Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.simplify, "∂(cos(t),t,t,1°)").getResult());
cm.getEngine().setAngleUnits(defaultAngleUnit); } finally {
} cm.getEngine().setAngleUnits(defaultAngleUnit);
} }
}
@Test
public void testLongExecution() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testLongExecution() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
try {
cm.evaluate(JsclOperation.numeric, "3^10^10^10"); try {
Assert.fail(); cm.evaluate(JsclOperation.numeric, "3^10^10^10");
} catch (CalculatorParseException e) { Assert.fail();
if (e.getMessageCode().equals(Messages.msg_3)) { } catch (CalculatorParseException e) {
if (e.getMessageCode().equals(Messages.msg_3)) {
} else {
System.out.print(e.getCause().getMessage()); } else {
Assert.fail(); System.out.print(e.getCause().getMessage());
} Assert.fail();
} }
}
try {
cm.evaluate(JsclOperation.numeric, "9999999!"); try {
Assert.fail(); cm.evaluate(JsclOperation.numeric, "9999999!");
} catch (CalculatorParseException e) { Assert.fail();
if (e.getMessageCode().equals(Messages.msg_3)) { } catch (CalculatorParseException e) {
if (e.getMessageCode().equals(Messages.msg_3)) {
} else {
System.out.print(e.getCause().getMessage()); } else {
Assert.fail(); System.out.print(e.getCause().getMessage());
} Assert.fail();
} }
}
/*final long start = System.currentTimeMillis();
try { /*final long start = System.currentTimeMillis();
cm.evaluate(JsclOperation.numeric, "3^10^10^10"); try {
Assert.fail(); cm.evaluate(JsclOperation.numeric, "3^10^10^10");
} catch (ParseException e) { Assert.fail();
if (e.getMessage().startsWith("Too long calculation")) { } catch (ParseException e) {
final long end = System.currentTimeMillis(); if (e.getMessage().startsWith("Too long calculation")) {
Assert.assertTrue(end - start < 1000); final long end = System.currentTimeMillis();
} else { Assert.assertTrue(end - start < 1000);
Assert.fail(); } else {
} Assert.fail();
}*/ }
}*/
}
}
@Test
public void testEvaluate() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testEvaluate() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
Assert.assertEquals("cos(t)+10%", cm.evaluate(JsclOperation.simplify, "cos(t)+10%").getResult());
Assert.assertEquals("cos(t)+10%", cm.evaluate(JsclOperation.simplify, "cos(t)+10%").getResult());
final Generic expression = cm.getEngine().simplifyGeneric("cos(t)+10%");
expression.substitute(new Constant("t"), Expression.valueOf(100d)); final Generic expression = cm.getEngine().simplifyGeneric("cos(t)+10%");
expression.substitute(new Constant("t"), Expression.valueOf(100d));
Assert.assertEquals("it", cm.evaluate(JsclOperation.simplify, "it").getResult());
Assert.assertEquals("10%", cm.evaluate(JsclOperation.simplify, "10%").getResult()); Assert.assertEquals("it", cm.evaluate(JsclOperation.simplify, "it").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult()); Assert.assertEquals("10%", cm.evaluate(JsclOperation.simplify, "10%").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq( 1, 1)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.simplify, "eq( 1, 1)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq( 1, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lg(10)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.simplify, "eq( 1, 1)").getResult());
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "2+2").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lg(10)").getResult());
final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits(); Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "2+2").getResult());
try { final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
cm.getEngine().setAngleUnits(AngleUnit.rad); try {
Assert.assertEquals("-0.757", cm.evaluate(JsclOperation.numeric, "sin(4)").getResult()); cm.getEngine().setAngleUnits(AngleUnit.rad);
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(0.5)").getResult()); Assert.assertEquals("-0.757", cm.evaluate(JsclOperation.numeric, "sin(4)").getResult());
Assert.assertEquals("-0.396", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)").getResult()); Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(0.5)").getResult());
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult()); Assert.assertEquals("-0.396", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)").getResult());
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult()); Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult());
} finally { Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult());
cm.getEngine().setAngleUnits(defaultAngleUnit); } finally {
} cm.getEngine().setAngleUnits(defaultAngleUnit);
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "e^2").getResult()); }
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(1)^2").getResult()); Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "e^2").getResult());
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(2)").getResult()); Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(1)^2").getResult());
Assert.assertEquals("2+i", cm.evaluate(JsclOperation.numeric, "2*1+√(-1)").getResult()); Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(2)").getResult());
try { Assert.assertEquals("2+i", cm.evaluate(JsclOperation.numeric, "2*1+√(-1)").getResult());
cm.getEngine().setAngleUnits(AngleUnit.rad); try {
Assert.assertEquals("0.921+Πi", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))").getResult()); cm.getEngine().setAngleUnits(AngleUnit.rad);
Assert.assertEquals("-3.41+3.41i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)").getResult()); Assert.assertEquals("0.921+Πi", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))").getResult());
} finally { Assert.assertEquals("-3.41+3.41i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)").getResult());
cm.getEngine().setAngleUnits(defaultAngleUnit); } finally {
} cm.getEngine().setAngleUnits(defaultAngleUnit);
Assert.assertEquals("7.389i", cm.evaluate(JsclOperation.numeric, "iexp(2)").getResult()); }
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)").getResult()); Assert.assertEquals("7.389i", cm.evaluate(JsclOperation.numeric, "iexp(2)").getResult());
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)").getResult()); Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)").getResult());
Assert.assertEquals("2-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i").getResult()); Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)").getResult());
Assert.assertEquals("-2-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i").getResult()); Assert.assertEquals("2-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i").getResult());
Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getResult()); Assert.assertEquals("-2-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i").getResult());
Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getResult()); Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getResult());
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getResult()); Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getResult());
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getResult());
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getResult());
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getResult()); junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getResult());
junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getResult()); junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getResult());
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getResult()); junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getResult());
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getResult()); junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getResult());
junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "(3!)!").getResult()); junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getResult());
junit.framework.Assert.assertEquals("36", Expression.valueOf("3!^2").numeric().toString()); junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "(3!)!").getResult());
junit.framework.Assert.assertEquals("3", Expression.valueOf("cubic(27)").numeric().toString()); junit.framework.Assert.assertEquals("36", Expression.valueOf("3!^2").numeric().toString());
try { junit.framework.Assert.assertEquals("3", Expression.valueOf("cubic(27)").numeric().toString());
junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult()); try {
fail(); junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult());
} catch (CalculatorParseException e) { fail();
} } catch (CalculatorParseException e) {
}
junit.framework.Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "(π/π)!").getResult());
junit.framework.Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "(π/π)!").getResult());
try {
junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "(-1)i!").getResult()); try {
fail(); junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "(-1)i!").getResult());
} catch (CalculatorParseException e) { fail();
} catch (CalculatorParseException e) {
}
junit.framework.Assert.assertEquals("24i", cm.evaluate(JsclOperation.numeric, "4!i").getResult()); }
junit.framework.Assert.assertEquals("24i", cm.evaluate(JsclOperation.numeric, "4!i").getResult());
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
try {
cm.getEngine().setAngleUnits(AngleUnit.rad); try {
Assert.assertEquals("0.451", cm.evaluate(JsclOperation.numeric, "acos(0.8999999999999811)").getResult()); cm.getEngine().setAngleUnits(AngleUnit.rad);
Assert.assertEquals("-0.959", cm.evaluate(JsclOperation.numeric, "sin(5)").getResult()); Assert.assertEquals("0.451", cm.evaluate(JsclOperation.numeric, "acos(0.8999999999999811)").getResult());
Assert.assertEquals("-4.795", cm.evaluate(JsclOperation.numeric, "sin(5)si").getResult()); Assert.assertEquals("-0.959", cm.evaluate(JsclOperation.numeric, "sin(5)").getResult());
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "sisin(5)si").getResult()); Assert.assertEquals("-4.795", cm.evaluate(JsclOperation.numeric, "sin(5)si").getResult());
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "si*sin(5)si").getResult()); Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "sisin(5)si").getResult());
Assert.assertEquals("-3.309", cm.evaluate(JsclOperation.numeric, "sisin(5si)si").getResult()); Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "si*sin(5)si").getResult());
} finally { Assert.assertEquals("-3.309", cm.evaluate(JsclOperation.numeric, "sisin(5si)si").getResult());
cm.getEngine().setAngleUnits(defaultAngleUnit); } finally {
} cm.getEngine().setAngleUnits(defaultAngleUnit);
}
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("s", 1d));
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult()); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("s", 1d));
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult());
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", 3.5d));
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k1", 4d)); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", 3.5d));
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "k11").getResult()); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k1", 4d));
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "k11").getResult());
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
Assert.assertEquals("11t", cm.evaluate(JsclOperation.numeric, "t11").getResult()); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
Assert.assertEquals("11et", cm.evaluate(JsclOperation.numeric, "t11e").getResult()); Assert.assertEquals("11t", cm.evaluate(JsclOperation.numeric, "t11").getResult());
Assert.assertEquals("", cm.evaluate(JsclOperation.numeric, "").getResult()); Assert.assertEquals("11et", cm.evaluate(JsclOperation.numeric, "t11e").getResult());
Assert.assertEquals("", cm.evaluate(JsclOperation.numeric, "Infinity").getResult()); Assert.assertEquals("", cm.evaluate(JsclOperation.numeric, "").getResult());
Assert.assertEquals("11∞t", cm.evaluate(JsclOperation.numeric, "t11∞").getResult()); Assert.assertEquals("", cm.evaluate(JsclOperation.numeric, "Infinity").getResult());
Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)").getResult()); Assert.assertEquals("11∞t", cm.evaluate(JsclOperation.numeric, "t11∞").getResult());
Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)").getResult());
Assert.assertEquals("100", cm.evaluate(JsclOperation.numeric, "0.1E3").getResult());
Assert.assertEquals("3.957", cm.evaluate(JsclOperation.numeric, "ln(8)lg(8)+ln(8)").getResult()); Assert.assertEquals("100", cm.evaluate(JsclOperation.numeric, "0.1E3").getResult());
Assert.assertEquals("3.957", cm.evaluate(JsclOperation.numeric, "ln(8)lg(8)+ln(8)").getResult());
Assert.assertEquals("0.933", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult());
Assert.assertEquals("0.933", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult());
try {
cm.getEngine().setNumeralBase(NumeralBase.hex); try {
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult()); cm.getEngine().setNumeralBase(NumeralBase.hex);
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "0x:E/0x:F").getResult()); Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult());
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "E/F").getResult()); Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "0x:E/0x:F").getResult());
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "E/F").getResult()); Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "E/F").getResult());
} finally { Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "E/F").getResult());
cm.getEngine().setNumeralBase(NumeralBase.dec); } finally {
} cm.getEngine().setNumeralBase(NumeralBase.dec);
}
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((0))))))").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((0))))))").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getResult());
/* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult());
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "(10+20)°").getResult()); /* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult());
Assert.assertEquals("1.047", cm.evaluate(JsclOperation.numeric, "(10+20)°*2").getResult()); Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "(10+20)°").getResult());
try { Assert.assertEquals("1.047", cm.evaluate(JsclOperation.numeric, "(10+20)°*2").getResult());
Assert.assertEquals("0.278", cm.evaluate(JsclOperation.numeric, "30°^2").getResult()); try {
junit.framework.Assert.fail(); Assert.assertEquals("0.278", cm.evaluate(JsclOperation.numeric, "30°^2").getResult());
} catch (ParseException e) { junit.framework.Assert.fail();
if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) { } catch (ParseException e) {
junit.framework.Assert.fail(); if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) {
} junit.framework.Assert.fail();
}*/ }
}*/
/* try {
cm.setTimeout(5000); /* try {
Assert.assertEquals("2", cm.evaluate(JsclOperation.numeric, "2!").getResult()); cm.setTimeout(5000);
} finally { Assert.assertEquals("2", cm.evaluate(JsclOperation.numeric, "2!").getResult());
cm.setTimeout(3000); } finally {
}*/ cm.setTimeout(3000);
}*/
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult()); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
Assert.assertEquals("2t", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult()); Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult());
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", "2")); Assert.assertEquals("2t", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult());
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult()); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", "2"));
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult()); Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult());
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult());
Assert.assertEquals("-x+x*ln(x)", cm.getEngine().simplify("∫(ln(x), x)"));
Assert.assertEquals("-(x-x*ln(x))/(ln(2)+ln(5))", cm.getEngine().simplify("∫(log(10, x), x)")); Assert.assertEquals("-x+x*ln(x)", cm.getEngine().simplify("∫(ln(x), x)"));
Assert.assertEquals("-(x-x*ln(x))/(ln(2)+ln(5))", cm.getEngine().simplify("∫(log(10, x), x)"));
Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(ln(10)/ln(x), x)"));
Assert.assertEquals("∫(ln(10)/ln(x), x)", Expression.valueOf("∫(log(x, 10), x)").expand().toString()); Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(ln(10)/ln(x), x)"));
Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(log(x, 10), x)")); Assert.assertEquals("∫(ln(10)/ln(x), x)", Expression.valueOf("∫(log(x, 10), x)").expand().toString());
} Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(log(x, 10), x)"));
}
@Test
public void testFormatting() throws Exception { @Test
final CalculatorEngine ce = CalculatorEngine.instance; public void testFormatting() throws Exception {
final CalculatorEngine ce = CalculatorEngine.instance;
Assert.assertEquals("12 345", ce.evaluate(JsclOperation.simplify, "12345").getResult());
Assert.assertEquals("12 345", ce.evaluate(JsclOperation.simplify, "12345").getResult());
}
}
@Test
public void testI() throws CalculatorParseException, CalculatorEvalException { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testI() throws CalculatorParseException, CalculatorEvalException {
final CalculatorEngine cm = CalculatorEngine.instance;
Assert.assertEquals("-i", cm.evaluate(JsclOperation.numeric, "i^3").getResult());
for (int i = 0; i < 1000; i++) { Assert.assertEquals("-i", cm.evaluate(JsclOperation.numeric, "i^3").getResult());
double real = (Math.random()-0.5) * 1000; for (int i = 0; i < 1000; i++) {
double imag = (Math.random()-0.5) * 1000; double real = (Math.random()-0.5) * 1000;
int exp = (int)(Math.random() * 10); double imag = (Math.random()-0.5) * 1000;
int exp = (int)(Math.random() * 10);
final StringBuilder sb = new StringBuilder();
sb.append(real); final StringBuilder sb = new StringBuilder();
if ( imag > 0 ) { sb.append(real);
sb.append("+"); if ( imag > 0 ) {
} sb.append("+");
sb.append(imag); }
sb.append("^").append(exp); sb.append(imag);
try { sb.append("^").append(exp);
cm.evaluate(JsclOperation.numeric, sb.toString()).getResult(); try {
} catch (Throwable e) { cm.evaluate(JsclOperation.numeric, sb.toString()).getResult();
fail(sb.toString()); } catch (Throwable e) {
} fail(sb.toString());
} }
} }
}
@Test
public void testEmptyFunction() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testEmptyFunction() throws Exception {
try { final CalculatorEngine cm = CalculatorEngine.instance;
cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))"); try {
Assert.fail(); cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))");
} catch (CalculatorParseException e) { Assert.fail();
} } catch (CalculatorParseException e) {
Assert.assertEquals("0.34+1.382i", cm.evaluate(JsclOperation.numeric, "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))").getResult()); }
try { Assert.assertEquals("0.34+1.382i", cm.evaluate(JsclOperation.numeric, "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))").getResult());
cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos())))))))))))))))))))))))))))))))))))"); try {
Assert.fail(); cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos())))))))))))))))))))))))))))))))))))");
} catch (CalculatorParseException e) { Assert.fail();
} } catch (CalculatorParseException e) {
}
final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
try { final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
cm.getEngine().setAngleUnits(AngleUnit.rad); try {
Assert.assertEquals("0.739", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))").getResult()); cm.getEngine().setAngleUnits(AngleUnit.rad);
} finally { Assert.assertEquals("0.739", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))").getResult());
cm.getEngine().setAngleUnits(defaultAngleUnit); } finally {
} cm.getEngine().setAngleUnits(defaultAngleUnit);
}
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult()); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult());
try {
cm.evaluate(JsclOperation.numeric, "sin"); try {
Assert.fail(); cm.evaluate(JsclOperation.numeric, "sin");
} catch (CalculatorParseException e) { Assert.fail();
} } catch (CalculatorParseException e) {
} }
}
@Test
public void testRounding() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testRounding() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
try {
DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault()); try {
decimalGroupSymbols.setDecimalSeparator('.'); DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault());
decimalGroupSymbols.setGroupingSeparator('\''); decimalGroupSymbols.setDecimalSeparator('.');
cm.setDecimalGroupSymbols(decimalGroupSymbols); decimalGroupSymbols.setGroupingSeparator('\'');
cm.setPrecision(2); cm.setDecimalGroupSymbols(decimalGroupSymbols);
Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult()); cm.setPrecision(2);
cm.setPrecision(10); Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult());
Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult()); cm.setPrecision(10);
Assert.assertEquals("123'456'789", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getResult()); Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult());
Assert.assertEquals("1'234'567'890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9").getResult()); Assert.assertEquals("123'456'789", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getResult());
} finally { Assert.assertEquals("1'234'567'890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9").getResult());
cm.setPrecision(3); } finally {
DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault()); cm.setPrecision(3);
decimalGroupSymbols.setDecimalSeparator('.'); DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault());
decimalGroupSymbols.setGroupingSeparator(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT.charAt(0)); decimalGroupSymbols.setDecimalSeparator('.');
cm.setDecimalGroupSymbols(decimalGroupSymbols); decimalGroupSymbols.setGroupingSeparator(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT.charAt(0));
} cm.setDecimalGroupSymbols(decimalGroupSymbols);
} }
}
@Test
public void testComparisonFunction() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testComparisonFunction() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1.0)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 1.000000000000001)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1.0)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 0)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 1.000000000000001)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 0)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lt(0, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 1)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lt(0, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 0)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 0)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(0, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(1, 1)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "gt(1, 0)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(1, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "gt(1, 0)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(0, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ne(1, 1)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(1, 0)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ne(1, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(1, 0)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(1, 1)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(0, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "le(1, 0)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(1, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "le(1, 0)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ge(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 1)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ge(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 0)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 0)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(0, 1)").getResult());
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1)").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(0, 1)").getResult());
//Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1.000000000000001)").getResult()); Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(1, 0)").getResult()); //Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1.000000000000001)").getResult());
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(1, 0)").getResult());
}
}
@Test
public void testNumeralSystems() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testNumeralSystems() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
Assert.assertEquals("11 259 375", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF").getResult());
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e").getResult()); Assert.assertEquals("11 259 375", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF").getResult());
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF").getResult()); Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e").getResult());
Assert.assertEquals("e", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF/0x:ABCDEF").getResult()); Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF").getResult());
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF").getResult()); Assert.assertEquals("e", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF/0x:ABCDEF").getResult());
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C").getResult()); Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF").getResult());
Assert.assertEquals("1 446 257 064 651.832", cm.evaluate(JsclOperation.numeric, "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) ").getResult()); Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C").getResult());
Assert.assertEquals("13", cm.evaluate(JsclOperation.numeric, "0b:1101").getResult()); Assert.assertEquals("1 446 257 064 651.832", cm.evaluate(JsclOperation.numeric, "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) ").getResult());
Assert.assertEquals("13", cm.evaluate(JsclOperation.numeric, "0b:1101").getResult());
try {
cm.evaluate(JsclOperation.numeric, "0b:π").getResult(); try {
Assert.fail(); cm.evaluate(JsclOperation.numeric, "0b:π").getResult();
} catch (CalculatorParseException e) { Assert.fail();
// ok } catch (CalculatorParseException e) {
} // ok
}
final NumeralBase defaultNumeralBase = cm.getEngine().getNumeralBase();
try{ final NumeralBase defaultNumeralBase = cm.getEngine().getNumeralBase();
cm.getEngine().setNumeralBase(NumeralBase.bin); try{
Assert.assertEquals("101", cm.evaluate(JsclOperation.numeric, "10+11").getResult()); cm.getEngine().setNumeralBase(NumeralBase.bin);
Assert.assertEquals("10/11", cm.evaluate(JsclOperation.numeric, "10/11").getResult()); Assert.assertEquals("101", cm.evaluate(JsclOperation.numeric, "10+11").getResult());
Assert.assertEquals("10/11", cm.evaluate(JsclOperation.numeric, "10/11").getResult());
cm.getEngine().setNumeralBase(NumeralBase.hex);
Assert.assertEquals("63 7B", cm.evaluate(JsclOperation.numeric, "56CE+CAD").getResult()); cm.getEngine().setNumeralBase(NumeralBase.hex);
Assert.assertEquals("E", cm.evaluate(JsclOperation.numeric, "E").getResult()); Assert.assertEquals("63 7B", cm.evaluate(JsclOperation.numeric, "56CE+CAD").getResult());
} finally { Assert.assertEquals("E", cm.evaluate(JsclOperation.numeric, "E").getResult());
cm.setNumeralBase(defaultNumeralBase); } finally {
} cm.setNumeralBase(defaultNumeralBase);
} }
}
@Test
public void testLog() throws Exception { @Test
final CalculatorEngine cm = CalculatorEngine.instance; public void testLog() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
Assert.assertEquals("", Expression.valueOf("1/0").numeric().toString());
Assert.assertEquals("", Expression.valueOf("ln(10)/ln(1)").numeric().toString()); Assert.assertEquals("", Expression.valueOf("1/0").numeric().toString());
Assert.assertEquals("", Expression.valueOf("ln(10)/ln(1)").numeric().toString());
// logarithm
Assert.assertEquals("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent()); // logarithm
Assert.assertEquals("", cm.evaluate(JsclOperation.numeric, "log(1, 10)").getResult()); Assert.assertEquals("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent());
Assert.assertEquals("3.322", cm.evaluate(JsclOperation.numeric, "log(2, 10)").getResult()); Assert.assertEquals("", cm.evaluate(JsclOperation.numeric, "log(1, 10)").getResult());
Assert.assertEquals("1.431", cm.evaluate(JsclOperation.numeric, "log(5, 10)").getResult()); Assert.assertEquals("3.322", cm.evaluate(JsclOperation.numeric, "log(2, 10)").getResult());
Assert.assertEquals("0.96", cm.evaluate(JsclOperation.numeric, "log(11, 10)").getResult()); Assert.assertEquals("1.431", cm.evaluate(JsclOperation.numeric, "log(5, 10)").getResult());
Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getResult()); Assert.assertEquals("0.96", cm.evaluate(JsclOperation.numeric, "log(11, 10)").getResult());
Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getResult()); Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getResult());
Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getResult());
}
} }
}

View File

@ -1,69 +1,70 @@
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator.model;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
import java.text.DecimalFormatSymbols;
import java.text.DecimalFormatSymbols;
/**
* User: serso /**
* Date: 10/20/11 * User: serso
* Time: 3:43 PM * Date: 10/20/11
*/ * Time: 3:43 PM
public class FromJsclSimplifyTextProcessorTest { */
public class FromJsclSimplifyTextProcessorTest {
@BeforeClass
public static void setUp() throws Exception { @BeforeClass
CalculatorEngine.instance.init(null, null); public static void setUp() throws Exception {
} CalculatorEngine.instance.init(null, null);
}
@Test
public void testProcess() throws Exception { @Test
FromJsclSimplifyTextProcessor tp = new FromJsclSimplifyTextProcessor(); public void testProcess() throws Exception {
//Assert.assertEquals("(e)", tp.process("(2.718281828459045)")); FromJsclSimplifyTextProcessor tp = new FromJsclSimplifyTextProcessor();
//Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045")); //Assert.assertEquals("(e)", tp.process("(2.718281828459045)"));
//Assert.assertEquals("((e)(e))", tp.process("((2.718281828459045)*(2.718281828459045))")); //Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045"));
DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(); //Assert.assertEquals("((e)(e))", tp.process("((2.718281828459045)*(2.718281828459045))"));
decimalGroupSymbols.setGroupingSeparator(' '); DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols();
CalculatorEngine.instance.setDecimalGroupSymbols(decimalGroupSymbols); decimalGroupSymbols.setGroupingSeparator(' ');
//Assert.assertEquals("123 456 789e", tp.process("123456789*2.718281828459045")); CalculatorEngine.instance.setDecimalGroupSymbols(decimalGroupSymbols);
//Assert.assertEquals("123 456 789e", tp.process("123 456 789 * 2.718281828459045")); //Assert.assertEquals("123 456 789e", tp.process("123456789*2.718281828459045"));
//Assert.assertEquals("t11e", tp.process("t11*2.718281828459045")); //Assert.assertEquals("123 456 789e", tp.process("123 456 789 * 2.718281828459045"));
//Assert.assertEquals("e", tp.process("2.718281828459045")); //Assert.assertEquals("t11e", tp.process("t11*2.718281828459045"));
//Assert.assertEquals("tee", tp.process("t2.718281828459045*2.718281828459045")); //Assert.assertEquals("e", tp.process("2.718281828459045"));
//Assert.assertEquals("tee", tp.process("t2.718281828459045*2.718281828459045"));
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t2.718281828459045", "2"));
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String)null)); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t2.718281828459045", "2"));
//Assert.assertEquals("t2.718281828459045e", tp.process("t2.718281828459045*2.718281828459045")); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String)null));
//Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045")); //Assert.assertEquals("t2.718281828459045e", tp.process("t2.718281828459045*2.718281828459045"));
Assert.assertEquals("t×", tp.process("t*")); //Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045"));
Assert.assertEquals("×t", tp.process("*t")); Assert.assertEquals("t×", tp.process("t*"));
Assert.assertEquals("t2", tp.process("t*2")); Assert.assertEquals("×t", tp.process("*t"));
Assert.assertEquals("2t", tp.process("2*t")); Assert.assertEquals("t2", tp.process("t*2"));
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null)); Assert.assertEquals("2t", tp.process("2*t"));
Assert.assertEquals("t×", tp.process("t*")); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
Assert.assertEquals("×t", tp.process("*t")); Assert.assertEquals("t×", tp.process("t*"));
Assert.assertEquals("×t", tp.process("*t"));
Assert.assertEquals("t2", tp.process("t*2"));
Assert.assertEquals("2t", tp.process("2*t")); Assert.assertEquals("t2", tp.process("t*2"));
Assert.assertEquals("2t", tp.process("2*t"));
Assert.assertEquals("t^2×2", tp.process("t^2*2"));
Assert.assertEquals("2t^2", tp.process("2*t^2")); Assert.assertEquals("t^2×2", tp.process("t^2*2"));
Assert.assertEquals("2t^2", tp.process("2*t^2"));
Assert.assertEquals("t^[2×2t]", tp.process("t^[2*2*t]"));
Assert.assertEquals("2t^2[2t]", tp.process("2*t^2[2*t]")); Assert.assertEquals("t^[2×2t]", tp.process("t^[2*2*t]"));
Assert.assertEquals("2t^2[2t]", tp.process("2*t^2[2*t]"));
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", (String) null));
Assert.assertEquals("(t+2k)[k+2t]", tp.process("(t+2*k)*[k+2*t]")); CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", (String) null));
Assert.assertEquals("(te+2k)e[k+2te]", tp.process("(t*e+2*k)*e*[k+2*t*e]")); Assert.assertEquals("(t+2k)[k+2t]", tp.process("(t+2*k)*[k+2*t]"));
Assert.assertEquals("(te+2k)e[k+2te]", tp.process("(t*e+2*k)*e*[k+2*t*e]"));
Assert.assertEquals("tlog(3)", tp.process("t*log(3)"));
Assert.assertEquals("t√(3)", tp.process("t*√(3)")); Assert.assertEquals("tlog(3)", tp.process("t*log(3)"));
Assert.assertEquals("20x", tp.process("20*x")); Assert.assertEquals("t√(3)", tp.process("t*√(3)"));
Assert.assertEquals("20x", tp.process("20x")); Assert.assertEquals("20x", tp.process("20*x"));
Assert.assertEquals("2×0x3", tp.process("2*0x3")); Assert.assertEquals("20x", tp.process("20x"));
Assert.assertEquals("2×0x:3", tp.process("2*0x:3")); Assert.assertEquals("2×0x3", tp.process("2*0x3"));
} Assert.assertEquals("2×0x:3", tp.process("2*0x:3"));
} }
}

View File

@ -1,146 +1,147 @@
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator.model;
import au.com.bytecode.opencsv.CSVReader; import au.com.bytecode.opencsv.CSVReader;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.MathEngine; import jscl.MathEngine;
import jscl.math.Expression; import jscl.math.Expression;
import jscl.text.ParseException; import jscl.text.ParseException;
import jscl.util.ExpressionGeneratorWithInput; import jscl.util.ExpressionGeneratorWithInput;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.common.Converter; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.Converter;
import java.io.InputStreamReader;
import java.util.ArrayList; import java.io.InputStreamReader;
import java.util.List; import java.util.ArrayList;
import java.util.List;
/**
* User: serso /**
* Date: 12/14/11 * User: serso
* Time: 4:16 PM * Date: 12/14/11
*/ * Time: 4:16 PM
public class NumeralBaseTest { */
public class NumeralBaseTest {
@BeforeClass
public static void setUp() throws Exception { @BeforeClass
CalculatorEngine.instance.init(null, null); public static void setUp() throws Exception {
CalculatorEngine.instance.setPrecision(3); CalculatorEngine.instance.init(null, null);
CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl()); CalculatorEngine.instance.setPrecision(3);
} CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl());
}
@Test
public void testConversion() throws Exception { @Test
CSVReader reader = null; public void testConversion() throws Exception {
try { CSVReader reader = null;
final MathEngine me = JsclMathEngine.instance; try {
final MathEngine me = JsclMathEngine.instance;
reader = new CSVReader(new InputStreamReader(NumeralBaseTest.class.getResourceAsStream("/org/solovyev/android/calculator/model/nb_table.csv")), '\t');
reader = new CSVReader(new InputStreamReader(NumeralBaseTest.class.getResourceAsStream("/org/solovyev/android/calculator/model/nb_table.csv")), '\t');
// skip first line
reader.readNext(); // skip first line
reader.readNext();
String[] line = reader.readNext();
for (; line != null; line = reader.readNext()) { String[] line = reader.readNext();
testExpression(line, new DummyExpression()); for (; line != null; line = reader.readNext()) {
testExpression(line, new Expression1()); testExpression(line, new DummyExpression());
testExpression(line, new Expression2()); testExpression(line, new Expression1());
testExpression(line, new Expression3()); testExpression(line, new Expression2());
testExpression(line, new Expression3());
final String dec = line[0].toUpperCase();
final String hex = "0x:" + line[1].toUpperCase(); final String dec = line[0].toUpperCase();
final String bin = "0b:" + line[2].toUpperCase(); final String hex = "0x:" + line[1].toUpperCase();
final String bin = "0b:" + line[2].toUpperCase();
final List<String> input = new ArrayList<String>();
input.add(dec); final List<String> input = new ArrayList<String>();
input.add(hex); input.add(dec);
input.add(bin); input.add(hex);
input.add(bin);
//System.out.println("Dec: " + dec);
//System.out.println("Hex: " + hex); //System.out.println("Dec: " + dec);
//System.out.println("Bin: " + bin); //System.out.println("Hex: " + hex);
//System.out.println("Bin: " + bin);
final ExpressionGeneratorWithInput eg = new ExpressionGeneratorWithInput(input, 20);
final List<String> expressions = eg.generate(); final ExpressionGeneratorWithInput eg = new ExpressionGeneratorWithInput(input, 20);
final List<String> expressions = eg.generate();
final String decExpression = expressions.get(0);
final String hexExpression = expressions.get(1); final String decExpression = expressions.get(0);
final String binExpression = expressions.get(2); final String hexExpression = expressions.get(1);
final String binExpression = expressions.get(2);
//System.out.println("Dec expression: " + decExpression);
//System.out.println("Hex expression: " + hexExpression); //System.out.println("Dec expression: " + decExpression);
//System.out.println("Bin expression: " + binExpression); //System.out.println("Hex expression: " + hexExpression);
//System.out.println("Bin expression: " + binExpression);
final String decResult = Expression.valueOf(decExpression).numeric().toString();
//System.out.println("Dec result: " + decResult); final String decResult = Expression.valueOf(decExpression).numeric().toString();
//System.out.println("Dec result: " + decResult);
final String hexResult = Expression.valueOf(hexExpression).numeric().toString();
//System.out.println("Hex result: " + hexResult); final String hexResult = Expression.valueOf(hexExpression).numeric().toString();
//System.out.println("Hex result: " + hexResult);
final String binResult = Expression.valueOf(binExpression).numeric().toString();
//System.out.println("Bin result: " + binResult); final String binResult = Expression.valueOf(binExpression).numeric().toString();
//System.out.println("Bin result: " + binResult);
Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult); Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
} Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult);
} finally { }
if (reader != null) { } finally {
reader.close(); if (reader != null) {
} reader.close();
} }
} }
}
public static void testExpression(@NotNull String[] line, @NotNull Converter<String, String> converter) throws ParseException, CalculatorEvalException, CalculatorParseException {
final String dec = line[0].toUpperCase(); public static void testExpression(@NotNull String[] line, @NotNull Converter<String, String> converter) throws ParseException, CalculatorEvalException, CalculatorParseException {
final String hex = "0x:" + line[1].toUpperCase(); final String dec = line[0].toUpperCase();
final String bin = "0b:" + line[2].toUpperCase(); final String hex = "0x:" + line[1].toUpperCase();
final String bin = "0b:" + line[2].toUpperCase();
final String decExpression = converter.convert(dec);
final String decResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, decExpression).getResult(); final String decExpression = converter.convert(dec);
final String hexExpression = converter.convert(hex); final String decResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, decExpression).getResult();
final String hexResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, hexExpression).getResult(); final String hexExpression = converter.convert(hex);
final String binExpression = converter.convert(bin); final String hexResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, hexExpression).getResult();
final String binResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, binExpression).getResult(); final String binExpression = converter.convert(bin);
final String binResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, binExpression).getResult();
Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult); Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
} Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult);
}
private static class DummyExpression implements Converter<String, String> {
private static class DummyExpression implements Converter<String, String> {
@NotNull
@Override @NotNull
public String convert(@NotNull String s) { @Override
return s; public String convert(@NotNull String s) {
} return s;
} }
}
private static class Expression1 implements Converter<String, String> {
private static class Expression1 implements Converter<String, String> {
@NotNull
@Override @NotNull
public String convert(@NotNull String s) { @Override
return s + "*" + s; public String convert(@NotNull String s) {
} return s + "*" + s;
} }
}
private static class Expression2 implements Converter<String, String> {
private static class Expression2 implements Converter<String, String> {
@NotNull
@Override @NotNull
public String convert(@NotNull String s) { @Override
return s + "*" + s + " * sin(" + s + ") - 0b:1101"; public String convert(@NotNull String s) {
} return s + "*" + s + " * sin(" + s + ") - 0b:1101";
} }
}
private static class Expression3 implements Converter<String, String> {
private static class Expression3 implements Converter<String, String> {
@NotNull
@Override @NotNull
public String convert(@NotNull String s) { @Override
return s + "*" + s + " * sin(" + s + ") - 0b:1101 + √(" + s + ") + exp ( " + s + ")"; public String convert(@NotNull String s) {
} return s + "*" + s + " * sin(" + s + ") - 0b:1101 + √(" + s + ") + exp ( " + s + ")";
} }
} }
}

View File

@ -1,161 +1,163 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.model; package org.solovyev.android.calculator.model;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.NumeralBase; import jscl.NumeralBase;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.solovyev.android.calculator.CalculatorParseException;
/** import org.solovyev.android.calculator.text.TextProcessor;
* User: serso
* Date: 9/26/11 /**
* Time: 12:13 PM * User: serso
*/ * Date: 9/26/11
public class ToJsclTextProcessorTest { * Time: 12:13 PM
*/
@BeforeClass public class ToJsclTextProcessorTest {
public static void setUp() throws Exception {
CalculatorEngine.instance.init(null, null); @BeforeClass
} public static void setUp() throws Exception {
CalculatorEngine.instance.init(null, null);
@Test }
public void testSpecialCases() throws CalculatorParseException {
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance(); @Test
Assert.assertEquals( "3^E10", preprocessor.process("3^E10").toString()); public void testSpecialCases() throws CalculatorParseException {
} final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
Assert.assertEquals( "3^E10", preprocessor.process("3^E10").toString());
@Test }
public void testProcess() throws Exception {
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance(); @Test
public void testProcess() throws Exception {
Assert.assertEquals( "", preprocessor.process("").toString()); final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
Assert.assertEquals( "()", preprocessor.process("[]").toString());
Assert.assertEquals( "()*()", preprocessor.process("[][]").toString()); Assert.assertEquals( "", preprocessor.process("").toString());
Assert.assertEquals( "()*(1)", preprocessor.process("[][1]").toString()); Assert.assertEquals( "()", preprocessor.process("[]").toString());
Assert.assertEquals( "(0)*(1)", preprocessor.process("[0][1]").toString()); Assert.assertEquals( "()*()", preprocessor.process("[][]").toString());
Assert.assertEquals( "(0)*(1E)", preprocessor.process("[0][1E]").toString()); Assert.assertEquals( "()*(1)", preprocessor.process("[][1]").toString());
Assert.assertEquals( "(0)*(1E1)", preprocessor.process("[0][1E1]").toString()); Assert.assertEquals( "(0)*(1)", preprocessor.process("[0][1]").toString());
Assert.assertEquals( "(0)*(1E-1)", preprocessor.process("[0][1E-1]").toString()); Assert.assertEquals( "(0)*(1E)", preprocessor.process("[0][1E]").toString());
Assert.assertEquals( "(0)*(1.E-1)", preprocessor.process("[0][1.E-1]").toString()); Assert.assertEquals( "(0)*(1E1)", preprocessor.process("[0][1E1]").toString());
Assert.assertEquals( "(0)*(2*E-1)", preprocessor.process("[0][2*E-1]").toString()); Assert.assertEquals( "(0)*(1E-1)", preprocessor.process("[0][1E-1]").toString());
Assert.assertEquals( "(0)*ln(1)*(2*E-1)", preprocessor.process("[0]ln(1)[2*E-1]").toString()); Assert.assertEquals( "(0)*(1.E-1)", preprocessor.process("[0][1.E-1]").toString());
Assert.assertEquals( "sin(4)*asin(0.5)*√(2)", preprocessor.process("sin(4)asin(0.5)√(2)").toString()); Assert.assertEquals( "(0)*(2*E-1)", preprocessor.process("[0][2*E-1]").toString());
Assert.assertEquals( "sin(4)*cos(5)", preprocessor.process("sin(4)cos(5)").toString()); Assert.assertEquals( "(0)*ln(1)*(2*E-1)", preprocessor.process("[0]ln(1)[2*E-1]").toString());
Assert.assertEquals( "π*sin(4)*π*cos(√(5))", preprocessor.process("πsin(4)πcos(√(5))").toString()); Assert.assertEquals( "sin(4)*asin(0.5)*√(2)", preprocessor.process("sin(4)asin(0.5)√(2)").toString());
Assert.assertEquals( "π*sin(4)+π*cos(√(5))", preprocessor.process("πsin(4)+πcos(√(5))").toString()); Assert.assertEquals( "sin(4)*cos(5)", preprocessor.process("sin(4)cos(5)").toString());
Assert.assertEquals( "π*sin(4)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4)+πcos(√(5+i))").toString()); Assert.assertEquals( "π*sin(4)*π*cos(√(5))", preprocessor.process("πsin(4)πcos(√(5))").toString());
Assert.assertEquals( "π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4.01)+πcos(√(5+i))").toString()); Assert.assertEquals( "π*sin(4)+π*cos(√(5))", preprocessor.process("πsin(4)+πcos(√(5))").toString());
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))").toString()); Assert.assertEquals( "π*sin(4)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4)+πcos(√(5+i))").toString());
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E2").toString()); Assert.assertEquals( "π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4.01)+πcos(√(5+i))").toString());
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E-2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E-2").toString()); Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))").toString());
Assert.assertEquals( "E2", preprocessor.process("E2").toString()); Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E2").toString());
Assert.assertEquals( "E-2", preprocessor.process("E-2").toString()); Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E-2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E-2").toString());
Assert.assertEquals( "E-1/2", preprocessor.process("E-1/2").toString()); Assert.assertEquals( "E2", preprocessor.process("E2").toString());
Assert.assertEquals( "E-1.2", preprocessor.process("E-1.2").toString()); Assert.assertEquals( "E-2", preprocessor.process("E-2").toString());
Assert.assertEquals( "E+1.2", preprocessor.process("E+1.2").toString()); Assert.assertEquals( "E-1/2", preprocessor.process("E-1/2").toString());
Assert.assertEquals( "E(-1.2)", preprocessor.process("E(-1.2)").toString()); Assert.assertEquals( "E-1.2", preprocessor.process("E-1.2").toString());
Assert.assertEquals( "EE", preprocessor.process("EE").toString()); Assert.assertEquals( "E+1.2", preprocessor.process("E+1.2").toString());
Assert.assertEquals( "E(-1.2)", preprocessor.process("E(-1.2)").toString());
try { Assert.assertEquals( "EE", preprocessor.process("EE").toString());
CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.hex);
Assert.assertEquals( "22F*exp(F)", preprocessor.process("22Fexp(F)").toString()); try {
} finally { CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.hex);
CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.dec); Assert.assertEquals( "22F*exp(F)", preprocessor.process("22Fexp(F)").toString());
} } finally {
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:ABCDEF").toString()); CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.dec);
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString()); }
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString()); Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:ABCDEF").toString());
Assert.assertEquals( "0x:ABCDEF*0*x", preprocessor.process("0x:A BC DEF*0x").toString()); Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
Assert.assertEquals( "0x:ABCDEF001*0*x", preprocessor.process("0x:A BC DEF001*0x").toString()); Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
Assert.assertEquals( "0x:ABCDEF001*0*c", preprocessor.process("0x:A BC DEF001*0c").toString()); Assert.assertEquals( "0x:ABCDEF*0*x", preprocessor.process("0x:A BC DEF*0x").toString());
Assert.assertEquals( "0x:ABCDEF001*c", preprocessor.process("0x:A BC DEF001*c").toString()); Assert.assertEquals( "0x:ABCDEF001*0*x", preprocessor.process("0x:A BC DEF001*0x").toString());
Assert.assertEquals( "0b:1101", preprocessor.process("0b:1101").toString()); Assert.assertEquals( "0x:ABCDEF001*0*c", preprocessor.process("0x:A BC DEF001*0c").toString());
Assert.assertEquals( "0x:1C", preprocessor.process("0x:1C").toString()); Assert.assertEquals( "0x:ABCDEF001*c", preprocessor.process("0x:A BC DEF001*c").toString());
Assert.assertEquals( "0x:1C", preprocessor.process(" 0x:1C").toString()); Assert.assertEquals( "0b:1101", preprocessor.process("0b:1101").toString());
Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString()); Assert.assertEquals( "0x:1C", preprocessor.process("0x:1C").toString());
Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString()); Assert.assertEquals( "0x:1C", preprocessor.process(" 0x:1C").toString());
Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString());
try { Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString());
preprocessor.process("ln()");
Assert.fail(); try {
} catch (CalculatorParseException e) { preprocessor.process("ln()");
} Assert.fail();
try { } catch (CalculatorParseException e) {
preprocessor.process("ln()ln()"); }
Assert.fail(); try {
} catch (CalculatorParseException e) { preprocessor.process("ln()ln()");
} Assert.fail();
} catch (CalculatorParseException e) {
try { }
preprocessor.process("eln()eln()ln()ln()ln()e");
Assert.fail(); try {
} catch (CalculatorParseException e) { preprocessor.process("eln()eln()ln()ln()ln()e");
} Assert.fail();
} catch (CalculatorParseException e) {
try { }
preprocessor.process("ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln()))))))))))))))");
Assert.fail(); try {
} catch (CalculatorParseException e) { preprocessor.process("ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln()))))))))))))))");
} Assert.fail();
} catch (CalculatorParseException e) {
try { }
preprocessor.process("cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))");
Assert.fail(); try {
} catch (CalculatorParseException e) { preprocessor.process("cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))");
} Assert.fail();
} } catch (CalculatorParseException e) {
}
@Test }
public void testDegrees() throws Exception {
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance(); @Test
public void testDegrees() throws Exception {
Assert.assertEquals( "", preprocessor.process("").toString()); final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
/* try {
Assert.assertEquals( "π/180", preprocessor.process("°").toString()); Assert.assertEquals( "", preprocessor.process("").toString());
} catch (ParseException e) { /* try {
if ( !e.getMessage().startsWith("Could not find start of prefix") ){ Assert.assertEquals( "π/180", preprocessor.process("°").toString());
junit.framework.Assert.fail(); } catch (ParseException e) {
} if ( !e.getMessage().startsWith("Could not find start of prefix") ){
} junit.framework.Assert.fail();
Assert.assertEquals( "1*π/180", preprocessor.process("").toString()); }
Assert.assertEquals( "20.0*π/180", preprocessor.process("20.0°").toString()); }
Assert.assertEquals( "sin(30*π/180)", preprocessor.process("sin(30°)").toString()); Assert.assertEquals( "1*π/180", preprocessor.process("").toString());
Assert.assertEquals( "asin(sin(π/6))*π/180", preprocessor.process("asin(sin(π/6))°").toString()); Assert.assertEquals( "20.0*π/180", preprocessor.process("20.0°").toString());
Assert.assertEquals( "1*π/180*sin(1)", preprocessor.process("1°sin(1)").toString()); Assert.assertEquals( "sin(30*π/180)", preprocessor.process("sin(30°)").toString());
try { Assert.assertEquals( "asin(sin(π/6))*π/180", preprocessor.process("asin(sin(π/6))°").toString());
Assert.assertEquals( "1*π/180^sin(1)", preprocessor.process("1°^sin(1)").toString()); Assert.assertEquals( "1*π/180*sin(1)", preprocessor.process("1°sin(1)").toString());
junit.framework.Assert.fail(); try {
} catch (ParseException e) { Assert.assertEquals( "1*π/180^sin(1)", preprocessor.process("1°^sin(1)").toString());
if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) { junit.framework.Assert.fail();
junit.framework.Assert.fail(); } catch (ParseException e) {
} if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) {
}*/ junit.framework.Assert.fail();
}
} }*/
@Test }
public void testPostfixFunction() throws Exception {
} @Test
public void testPostfixFunction() throws Exception {
@Test }
public void testNumeralBases() throws Exception {
final TextProcessor<PreparedExpression, String> processor = ToJsclTextProcessor.getInstance(); @Test
public void testNumeralBases() throws Exception {
final NumeralBase defaultNumeralBase = JsclMathEngine.instance.getNumeralBase(); final TextProcessor<PreparedExpression, String> processor = ToJsclTextProcessor.getInstance();
try{
JsclMathEngine.instance.setNumeralBase(NumeralBase.bin); final NumeralBase defaultNumeralBase = JsclMathEngine.instance.getNumeralBase();
Assert.assertEquals("101", JsclMathEngine.instance.evaluate("10+11")); try{
JsclMathEngine.instance.setNumeralBase(NumeralBase.bin);
JsclMathEngine.instance.setNumeralBase(NumeralBase.hex); Assert.assertEquals("101", JsclMathEngine.instance.evaluate("10+11"));
Assert.assertEquals("56CE+CAD", processor.process("56CE+CAD").getExpression());
} finally { JsclMathEngine.instance.setNumeralBase(NumeralBase.hex);
JsclMathEngine.instance.setNumeralBase(defaultNumeralBase); Assert.assertEquals("56CE+CAD", processor.process("56CE+CAD").getExpression());
} } finally {
} JsclMathEngine.instance.setNumeralBase(defaultNumeralBase);
} }
}
}

16
pom.xml
View File

@ -122,6 +122,22 @@
<version>11.0.2</version> <version>11.0.2</version>
</dependency> </dependency>
<dependency>
<groupId>org.simpleframework</groupId>
<artifactId>simple-xml</artifactId>
<version>2.6.1</version>
<exclusions>
<exclusion>
<artifactId>stax-api</artifactId>
<groupId>stax</groupId>
</exclusion>
<exclusion>
<artifactId>xpp3</artifactId>
<groupId>xpp3</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>