Numeral bases

This commit is contained in:
serso 2016-02-11 16:26:18 +01:00
parent 9e10640e54
commit 7350a9ed0c
23 changed files with 442 additions and 803 deletions

View File

@ -30,12 +30,14 @@ import android.util.Log;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.calculations.CalculationCancelledEvent; import org.solovyev.android.calculator.calculations.CalculationCancelledEvent;
import org.solovyev.android.calculator.calculations.CalculationFailedEvent; import org.solovyev.android.calculator.calculations.CalculationFailedEvent;
import org.solovyev.android.calculator.calculations.CalculationFinishedEvent; import org.solovyev.android.calculator.calculations.CalculationFinishedEvent;
import org.solovyev.android.calculator.calculations.ConversionFailedEvent;
import org.solovyev.android.calculator.calculations.ConversionFinishedEvent;
import org.solovyev.android.calculator.functions.FunctionsRegistry; import org.solovyev.android.calculator.functions.FunctionsRegistry;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
import org.solovyev.android.calculator.variables.CppVariable; import org.solovyev.android.calculator.variables.CppVariable;
import org.solovyev.common.msg.ListMessageRegistry; import org.solovyev.common.msg.ListMessageRegistry;
import org.solovyev.common.msg.Message; import org.solovyev.common.msg.Message;
@ -43,8 +45,17 @@ import org.solovyev.common.msg.MessageRegistry;
import org.solovyev.common.msg.MessageType; import org.solovyev.common.msg.MessageType;
import org.solovyev.common.text.Strings; import org.solovyev.common.text.Strings;
import org.solovyev.common.units.ConversionException; import org.solovyev.common.units.ConversionException;
import org.solovyev.common.units.Conversions;
import jscl.JsclArithmeticException;
import jscl.JsclMathEngine;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Constants;
import jscl.math.function.IConstant;
import jscl.text.ParseInterruptedException;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -58,15 +69,6 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import jscl.JsclArithmeticException;
import jscl.JsclMathEngine;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Constants;
import jscl.math.function.IConstant;
import jscl.text.ParseInterruptedException;
@Singleton @Singleton
public class Calculator implements SharedPreferences.OnSharedPreferenceChangeListener { public class Calculator implements SharedPreferences.OnSharedPreferenceChangeListener {
@ -111,28 +113,12 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis
@Nonnull @Nonnull
private static String doConversion(@Nonnull Generic generic, private static String convert(@Nonnull Generic generic, @Nonnull NumeralBase to) throws ConversionException {
@Nonnull NumeralBase from, final BigInteger value = generic.toBigInteger();
@Nonnull NumeralBase to) throws ConversionException { if (value == null) {
final String result; throw new ConversionException();
if (from != to) {
String fromString = generic.toString();
if (!Strings.isEmpty(fromString)) {
try {
fromString = ToJsclTextProcessor.getInstance().process(fromString).getValue();
} catch (ParseException e) {
// ok, problems while processing occurred
} }
} return to.toString(value);
result = Conversions.doConversion(CalculatorNumeralBase.getConverter(), fromString, CalculatorNumeralBase.valueOf(from), CalculatorNumeralBase.valueOf(to));
} else {
result = generic.toString();
}
return result;
} }
@Nonnull @Nonnull
@ -141,12 +127,6 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis
return CalculatorEventDataImpl.newInstance(eventId, eventId); return CalculatorEventDataImpl.newInstance(eventId, eventId);
} }
@Nonnull
private CalculatorEventData nextEventData(@Nonnull Object source) {
long eventId = nextSequence();
return CalculatorEventDataImpl.newInstance(eventId, eventId, source);
}
@Nonnull @Nonnull
private CalculatorEventData nextEventData(@Nonnull Long sequenceId) { private CalculatorEventData nextEventData(@Nonnull Long sequenceId) {
long eventId = nextSequence(); long eventId = nextSequence();
@ -211,15 +191,6 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis
} }
} }
@Nonnull
private CalculatorConversionEventData newConversionEventData(@Nonnull Long sequenceId,
@Nonnull Generic value,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to,
@Nonnull DisplayState displayViewState) {
return CalculatorConversionEventDataImpl.newInstance(nextEventData(sequenceId), value, from, to, displayViewState);
}
private void evaluateAsync(long sequence, @Nonnull JsclOperation o, @Nonnull String e) { private void evaluateAsync(long sequence, @Nonnull JsclOperation o, @Nonnull String e) {
evaluateAsync(sequence, o, e, new ListMessageRegistry()); evaluateAsync(sequence, o, e, new ListMessageRegistry());
} }
@ -240,7 +211,7 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis
pe = prepare(e); pe = prepare(e);
try { try {
Locator.getInstance().getEngine().getMathEngine().setMessageRegistry(mr); mathEngine.setMessageRegistry(mr);
final Generic result = o.evaluateGeneric(pe.value, mathEngine); final Generic result = o.evaluateGeneric(pe.value, mathEngine);
@ -325,38 +296,33 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis
bus.post(new CalculationFailedEvent(operation, e, sequence, parseException)); bus.post(new CalculationFailedEvent(operation, e, sequence, parseException));
} }
@Nonnull public void convert(@Nonnull final DisplayState state, @Nonnull final NumeralBase to) {
public CalculatorEventData convert(@Nonnull final Generic value, final Generic value = state.getResult();
@Nonnull final NumeralBase to) { Check.isNotNull(value);
final CalculatorEventData eventDataId = nextEventData(); final NumeralBase from = mathEngine.getNumeralBase();
if (from == to) {
final DisplayState displayViewState = App.getDisplay().getState(); return;
final NumeralBase from = Locator.getInstance().getEngine().getMathEngine().getNumeralBase(); }
background.execute(new Runnable() { background.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
final Long sequenceId = eventDataId.getSequenceId();
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_started, null);
try { try {
final String result = convert(value, to);
final String result = doConversion(value, from, to); bus.post(new ConversionFinishedEvent(result, to, state));
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_result, result);
} catch (ConversionException e) { } catch (ConversionException e) {
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_failed, new ConversionFailureImpl(e)); bus.post(new ConversionFailedEvent(state));
} }
} }
}); });
return eventDataId;
} }
public boolean isConversionPossible(@Nonnull Generic generic, NumeralBase from, @Nonnull NumeralBase to) { public boolean canConvert(@Nonnull Generic generic, @NonNull NumeralBase from, @Nonnull NumeralBase to) {
if(from == to) {
return false;
}
try { try {
doConversion(generic, from, to); convert(generic, to);
return true; return true;
} catch (ConversionException e) { } catch (ConversionException e) {
return false; return false;
@ -389,15 +355,6 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis
return eventData; return eventData;
} }
@Nonnull
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data, @Nonnull Object source) {
final CalculatorEventData eventData = nextEventData(source);
fireCalculatorEvent(eventData, calculatorEventType, data);
return eventData;
}
@Subscribe @Subscribe
public void onEditorChanged(@Nonnull Editor.ChangedEvent e) { public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
if (!calculateOnFly) { if (!calculateOnFly) {
@ -476,4 +433,5 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis
public static long nextSequence() { public static long nextSequence() {
return SEQUENCER.incrementAndGet(); return SEQUENCER.incrementAndGet();
} }
} }

View File

@ -1,126 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import jscl.NumeralBase;
import jscl.math.Generic;
/**
* User: Solovyev_S
* Date: 24.09.12
* Time: 16:48
*/
public class CalculatorConversionEventDataImpl implements CalculatorConversionEventData {
@Nonnull
private CalculatorEventData calculatorEventData;
@Nonnull
private NumeralBase fromNumeralBase;
@Nonnull
private NumeralBase toNumeralBase;
@Nonnull
private Generic value;
@Nonnull
private DisplayState displayState;
private CalculatorConversionEventDataImpl() {
}
@Nonnull
public static CalculatorConversionEventData newInstance(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull Generic value,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to,
@Nonnull DisplayState displayViewState) {
final CalculatorConversionEventDataImpl result = new CalculatorConversionEventDataImpl();
result.calculatorEventData = calculatorEventData;
result.value = value;
result.displayState = displayViewState;
result.fromNumeralBase = from;
result.toNumeralBase = to;
return result;
}
@Override
public long getEventId() {
return calculatorEventData.getEventId();
}
@Override
@Nonnull
public Long getSequenceId() {
return calculatorEventData.getSequenceId();
}
@Override
public Object getSource() {
return calculatorEventData.getSource();
}
@Override
public boolean isAfter(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfter(that);
}
@Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return calculatorEventData.isSameSequence(that);
}
@Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfterSequence(that);
}
@Nonnull
@Override
public DisplayState getDisplayState() {
return this.displayState;
}
@Override
@Nonnull
public NumeralBase getFromNumeralBase() {
return fromNumeralBase;
}
@Override
@Nonnull
public NumeralBase getToNumeralBase() {
return toNumeralBase;
}
@Override
@Nonnull
public Generic getValue() {
return value;
}
}

