// Copyright (C) 2014 Bonsai Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package com.bonsai.wallet32;
import android.content.Context;
import android.content.res.Resources;
public class BTCFmt {
public final static int SCALE_BTC = 8;
public final static int SCALE_MBTC = 5;
public final static int SCALE_UBTC = 2;
private int mScale;
private String mUnitStr;
public BTCFmt(int scale, Context ctxt) {
mScale = scale;
Resources res = ctxt.getResources();
switch (mScale) {
case SCALE_BTC:
mUnitStr = res.getString(R.string.app_units_btc);
break;
case SCALE_MBTC:
mUnitStr = res.getString(R.string.app_units_mbtc);
break;
case SCALE_UBTC:
mUnitStr = res.getString(R.string.app_units_ubtc);
break;
default:
throw new RuntimeException(String.format("unknown scale %d", mScale));
}
}
public String unitStr() {
return mUnitStr;
}
// Returns the minimum length scaled string which maintains all
// necessary precision.
//
public String format(long amt) {
return formatInternal(mScale, amt, 0, false, false);
}
// Used for formatting column aligned values.
//
public String formatCol(long amt,
int reducePrecision,
boolean colPad,
boolean triSpace) {
return formatInternal(mScale, amt, reducePrecision, colPad, triSpace);
}
// Always formats using the BTC units, for cases where scaled
// units are not acceptable (eg: request urls)
//
public String formatBTC(long amt) {
return formatInternal(SCALE_BTC, amt, 0, false, false);
}
protected String formatInternal(int scale,
long amt,
int reducePrecision,
boolean colPad,
boolean triSpace) {
// Convert negative numbers to positive, reverse at end.
boolean isNeg = false;
if (amt < 0) {
amt = -amt;
isNeg = true;
}
if (reducePrecision > 0) {
double factor = Math.pow(10, reducePrecision);
amt = Math.round(((double) amt) / factor);
}
StringBuilder sb = new StringBuilder();
sb.append(Long.toString(amt));
// How wide should the fractional field be?
int fracWidth = scale - reducePrecision;
// Add left padding as necessary.
int leftPadLen = fracWidth + 1 - sb.length();
if (leftPadLen > 0)
for (int ii = 0; ii < leftPadLen; ++ii)
sb.insert(0, "0");
// Insert the decimal point.
sb.insert(sb.length() - fracWidth, ".");
// Remove trailing '0' characters.
if (colPad) {
// Replace trailing '0' with ' '.
int ndx;
for (ndx = sb.length() - 1; ndx >= 0; --ndx) {
if (sb.charAt(ndx) == '0')
sb.replace(ndx, ndx+1, " ");
else
break;
}
// If the last character is the '.', replace it too.
if (sb.charAt(ndx) == '.')
sb.replace(ndx, ndx+1, " ");
} else {
// Just remove the characters.
while (sb.charAt(sb.length() - 1) == '0')
sb.deleteCharAt(sb.length() - 1);
// If the last character is the '.', remove it too.
if (sb.charAt(sb.length() - 1) == '.')
sb.deleteCharAt(sb.length() - 1);
}
if (triSpace) {
// Insert leading tri-spaces
int ndx = sb.indexOf(".");
if (ndx == -1) {
// Find the last non-space char.
for (ndx = sb.length() - 1; ndx >= 0; ndx--)
if (sb.charAt(ndx) != ' ')
break;
++ndx;
}
while (ndx - 3 > 0) {
ndx -= 3;
sb.insert(ndx, '\u202F');
}
// Insert following tri-spaces
ndx = sb.indexOf(".");
if (ndx == -1) {
// Find the last non-space char.
for (ndx = sb.length() - 1; ndx >= 0; ndx--)
if (sb.charAt(ndx) != ' ')
break;
++ndx;
}
++ndx;
while (ndx + 3 < sb.length() - 1) {
ndx += 3;
sb.insert(ndx, '\u202F');
++ndx;
}
}
// If we were negative prepend a "-".
if (isNeg)
sb.insert(0, '-');
return sb.toString();
}
public long parse(String valstr) throws NumberFormatException {
// Some countries use comma as the decimal separator.
// Android's numberDecimal EditText fields don't handle this
// correctly (https://code.google.com/p/android/issues/detail?id=2626).
// As a workaround we substitute ',' -> '.' manually ...
double dval = Double.parseDouble(valstr.toString().replace(',', '.'));
return (long)(dval * Math.pow(10, mScale));
}
public double fiatAtRate(long btc, double fiatPerBTC) {
// Fiat is always expressed per BTC, not mBTC, for example.
final int fiatScale = 8;
double dval = ((double) btc) / Math.pow(10, fiatScale);
return dval * fiatPerBTC;
}
public long btcAtRate(double fiat, double fiatPerBTC) {
// Fiat is always expressed per BTC, not mBTC, for example.
final int fiatScale = 8;
return (long) ((fiat / fiatPerBTC) * Math.pow(10, fiatScale));
}
}
// Local Variables:
// mode: java
// c-basic-offset: 4
// tab-width: 4
// End: