package org.ripple.power.txns;
import com.ripple.client.Client;
import com.ripple.client.requests.Request;
import com.ripple.client.responses.Response;
import com.ripple.core.coretypes.AccountID;
import com.ripple.core.coretypes.Amount;
import com.ripple.core.coretypes.Issue;
import com.ripple.core.coretypes.STArray;
import com.ripple.core.coretypes.STObject;
import com.ripple.core.types.known.sle.entries.Offer;
import org.json.JSONArray;
import org.json.JSONObject;
import org.ripple.power.config.LSystem;
import org.ripple.power.ui.RPClient;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
public abstract class OfferPrice {
public static boolean isSellOrder(long flag) {
return (flag & 0x00020000) > 0;
}
private final static double LOG10 = Math.log(10.0d);
public static double adjustValueFloor(double value, double digit) {
double n = Math.pow(10d, digit);
return Math.floor(value * n) / n;
}
public static double adjustValueCeil(double value, double digit) {
double n = Math.pow(10d, digit);
return Math.ceil(value * n) / n;
}
public static double numberOfDigits(double value) {
return Math.floor(Math.log(value) / LOG10) + 1;
}
protected static ArrayList<Store> _storage = new ArrayList<Store>();
private static class Store {
public String price;
public String name;
public long date = 0;
public Store(String p, String str) {
this.price = p;
this.name = str;
this.date = System.currentTimeMillis();
}
}
private static String reset(String name) {
for (Store s : _storage) {
if (s.name.equals(name)
&& (System.currentTimeMillis() - s.date) <= LSystem.MINUTE) {
return s.price;
} else if (s.name.equals(name)) {
_storage.remove(s);
return null;
}
}
return null;
}
private static void addStorage(Store s) {
_storage.add(s);
if (_storage.size() > 100) {
_storage.remove(0);
}
}
public synchronized static String getMoneyConvert(String srcValue,
String src, String dst) {
if (srcValue == null || src == null | dst == null) {
return "unkown";
}
if (src.equalsIgnoreCase(dst)) {
return srcValue;
}
if ("ker".equalsIgnoreCase(src) || "won".equalsIgnoreCase(src)) {
src = "krw";
}
if ("ker".equalsIgnoreCase(dst) || "won".equalsIgnoreCase(dst)) {
dst = "krw";
}
String name = (srcValue + src + dst).trim().toLowerCase();
String ret = reset(name);
if (ret != null) {
return ret;
}
String oneValue = null;
String twoValue = null;
try {
oneValue = OtherData.getCoinmarketcapCoinToUSD(src);
twoValue = OtherData.getCoinmarketcapCoinToUSD(dst);
if (oneValue != null && twoValue != null) {
BigDecimal a1 = new BigDecimal(oneValue);
BigDecimal b1 = new BigDecimal(twoValue);
String result = LSystem.getNumber(a1.divide(b1,
MathContext.DECIMAL128).multiply(
new BigDecimal(srcValue)));
addStorage(new Store(result, name));
return result;
}
} catch (Exception ex) {
// null
oneValue = null;
twoValue = null;
}
try {
String tmp = OtherData.converterMoney(src, dst);
if (tmp != null) {
BigDecimal srcValueb = new BigDecimal(srcValue);
BigDecimal valueb = new BigDecimal(tmp);
String result = LSystem.getNumber(srcValueb.multiply(valueb));
addStorage(new Store(result, name));
return result;
} else {
if (oneValue == null) {
oneValue = OtherData.converterMoney(src, "usd");
}
if (oneValue == null) {
oneValue = OtherData.getCoinmarketcapCoinToUSD(src);
}
if (oneValue != null) {
if (twoValue == null) {
twoValue = OtherData.converterMoney(dst, "usd");
}
if (twoValue != null) {
BigDecimal srcValueb = new BigDecimal(oneValue);
BigDecimal valueb = new BigDecimal(twoValue);
String result = LSystem.getNumber(srcValueb.divide(
valueb, MathContext.DECIMAL128).multiply(
new BigDecimal(srcValue)));
addStorage(new Store(result, name));
return result;
} else {
double yahooValue = OtherData
.getLegaltenderCurrencyToUSD(src);
if (yahooValue != -1) {
if (twoValue == null) {
twoValue = OtherData.converterMoney(dst, "usd");
}
if (twoValue != null) {
BigDecimal srcValueb = new BigDecimal(
yahooValue);
BigDecimal valueb = new BigDecimal(twoValue);
String result = LSystem.getNumber(srcValueb
.divide(valueb, MathContext.DECIMAL128)
.multiply(new BigDecimal(srcValue)));
addStorage(new Store(result, name));
return result;
} else {
addStorage(new Store("unkown", name));
return "unkown";
}
}
}
}
}
} catch (Exception ex) {
return "unkown";
}
return "unkown";
}
public static class OfferFruit {
public String message;
public Offer offer;
public String toString() {
return message;
}
}
public boolean subscribe = false;
public String highBuy;
public String highSell;
public String spread;
public abstract void buy(Offer offer);
public abstract void sell(Offer offer);
public abstract void empty();
public abstract void error(JSONObject obj);
public abstract void complete(ArrayList<OfferFruit> buys,
ArrayList<OfferFruit> sells, OfferPrice price);
public static void load(String address, String buyCurName,
String sellCurName, OfferPrice price) {
load(address, buyCurName, sellCurName, price, true);
}
public static void load(String address, String buyCurName,
String sellCurName, OfferPrice price, boolean html) {
AccountID account = AccountID.fromAddress(address);
RPClient ripple = RPClient.ripple();
if (ripple != null) {
Issue buy = account.issue(buyCurName);
Issue sell = account.issue(sellCurName);
load(ripple.getClinet(), buy, sell, price, html);
}
}
public static void load(IssuedCurrency buy, IssuedCurrency sell,
OfferPrice price) {
load(buy, sell, price, true);
}
public static void load(IssuedCurrency buy, IssuedCurrency sell,
OfferPrice price, boolean html) {
RPClient ripple = RPClient.ripple();
if (ripple != null) {
load(ripple.getClinet(), buy.getIssue(), sell.getIssue(), price,
html);
}
}
public static void load(Issue buy, Issue sell, OfferPrice price) {
load(buy, sell, price, true);
}
public static void load(Issue buy, Issue sell, OfferPrice price,
boolean html) {
RPClient ripple = RPClient.ripple();
if (ripple != null) {
load(ripple.getClinet(), buy, sell, price, html);
}
}
public static class OrderBooks {
public static interface BookEvents {
public void onUpdate(OrderBooks book);
}
private Client client;
private int limit = 30;
private final BookEvents callback;
public Issue first, second;
public STArray asks, bids;
public Amount ask, bid, spread;
public OrderBooks(Client client, Issue first, Issue second,
BookEvents callback) {
this(client, first, second, 30, callback);
}
public OrderBooks(Client client, Issue first, Issue second, int limit,
BookEvents callback) {
this.limit = limit;
this.client = client;
this.first = first;
this.second = second;
this.callback = callback;
}
private void calculateStats() {
Offer firstAsk = (Offer) asks.get(0);
Offer firstBid = (Offer) bids.get(0);
BigDecimal askQuality = firstAsk.askQuality();
BigDecimal bidQuality = firstBid.bidQuality();
Amount secondOne = firstAsk.paysOne();
ask = secondOne.multiply(askQuality);
bid = secondOne.multiply(bidQuality);
spread = ask.subtract(bid).abs();
}
private void requestUpdate(final OfferPrice price) {
for (int i = 0; i < 2; i++) {
final boolean getAsks = i == 0, getBids = !getAsks;
Issue getIssue = getAsks ? first : second, payIssue = getAsks ? second
: first;
Request request = null;
if (price.subscribe) {
request = client.subscribeBookOffers(getIssue, payIssue);
} else {
request = client.requestBookOffers(getIssue, payIssue);
}
request.json("limit", limit);
request.once(Request.OnResponse.class,
new Request.OnResponse() {
@Override
public void called(Response response) {
if (response.succeeded) {
JSONArray offersJSON = response.result
.optJSONArray("offers");
STArray offers = STArray.translate
.fromJSONArray(offersJSON);
if (getBids) {
bids = offers;
} else {
asks = offers;
}
if (retrievedBothBooks()) {
if (!isEmpty()) {
calculateStats();
}
callback.onUpdate(OrderBooks.this);
}
} else {
price.error(response.message);
}
}
});
request.once(Request.OnError.class, new Request.OnError() {
@Override
public void called(Response response) {
price.error(response.message);
}
});
request.request();
}
}
public boolean retrievedBothBooks() {
return asks != null && bids != null;
}
public boolean isEmpty() {
return !retrievedBothBooks() || asks.isEmpty() || bids.isEmpty();
}
}
private static void load(Client client, final Issue first,
final Issue second, final OfferPrice price, final boolean html) {
if (price == null) {
return;
}
new OrderBooks(client, first, second, new OrderBooks.BookEvents() {
@Override
public void onUpdate(OrderBooks book) {
ArrayList<OfferFruit> buys = new ArrayList<OfferFruit>(100);
ArrayList<OfferFruit> sells = new ArrayList<OfferFruit>(100);
if (!book.isEmpty()) {
price.highBuy = book.bid.toText();
price.highSell = book.ask.toText();
price.spread = book.spread.toText();
// sell
for (STObject offer : book.asks) {
Offer o = (Offer) offer;
price.sell(o);
BigDecimal payForOne = o.askQuality();
Amount paysOne = o.paysOne();
Amount getsOne = o.getsOne();
OfferFruit fruit = new OfferFruit();
fruit.offer = o;
if (html) {
fruit.message = o.takerGets().toText()
+ "<br><font size=5 color=red>Sell</font><br>"
+ (o.takerPays().toText())
+ "<br><font size=5 color=green>Exchange rate</font><br>"
+ getsOne.toText() + "=="
+ paysOne.multiply(payForOne).toText()
+ "<br>"
+ getsOne.divide(payForOne).toText() + "=="
+ paysOne.toText();
}
sells.add(fruit);
}
// buy
for (STObject offer : book.bids) {
Offer o = (Offer) offer;
price.buy(o);
BigDecimal payForOne = o.askQuality();
Amount paysOne = o.paysOne();
Amount getsOne = o.getsOne();
OfferFruit fruit = new OfferFruit();
fruit.offer = o;
if (html) {
fruit.message = o.takerGets().toText()
+ "<br><font size=5 color=green>Buy</font><br>"
+ (o.takerPays().toText())
+ "<br><font size=5 color=red>Exchange rate</font><br>"
+ paysOne.multiply(payForOne).toText()
+ "==" + getsOne.toText() + "<br>"
+ paysOne.toText() + "=="
+ getsOne.divide(payForOne).toText();
}
buys.add(fruit);
}
} else {
// empty
price.empty();
}
price.complete(buys, sells, price);
}
}).requestUpdate(price);
}
}