View File

@ -39,8 +39,6 @@ public enum CalculatorEventType {
* *
********************************************************************** **********************************************************************
*/ */
conversion_started,
// @Nonnull String conversion result // @Nonnull String conversion result
conversion_result, conversion_result,

View File

@ -1,36 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 24.09.12
* Time: 16:12
*/
public interface ConversionFailure {
@Nonnull
Exception getException();
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 24.09.12
* Time: 16:12
*/
public class ConversionFailureImpl implements ConversionFailure {
@Nonnull
private Exception exception;
public ConversionFailureImpl(@Nonnull Exception exception) {
this.exception = exception;
}
@Nonnull
@Override
public Exception getException() {
return this.exception;
}
}

View File

@ -1,77 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import android.content.Context;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.menu.AMenuItem;
import javax.annotation.Nonnull;
import jscl.NumeralBase;
import jscl.math.Generic;
/**
* User: serso
* Date: 9/21/12
* Time: 12:11 AM
*/
enum ConversionMenuItem implements AMenuItem<DisplayState> {
convert_to_bin(NumeralBase.bin),
convert_to_dec(NumeralBase.dec),
convert_to_hex(NumeralBase.hex);
@Nonnull
private final NumeralBase toNumeralBase;
ConversionMenuItem(@Nonnull NumeralBase toNumeralBase) {
this.toNumeralBase = toNumeralBase;
}
protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) {
boolean result = false;
if (operation == JsclOperation.numeric) {
if (generic.getConstants().isEmpty()) {
// conversion possible => return true
final NumeralBase fromNumeralBase = Locator.getInstance().getEngine().getMathEngine().getNumeralBase();
if (fromNumeralBase != toNumeralBase) {
result = Locator.getInstance().getCalculator().isConversionPossible(generic, fromNumeralBase, this.toNumeralBase);
}
}
}
return result;
}
@Override
public void onClick(@Nonnull DisplayState data, @Nonnull Context context) {
final Generic result = data.getResult();
if (result != null) {
Locator.getInstance().getCalculator().convert(result, this.toNumeralBase);
}
}
}

View File

@ -22,17 +22,17 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import jscl.NumeralBase;
import org.solovyev.android.calculator.keyboard.KeyboardUi; import org.solovyev.android.calculator.keyboard.KeyboardUi;
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
import org.solovyev.android.views.dragbutton.DirectionDragButton; import org.solovyev.android.views.dragbutton.DirectionDragButton;
import org.solovyev.android.views.dragbutton.DragDirection; import org.solovyev.android.views.dragbutton.DragDirection;
import jscl.NumeralBase;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public enum AndroidNumeralBase { public enum CppNumeralBase {
bin(CalculatorNumeralBase.bin) { bin(NumeralBase.bin) {
@Override @Override
public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) { public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) {
toggleButton(show, ui.button0); toggleButton(show, ui.button0);
@ -40,7 +40,7 @@ public enum AndroidNumeralBase {
} }
}, },
oct(CalculatorNumeralBase.oct) { oct(NumeralBase.oct) {
@Override @Override
public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) { public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) {
bin.toggleButtons(show, ui); bin.toggleButtons(show, ui);
@ -53,7 +53,7 @@ public enum AndroidNumeralBase {
} }
}, },
dec(CalculatorNumeralBase.dec) { dec(NumeralBase.dec) {
@Override @Override
public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) { public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) {
oct.toggleButtons(show, ui); oct.toggleButtons(show, ui);
@ -62,7 +62,7 @@ public enum AndroidNumeralBase {
} }
}, },
hex(CalculatorNumeralBase.hex) { hex(NumeralBase.hex) {
@Override @Override
public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) { public void toggleButtons(boolean show, @Nonnull KeyboardUi ui) {
dec.toggleButtons(show, ui); dec.toggleButtons(show, ui);
@ -81,17 +81,17 @@ public enum AndroidNumeralBase {
}; };
@Nonnull @Nonnull
private final CalculatorNumeralBase calculatorNumeralBase; public final NumeralBase numeralBase;
AndroidNumeralBase(@Nonnull CalculatorNumeralBase calculatorNumeralBase) { CppNumeralBase(@Nonnull NumeralBase numeralBase) {
this.calculatorNumeralBase = calculatorNumeralBase; this.numeralBase = numeralBase;
} }
@Nonnull @Nonnull
public static AndroidNumeralBase valueOf(@Nonnull NumeralBase nb) { public static CppNumeralBase valueOf(@Nonnull NumeralBase nb) {
for (AndroidNumeralBase androidNumeralBase : values()) { for (CppNumeralBase cppNumeralBase : values()) {
if (androidNumeralBase.calculatorNumeralBase.getNumeralBase() == nb) { if (cppNumeralBase.numeralBase == nb) {
return androidNumeralBase; return cppNumeralBase;
} }
} }
@ -104,9 +104,4 @@ public enum AndroidNumeralBase {
button.setShowText(show); button.setShowText(show);
button.invalidate(); button.invalidate();
} }
@Nonnull
public NumeralBase getNumeralBase() {
return calculatorNumeralBase.getNumeralBase();
}
} }

View File

@ -22,19 +22,9 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import static org.solovyev.android.calculator.BaseFragment.addMenu;
import static org.solovyev.android.calculator.CalculatorEventType.conversion_failed;
import static org.solovyev.android.calculator.CalculatorEventType.conversion_result;
import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.support.v7.app.AlertDialog; import android.support.annotation.NonNull;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
@ -43,11 +33,11 @@ import org.solovyev.android.Check;
import org.solovyev.android.calculator.calculations.CalculationCancelledEvent; import org.solovyev.android.calculator.calculations.CalculationCancelledEvent;
import org.solovyev.android.calculator.calculations.CalculationFailedEvent; import org.solovyev.android.calculator.calculations.CalculationFailedEvent;
import org.solovyev.android.calculator.calculations.CalculationFinishedEvent; import org.solovyev.android.calculator.calculations.CalculationFinishedEvent;
import org.solovyev.android.calculator.calculations.ConversionFailedEvent;
import org.solovyev.android.calculator.calculations.ConversionFinishedEvent;
import org.solovyev.android.calculator.errors.FixableErrorsActivity; import org.solovyev.android.calculator.errors.FixableErrorsActivity;
import org.solovyev.android.calculator.jscl.JsclOperation;
import dagger.Lazy; import dagger.Lazy;
import jscl.math.Generic;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -55,10 +45,8 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@Singleton @Singleton
public class Display implements CalculatorEventListener, View.OnClickListener, View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener { public class Display {
@Nonnull
private final CalculatorEventHolder lastEvent;
@Nonnull @Nonnull
private final Bus bus; private final Bus bus;
@Inject @Inject
@ -75,10 +63,8 @@ public class Display implements CalculatorEventListener, View.OnClickListener, V
private DisplayState state = DisplayState.empty(); private DisplayState state = DisplayState.empty();
@Inject @Inject
public Display(@Nonnull Calculator calculator, @Nonnull Bus bus) { public Display(@Nonnull Bus bus) {
this.bus = bus; this.bus = bus;
lastEvent = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
calculator.addCalculatorEventListener(this);
bus.register(this); bus.register(this);
} }
@ -87,12 +73,13 @@ public class Display implements CalculatorEventListener, View.OnClickListener, V
copy(); copy();
} }
private void copy() { void copy() {
if (!state.valid) { if (!state.valid) {
return; return;
} }
clipboard.get().setText(state.text); clipboard.get().setText(state.text);
notifier.get().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied)); notifier.get().showMessage(
CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied));
} }
@Subscribe @Subscribe
@ -124,6 +111,22 @@ public class Display implements CalculatorEventListener, View.OnClickListener, V
setState(DisplayState.createError(e.operation, error, e.sequence)); setState(DisplayState.createError(e.operation, error, e.sequence));
} }
@Subscribe
public void onConversionFinished(@NonNull ConversionFinishedEvent e) {
if (e.state.sequence != state.sequence) return;
final String result = e.numeralBase.getJsclPrefix() + e.result;
setState(DisplayState.createValid(e.state.getOperation(), e.state.getResult(), result,
e.state.sequence));
}
@Subscribe
public void onConversionFailed(@NonNull ConversionFailedEvent e) {
if (e.state.sequence != state.sequence) return;
setState(DisplayState.createError(e.state.getOperation(),
CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error),
e.state.sequence));
}
public void clearView(@Nonnull DisplayView view) { public void clearView(@Nonnull DisplayView view) {
Check.isMainThread(); Check.isMainThread();
if (this.view != view) { if (this.view != view) {
@ -135,7 +138,6 @@ public class Display implements CalculatorEventListener, View.OnClickListener, V
public void setView(@Nonnull DisplayView view) { public void setView(@Nonnull DisplayView view) {
Check.isMainThread(); Check.isMainThread();
this.view = view; this.view = view;
this.view.setOnClickListener(this);
this.view.setState(state); this.view.setState(state);
} }
@ -156,127 +158,6 @@ public class Display implements CalculatorEventListener, View.OnClickListener, V
bus.post(new ChangedEvent(oldState, newState)); bus.post(new ChangedEvent(oldState, newState));
} }
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
if (calculatorEventType.isOfType(conversion_result, conversion_failed)) {
final CalculatorEventHolder.Result result = lastEvent.apply(calculatorEventData);
if (result.isNewAfter()) {
switch (calculatorEventType) {
case conversion_failed:
processConversationFailed((CalculatorConversionEventData) calculatorEventData);
break;
case conversion_result:
processConversationResult((CalculatorConversionEventData) calculatorEventData, (String) data);
break;
}
}
}
}
private void processConversationFailed(@Nonnull CalculatorConversionEventData calculatorEventData) {
setState(DisplayState.createError(calculatorEventData.getDisplayState().getOperation(), CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error), calculatorEventData.getSequenceId()));
}
private void processConversationResult(@Nonnull CalculatorConversionEventData calculatorEventData, @Nonnull String result) {
// add prefix
if (calculatorEventData.getFromNumeralBase() != calculatorEventData.getToNumeralBase()) {
result = calculatorEventData.getToNumeralBase().getJsclPrefix() + result;
}
final DisplayState displayState = calculatorEventData.getDisplayState();
setState(DisplayState.createValid(displayState.getOperation(), displayState.getResult(), result, calculatorEventData.getSequenceId()));
}
@Override
public void onClick(View v) {
if (state.valid) {
v.setOnCreateContextMenuListener(this);
v.showContextMenu();
v.setOnCreateContextMenuListener(null);
} else {
showEvaluationError(v.getContext(), state.text);
}
}
public static void showEvaluationError(@Nonnull Context context, @Nonnull final String errorMessage) {
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
final AlertDialog.Builder builder = new AlertDialog.Builder(context, App.getTheme().alertDialogTheme)
.setPositiveButton(R.string.c_cancel, null)
.setView(errorMessageView);
builder.create().show();
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
if (!state.valid) {
return;
}
addMenu(menu, R.string.c_copy, this);
final Generic result = state.getResult();
final JsclOperation operation = state.getOperation();
if (result != null) {
if (ConversionMenuItem.convert_to_bin.isItemVisibleFor(result, operation)) {
addMenu(menu, R.string.convert_to_bin, this);
}
if (ConversionMenuItem.convert_to_dec.isItemVisibleFor(result, operation)) {
addMenu(menu, R.string.convert_to_dec, this);
}
if (ConversionMenuItem.convert_to_hex.isItemVisibleFor(result, operation)) {
addMenu(menu, R.string.convert_to_hex, this);
}
if (operation == JsclOperation.numeric && result.getConstants().isEmpty()) {
addMenu(menu, R.string.c_convert, this);
}
if (Locator.getInstance().getPlotter().isPlotPossibleFor(result)) {
addMenu(menu, R.string.c_plot, this);
}
}
}
@Override
public boolean onMenuItemClick(MenuItem item) {
final Generic result = state.getResult();
switch (item.getItemId()) {
case R.string.c_copy:
copy();
return true;
case R.string.convert_to_bin:
ConversionMenuItem.convert_to_bin.onClick(state, App.getApplication());
return true;
case R.string.convert_to_dec:
ConversionMenuItem.convert_to_dec.onClick(state, App.getApplication());
return true;
case R.string.convert_to_hex:
ConversionMenuItem.convert_to_hex.onClick(state, App.getApplication());
return true;
case R.string.c_convert:
if (result != null) {
// FIXME: 2016-02-10
//new NumeralBaseConverterDialog(result.toString()).show(App.getApplication());
}
return true;
case R.string.c_plot:
if (result != null) {
Locator.getInstance().getPlotter().plot(result);
}
return true;
default:
return false;
}
}
public static class CopyOperation { public static class CopyOperation {
} }

View File

@ -22,18 +22,65 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v7.app.AlertDialog;
import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView;
import com.squareup.otto.Bus;
import org.solovyev.android.calculator.converter.ConverterFragment;
import org.solovyev.android.calculator.jscl.JsclOperation;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import jscl.NumeralBase;
import jscl.math.Generic;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.inject.Inject; import javax.inject.Inject;
public class DisplayFragment extends BaseFragment { public class DisplayFragment extends BaseFragment implements View.OnClickListener,
MenuItem.OnMenuItemClickListener {
private enum ConversionMenuItem {
to_bin(NumeralBase.bin, R.string.convert_to_bin),
to_dec(NumeralBase.dec, R.string.convert_to_dec),
to_hex(NumeralBase.hex, R.string.convert_to_hex);
@Nonnull
public final NumeralBase toNumeralBase;
public final int title;
ConversionMenuItem(@Nonnull NumeralBase toNumeralBase, @StringRes int title) {
this.toNumeralBase = toNumeralBase;
this.title = title;
}
@Nullable
public static ConversionMenuItem getByTitle(int title) {
switch (title) {
case R.string.convert_to_bin:
return to_bin;
case R.string.convert_to_dec:
return to_dec;
case R.string.convert_to_hex:
return to_hex;
}
return null;
}
}
@Bind(R.id.calculator_display) @Bind(R.id.calculator_display)
DisplayView displayView; DisplayView displayView;
@ -41,12 +88,10 @@ public class DisplayFragment extends BaseFragment {
SharedPreferences preferences; SharedPreferences preferences;
@Inject @Inject
Display display; Display display;
@Inject
@Override Bus bus;
protected void inject(@Nonnull AppComponent component) { @Inject
super.inject(component); Calculator calculator;
component.inject(this);
}
@Nonnull @Nonnull
@Override @Override
@ -60,10 +105,18 @@ public class DisplayFragment extends BaseFragment {
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { protected void inject(@Nonnull AppComponent component) {
super.inject(component);
component.inject(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = super.onCreateView(inflater, container, savedInstanceState); final View view = super.onCreateView(inflater, container, savedInstanceState);
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
display.setView(displayView); display.setView(displayView);
displayView.setOnClickListener(this);
return view; return view;
} }
@ -72,4 +125,115 @@ public class DisplayFragment extends BaseFragment {
display.clearView(displayView); display.clearView(displayView);
super.onDestroyView(); super.onDestroyView();
} }
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
final DisplayState state = display.getState();
if (!state.valid) {
return;
}
addMenu(menu, R.string.c_copy, this);
final Generic result = state.getResult();
final JsclOperation operation = state.getOperation();
if (result != null) {
if (operation == JsclOperation.numeric && result.getConstants().isEmpty()) {
for (ConversionMenuItem item : ConversionMenuItem.values()) {
if (isMenuItemVisible(item, result)) {
addMenu(menu, item.title, this);
}
}
if (result.toDouble() != null) {
addMenu(menu, R.string.c_convert, this);
}
}
if (Locator.getInstance().getPlotter().isPlotPossibleFor(result)) {
addMenu(menu, R.string.c_plot, this);
}
}
}
protected boolean isMenuItemVisible(@NonNull ConversionMenuItem menuItem,
@Nonnull Generic generic) {
final NumeralBase fromNumeralBase =
Locator.getInstance().getEngine().getMathEngine().getNumeralBase();
if (fromNumeralBase != menuItem.toNumeralBase) {
return calculator.canConvert(generic, fromNumeralBase, menuItem.toNumeralBase);
}
return false;
}
@Override
public void onClick(View v) {
final DisplayState state = display.getState();
if (state.valid) {
v.setOnCreateContextMenuListener(this);
v.showContextMenu();
v.setOnCreateContextMenuListener(null);
} else {
showEvaluationError(v.getContext(), state.text);
}
}
public static void showEvaluationError(@Nonnull Context context,
@Nonnull final String errorMessage) {
final LayoutInflater layoutInflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
((TextView) errorMessageView.findViewById(R.id.error_message_text_view))
.setText(errorMessage);
final AlertDialog.Builder builder =
new AlertDialog.Builder(context, App.getTheme().alertDialogTheme)
.setPositiveButton(R.string.c_cancel, null)
.setView(errorMessageView);
builder.create().show();
}
@Override
public boolean onMenuItemClick(MenuItem item) {
final DisplayState state = display.getState();
final Generic result = state.getResult();
switch (item.getItemId()) {
case R.string.c_copy:
display.copy();
return true;
case R.string.convert_to_bin:
case R.string.convert_to_dec:
case R.string.convert_to_hex:
final ConversionMenuItem menuItem = ConversionMenuItem.getByTitle(item.getItemId());
if (menuItem == null) {
return false;
}
if (result != null) {
calculator.convert(state, menuItem.toNumeralBase);
}
return true;
case R.string.c_convert:
ConverterFragment.show(getActivity(), getValue(result));
return true;
case R.string.c_plot:
if (result != null) {
Locator.getInstance().getPlotter().plot(result);
}
return true;
default:
return false;
}
}
private static double getValue(@Nullable Generic result) {
if (result == null) {
return 1d;
}
final Double value = result.toDouble();
if (value == null) {
return 1d;
}
return value;
}
} }

View File

@ -0,0 +1,14 @@
package org.solovyev.android.calculator.calculations;
import android.support.annotation.NonNull;
import org.solovyev.android.calculator.DisplayState;
public class BaseConversionEvent {
@NonNull
public final DisplayState state;
public BaseConversionEvent(@NonNull DisplayState state) {
this.state = state;
}
}

View File

@ -0,0 +1,12 @@
package org.solovyev.android.calculator.calculations;
import android.support.annotation.NonNull;
import org.solovyev.android.calculator.DisplayState;
public class ConversionFailedEvent extends BaseConversionEvent {
public ConversionFailedEvent(@NonNull DisplayState state) {
super(state);
}
}

View File

@ -0,0 +1,21 @@
package org.solovyev.android.calculator.calculations;
import android.support.annotation.NonNull;
import org.solovyev.android.calculator.DisplayState;
import jscl.NumeralBase;
public class ConversionFinishedEvent extends BaseConversionEvent {
@NonNull
public final String result;
@NonNull
public final NumeralBase numeralBase;
public ConversionFinishedEvent(@NonNull String result, @NonNull NumeralBase numeralBase,
@NonNull DisplayState state) {
super(state);
this.result = result;
this.numeralBase = numeralBase;
}
}

View File

@ -13,19 +13,33 @@ import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.*; import android.widget.AdapterView;
import butterknife.Bind; import android.widget.ArrayAdapter;
import butterknife.ButterKnife; import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.TextView;
import org.solovyev.android.calculator.App; import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.BaseDialogFragment; import org.solovyev.android.calculator.BaseDialogFragment;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import butterknife.Bind;
import butterknife.ButterKnife;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.measure.unit.Dimension; import javax.measure.unit.Dimension;
import javax.measure.unit.NonSI; import javax.measure.unit.NonSI;
import javax.measure.unit.SI; import javax.measure.unit.SI;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import java.util.*;
public class ConverterFragment extends BaseDialogFragment public class ConverterFragment extends BaseDialogFragment
implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener, TextView.OnEditorActionListener, View.OnClickListener { implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener, TextView.OnEditorActionListener, View.OnClickListener {
@ -36,6 +50,7 @@ public class ConverterFragment extends BaseDialogFragment
private static final Map<MyDimension, List<Unit<?>>> units = new HashMap<>(); private static final Map<MyDimension, List<Unit<?>>> units = new HashMap<>();
private static final String STATE_SELECTION_FROM = "selection.from"; private static final String STATE_SELECTION_FROM = "selection.from";
private static final String STATE_SELECTION_TO = "selection.to"; private static final String STATE_SELECTION_TO = "selection.to";
private static final String EXTRA_VALUE = "value";
static { static {
for (Unit<?> unit : SI.getInstance().getUnits()) { for (Unit<?> unit : SI.getInstance().getUnits()) {
@ -88,7 +103,15 @@ public class ConverterFragment extends BaseDialogFragment
} }
public static void show(@Nonnull FragmentActivity activity) { public static void show(@Nonnull FragmentActivity activity) {
App.showDialog(new ConverterFragment(), "converter", show(activity, 1d);
}
public static void show(@Nonnull FragmentActivity activity, double value) {
final ConverterFragment fragment = new ConverterFragment();
final Bundle args = new Bundle(1);
args.putDouble(EXTRA_VALUE, value);
fragment.setArguments(args);
App.showDialog(fragment, "converter",
activity.getSupportFragmentManager()); activity.getSupportFragmentManager());
} }
@ -134,7 +157,7 @@ public class ConverterFragment extends BaseDialogFragment
swapButton.setOnClickListener(this); swapButton.setOnClickListener(this);
if (savedInstanceState == null) { if (savedInstanceState == null) {
editTextFrom.setText("1"); editTextFrom.setText(String.valueOf(getArguments().getDouble(EXTRA_VALUE, 1f)));
dimensionsSpinner.setSelection(0); dimensionsSpinner.setSelection(0);
} else { } else {
pendingFromSelection = savedInstanceState.getInt(STATE_SELECTION_FROM, View.NO_ID); pendingFromSelection = savedInstanceState.getInt(STATE_SELECTION_FROM, View.NO_ID);

View File

@ -1,5 +1,14 @@
package org.solovyev.android.calculator.keyboard; package org.solovyev.android.calculator.keyboard;
import static jscl.NumeralBase.hex;
import static org.solovyev.android.calculator.Engine.Preferences.angleUnit;
import static org.solovyev.android.calculator.Engine.Preferences.multiplicationSign;
import static org.solovyev.android.calculator.Engine.Preferences.numeralBase;
import static org.solovyev.android.calculator.Preferences.Gui.hideNumeralBaseDigits;
import static org.solovyev.android.views.dragbutton.DragDirection.down;
import static org.solovyev.android.views.dragbutton.DragDirection.left;
import static org.solovyev.android.views.dragbutton.DragDirection.up;
import android.app.Activity; import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -11,11 +20,12 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageButton; import android.widget.ImageButton;
import butterknife.Bind;
import butterknife.ButterKnife; import org.solovyev.android.calculator.ActivityLauncher;
import jscl.AngleUnit; import org.solovyev.android.calculator.CalculatorEventType;
import jscl.NumeralBase; import org.solovyev.android.calculator.CppNumeralBase;
import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.Engine;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.buttons.CppSpecialButton; import org.solovyev.android.calculator.buttons.CppSpecialButton;
import org.solovyev.android.calculator.history.History; import org.solovyev.android.calculator.history.History;
import org.solovyev.android.calculator.view.AngleUnitsButton; import org.solovyev.android.calculator.view.AngleUnitsButton;
@ -23,14 +33,14 @@ import org.solovyev.android.views.dragbutton.DirectionDragButton;
import org.solovyev.android.views.dragbutton.DragButton; import org.solovyev.android.views.dragbutton.DragButton;
import org.solovyev.android.views.dragbutton.DragDirection; import org.solovyev.android.views.dragbutton.DragDirection;
import butterknife.Bind;
import butterknife.ButterKnife;
import jscl.AngleUnit;
import jscl.NumeralBase;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.inject.Inject; import javax.inject.Inject;
import static jscl.NumeralBase.hex;
import static org.solovyev.android.calculator.Engine.Preferences.*;
import static org.solovyev.android.calculator.Preferences.Gui.hideNumeralBaseDigits;
import static org.solovyev.android.views.dragbutton.DragDirection.*;
public class KeyboardUi extends BaseKeyboardUi { public class KeyboardUi extends BaseKeyboardUi {
@Bind(R.id.cpp_button_0) @Bind(R.id.cpp_button_0)
@ -100,18 +110,18 @@ public class KeyboardUi extends BaseKeyboardUi {
toggleNumericDigits(numeralBase.getPreference(preferences)); toggleNumericDigits(numeralBase.getPreference(preferences));
} else { } else {
// set HEX to show all digits // set HEX to show all digits
AndroidNumeralBase.valueOf(hex).toggleButtons(true, this); CppNumeralBase.valueOf(hex).toggleButtons(true, this);
} }
} }
public void toggleNumericDigits(@Nonnull NumeralBase currentNumeralBase) { public void toggleNumericDigits(@Nonnull NumeralBase currentNumeralBase) {
for (NumeralBase numeralBase : NumeralBase.values()) { for (NumeralBase numeralBase : NumeralBase.values()) {
if (currentNumeralBase != numeralBase) { if (currentNumeralBase != numeralBase) {
AndroidNumeralBase.valueOf(numeralBase).toggleButtons(false, this); CppNumeralBase.valueOf(numeralBase).toggleButtons(false, this);
} }
} }
AndroidNumeralBase.valueOf(currentNumeralBase).toggleButtons(true, this); CppNumeralBase.valueOf(currentNumeralBase).toggleButtons(true, this);
} }
public void onCreateView(@Nonnull Activity activity, @Nonnull View view) { public void onCreateView(@Nonnull Activity activity, @Nonnull View view) {

View File

@ -1,119 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.units;
import org.solovyev.common.units.Unit;
import org.solovyev.common.units.UnitConverter;
import org.solovyev.common.units.UnitImpl;
import org.solovyev.common.units.UnitType;
import java.math.BigInteger;
import javax.annotation.Nonnull;
import jscl.NumeralBase;
/**
* User: Solovyev_S
* Date: 24.09.12
* Time: 16:05
*/
public enum CalculatorNumeralBase implements UnitType<String> {
bin(NumeralBase.bin),
oct(NumeralBase.oct),
dec(NumeralBase.dec),
hex(NumeralBase.hex);
@Nonnull
private static final CalculatorNumeralBase.Converter converter = new CalculatorNumeralBase.Converter();
@Nonnull
private final NumeralBase numeralBase;
CalculatorNumeralBase(@Nonnull NumeralBase numeralBase) {
this.numeralBase = numeralBase;
}
@Nonnull
public static CalculatorNumeralBase.Converter getConverter() {
return converter;
}
@Nonnull
public static CalculatorNumeralBase valueOf(@Nonnull NumeralBase nb) {
for (CalculatorNumeralBase calculatorNumeralBase : values()) {
if (calculatorNumeralBase.numeralBase == nb) {
return calculatorNumeralBase;
}
}
throw new IllegalArgumentException(nb + " is not supported numeral base!");
}
@Nonnull
public NumeralBase getNumeralBase() {
return numeralBase;
}
@Nonnull
@Override
public Class<String> getUnitValueClass() {
return String.class;
}
@Nonnull
public Unit<String> createUnit(@Nonnull String value) {
return UnitImpl.newInstance(value, this);
}
public static class Converter implements UnitConverter<String> {
private Converter() {
}
@Override
public boolean isSupported(@Nonnull UnitType<?> from, @Nonnull UnitType<String> to) {
return CalculatorNumeralBase.class.isAssignableFrom(from.getClass()) && CalculatorNumeralBase.class.isAssignableFrom(to.getClass());
}
@Nonnull
@Override
public Unit<String> convert(@Nonnull Unit<?> from, @Nonnull UnitType<String> toType) {
if (!isSupported(from.getUnitType(), toType)) {
throw new IllegalArgumentException("Types are not supported!");
}
final CalculatorNumeralBase fromTypeAndroid = (CalculatorNumeralBase) from.getUnitType();
final NumeralBase fromNumeralBase = fromTypeAndroid.numeralBase;
final NumeralBase toNumeralBase = ((CalculatorNumeralBase) toType).numeralBase;
final String fromValue = (String) from.getValue();
final BigInteger decBigInteger = fromNumeralBase.toBigInteger(fromValue);
return UnitImpl.newInstance(toNumeralBase.toString(decBigInteger), toType);
}
}
}

View File

@ -1,110 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android;
import android.os.Build;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import org.solovyev.android.calculator.BuildConfig;
import org.solovyev.android.calculator.CalculatorTestUtils;
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
import org.solovyev.common.units.Unit;
import org.solovyev.common.units.UnitConverter;
import javax.annotation.Nonnull;
import java.util.Date;
import java.util.Random;
import static org.junit.Assert.assertTrue;
/**
* User: serso
* Date: 4/21/12
* Time: 8:24 PM
*/
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
@RunWith(RobolectricGradleTestRunner.class)
public class AndroidNumeralBaseTest {
@Nonnull
private final UnitConverter<String> c = CalculatorNumeralBase.getConverter();
@BeforeClass
public static void staticSetUp() throws Exception {
CalculatorTestUtils.staticSetUp();
}
@Test
public void testIsSupported() throws Exception {
assertTrue(c.isSupported(CalculatorNumeralBase.bin, CalculatorNumeralBase.dec));
}
@Test
public void testConvertFromDec() throws Exception {
Assert.assertEquals("101", c.convert(CalculatorNumeralBase.dec.createUnit("5"), CalculatorNumeralBase.bin).getValue());
Assert.assertEquals("1", c.convert(CalculatorNumeralBase.dec.createUnit("1"), CalculatorNumeralBase.bin).getValue());
Assert.assertEquals("0", c.convert(CalculatorNumeralBase.dec.createUnit("0"), CalculatorNumeralBase.bin).getValue());
Assert.assertEquals("1111100111", c.convert(CalculatorNumeralBase.dec.createUnit("999"), CalculatorNumeralBase.bin).getValue());
Assert.assertEquals("A23", c.convert(CalculatorNumeralBase.dec.createUnit("2595"), CalculatorNumeralBase.hex).getValue());
Assert.assertEquals("AEE", c.convert(CalculatorNumeralBase.dec.createUnit("2798"), CalculatorNumeralBase.hex).getValue());
Assert.assertEquals("15", c.convert(CalculatorNumeralBase.dec.createUnit("21"), CalculatorNumeralBase.hex).getValue());
Assert.assertEquals("0", c.convert(CalculatorNumeralBase.dec.createUnit("0"), CalculatorNumeralBase.hex).getValue());
Assert.assertEquals("3E7", c.convert(CalculatorNumeralBase.dec.createUnit("999"), CalculatorNumeralBase.hex).getValue());
Assert.assertEquals("76", c.convert(CalculatorNumeralBase.dec.createUnit("62"), CalculatorNumeralBase.oct).getValue());
Assert.assertEquals("12", c.convert(CalculatorNumeralBase.dec.createUnit("10"), CalculatorNumeralBase.oct).getValue());
Assert.assertEquals("15", c.convert(CalculatorNumeralBase.dec.createUnit("13"), CalculatorNumeralBase.oct).getValue());
Assert.assertEquals("0", c.convert(CalculatorNumeralBase.dec.createUnit("0"), CalculatorNumeralBase.oct).getValue());
Assert.assertEquals("10445", c.convert(CalculatorNumeralBase.dec.createUnit("4389"), CalculatorNumeralBase.oct).getValue());
}
@Test
public void testRandomConvert() throws Exception {
final Random random = new Random(new Date().getTime());
for (int i = 0; i < 100000; i++) {
final String value = String.valueOf(random.nextInt());
Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.oct, CalculatorNumeralBase.oct, CalculatorNumeralBase.bin, CalculatorNumeralBase.dec));
Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.bin, CalculatorNumeralBase.hex, CalculatorNumeralBase.dec, CalculatorNumeralBase.dec));
Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.dec, CalculatorNumeralBase.hex, CalculatorNumeralBase.oct, CalculatorNumeralBase.dec));
Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.hex, CalculatorNumeralBase.bin, CalculatorNumeralBase.oct, CalculatorNumeralBase.dec));
}
}
@Nonnull
private String convertChain(@Nonnull String value, @Nonnull CalculatorNumeralBase baseAndroid, @Nonnull CalculatorNumeralBase... typeAndroids) {
Unit<String> unit = baseAndroid.createUnit(value);
for (CalculatorNumeralBase typeAndroid : typeAndroids) {
unit = CalculatorNumeralBase.getConverter().convert(unit, typeAndroid);
}
return unit.getValue();
}
}

View File

@ -2,15 +2,6 @@ package jscl.math;
import org.solovyev.common.Converter; import org.solovyev.common.Converter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.math.function.Fraction; import jscl.math.function.Fraction;
import jscl.math.function.Inverse; import jscl.math.function.Inverse;
@ -25,6 +16,15 @@ import jscl.text.ParserUtils;
import jscl.text.msg.Messages; import jscl.text.msg.Messages;
import jscl.util.ArrayUtils; import jscl.util.ArrayUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Expression extends Generic { public class Expression extends Generic {
protected static final Converter<Variable, Generic> FACTORIZE_CONVERTER = new Converter<Variable, Generic>() { protected static final Converter<Variable, Generic> FACTORIZE_CONVERTER = new Converter<Variable, Generic>() {

View File

@ -4,12 +4,22 @@ import jscl.math.function.Constant;
import jscl.mathml.MathML; import jscl.mathml.MathML;
import jscl.text.ParserUtils; import jscl.text.ParserUtils;
import javax.annotation.Nonnull; import java.math.BigInteger;
import javax.annotation.Nullable;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class Generic implements Arithmetic<Generic>, Comparable { public abstract class Generic implements Arithmetic<Generic>, Comparable {
public BigInteger toBigInteger() {
return null;
}
public Double toDouble() {
return null;
}
@Nonnull @Nonnull
public Generic subtract(@Nonnull Generic that) { public Generic subtract(@Nonnull Generic that) {
return add(that.negate()); return add(that.negate());

View File

@ -4,12 +4,13 @@ import jscl.JsclMathEngine;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.mathml.MathML; import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class JsclInteger extends Generic { public final class JsclInteger extends Generic {
public static final JsclInteger factory = new JsclInteger(BigInteger.valueOf(0)); public static final JsclInteger factory = new JsclInteger(BigInteger.valueOf(0));
@ -364,4 +365,14 @@ public final class JsclInteger extends Generic {
e1.appendChild(element.text(String.valueOf(content))); e1.appendChild(element.text(String.valueOf(content)));
element.appendChild(e1); element.appendChild(e1);
} }
@Override
public BigInteger toBigInteger() {
return content;
}
@Override
public Double toDouble() {
return content.doubleValue();
}
} }

View File

@ -4,13 +4,19 @@ import jscl.JsclMathEngine;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.math.function.Constants; import jscl.math.function.Constants;
import jscl.math.function.IConstant; import jscl.math.function.IConstant;
import jscl.math.numeric.*; import jscl.math.numeric.Complex;
import jscl.math.numeric.INumeric;
import jscl.math.numeric.Numeric;
import jscl.math.numeric.Real;
import jscl.math.numeric.Vector;
import jscl.mathml.MathML; import jscl.mathml.MathML;
import javax.annotation.Nonnull; import java.math.BigInteger;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
public final class NumericWrapper extends Generic implements INumeric<NumericWrapper> { public final class NumericWrapper extends Generic implements INumeric<NumericWrapper> {
@Nonnull @Nonnull
@ -415,7 +421,7 @@ public final class NumericWrapper extends Generic implements INumeric<NumericWra
} }
public String toJava() { public String toJava() {
return "JsclDouble.valueOf(" + new Double(((Real) content).doubleValue()) + ")"; return "JsclDouble.valueOf(" + ((Real) content).doubleValue() + ")";
} }
public void toMathML(MathML element, Object data) { public void toMathML(MathML element, Object data) {
@ -442,4 +448,14 @@ public final class NumericWrapper extends Generic implements INumeric<NumericWra
e1.appendChild(element.text(String.valueOf(new Double(((Real) content).doubleValue())))); e1.appendChild(element.text(String.valueOf(new Double(((Real) content).doubleValue()))));
element.appendChild(e1); element.appendChild(e1);
} }
@Override
public BigInteger toBigInteger() {
return content.toBigInteger();
}
@Override
public Double toDouble() {
return content.toDouble();
}
} }

View File

@ -5,11 +5,12 @@ import jscl.math.function.Fraction;
import jscl.math.function.Inverse; import jscl.math.function.Inverse;
import jscl.mathml.MathML; import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
public final class Rational extends Generic implements Field { public final class Rational extends Generic implements Field {
public static final Rational factory = new Rational(BigInteger.valueOf(0), BigInteger.valueOf(1)); public static final Rational factory = new Rational(BigInteger.valueOf(0), BigInteger.valueOf(1));
@ -308,4 +309,18 @@ public final class Rational extends Generic implements Field {
element.appendChild(e1); element.appendChild(e1);
} }
} }
@Override
public BigInteger toBigInteger() {
try {
return integerValue().toBigInteger();
} catch (NotIntegerException e) {
return null;
}
}
@Override
public Double toDouble() {
return numerator.doubleValue() / denominator.doubleValue();
}
} }

View File

@ -1,14 +1,16 @@
package jscl.math.numeric; package jscl.math.numeric;
import static jscl.math.numeric.Complex.I;
import static jscl.math.numeric.Real.ONE;
import static jscl.math.numeric.Real.TWO;
import jscl.AngleUnit; import jscl.AngleUnit;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.math.Arithmetic; import jscl.math.Arithmetic;
import javax.annotation.Nonnull; import java.math.BigInteger;
import static jscl.math.numeric.Complex.I; import javax.annotation.Nonnull;
import static jscl.math.numeric.Real.ONE;
import static jscl.math.numeric.Real.TWO;
public abstract class Numeric implements Arithmetic<Numeric>, INumeric<Numeric>, Comparable { public abstract class Numeric implements Arithmetic<Numeric>, INumeric<Numeric>, Comparable {
@ -325,4 +327,12 @@ public abstract class Numeric implements Arithmetic<Numeric>, INumeric<Numeric>,
protected String toString(final double value) { protected String toString(final double value) {
return JsclMathEngine.getInstance().format(value, JsclMathEngine.getInstance().getNumeralBase()); return JsclMathEngine.getInstance().format(value, JsclMathEngine.getInstance().getNumeralBase());
} }
public BigInteger toBigInteger() {
return null;
}
public Double toDouble() {
return null;
}
} }

View File

@ -2,6 +2,8 @@ package jscl.math.numeric;
import jscl.math.NotDivisibleException; import jscl.math.NotDivisibleException;
import java.math.BigInteger;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public final class Real extends Numeric { public final class Real extends Numeric {
@ -277,4 +279,17 @@ public final class Real extends Numeric {
public Complex toComplex() { public Complex toComplex() {
return Complex.valueOf(this.content, 0.); return Complex.valueOf(this.content, 0.);
} }
@Override
public BigInteger toBigInteger() {
if (content == Math.floor(content)) {
return BigInteger.valueOf((long) content);
}
return null;
}
@Override
public Double toDouble() {
return content;
}
} }