Files
probably-decentralized/src/Decentralized/TerminalWindow.cs
T

151 lines
6.1 KiB
C#
Raw Normal View History

using System;
using System.Globalization;
using System.Linq;
using Decentralized.Domain;
namespace Decentralized
{
/// <summary>交易终端窗口:钱包、交易、报告三页。每次操作后按当前页重建窗口。</summary>
public static class TerminalWindow
{
public const string Id = "pd_terminal";
private enum Page { Wallet, Trade, Report }
private static Page _page = Page.Wallet;
private static string _amount = "";
private static string _message;
public static void Open()
{
if (Session.Data == null) return;
var b = CustomUIManager.Window(Id, L.T("term.title"));
if (b == null) return;
b.SetSize(620, 560).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle();
b.BeginRow();
foreach (Page p in Enum.GetValues(typeof(Page)))
{
var page = p;
string name = L.T("tab." + p.ToString().ToLowerInvariant());
b.AddButton(page == _page ? $"[{name}]" : name, () => { _page = page; _message = null; Open(); });
}
b.End();
b.AddSeparator();
b.BeginScroll(440);
switch (_page)
{
case Page.Wallet: WalletPage(b); break;
case Page.Trade: TradePage(b); break;
default: ReportPage(b); break;
}
b.End();
if (!string.IsNullOrEmpty(_message)) b.AddLabel(_message);
b.Show();
}
private static void WalletPage(CustomUIBuilder b)
{
var w = Session.Data.Hot;
if (w.Balances.Count == 0) b.AddLabel(L.T("wallet.empty"));
foreach (var kv in w.Balances.OrderBy(k => k.Key))
b.AddLabel(L.T("wallet.line", kv.Key, Fmt.Num(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key))));
b.AddSeparator();
b.AddLabel(L.T("wallet.total", Fmt.Credits(w.Value(Session.Price))));
if (w.Taint > 0.5) b.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)));
}
private static void TradePage(CustomUIBuilder b)
{
b.AddLabel(L.T("trade.hint"));
b.BeginRow();
b.AddLabel(L.T("trade.amount"));
b.AddInput("0", _amount, s => _amount = s, "amount", s => _amount = s);
b.End();
b.BeginRow();
b.AddButton(L.T("trade.deposit"), Deposit);
b.AddButton(L.T("trade.withdraw"), Withdraw);
b.End();
b.AddSeparator();
foreach (var pool in Session.Data.Market.Pools)
{
var p = pool;
b.AddLabel(L.T("trade.pair", p.Base, p.Quote, L.T("venue." + p.Venue)) + " " + L.T("trade.price", Fmt.Num(p.Price)));
b.BeginRow();
b.AddButton(L.T("trade.buy"), () => Trade(p, buy: true));
b.AddButton(L.T("trade.sell"), () => Trade(p, buy: false));
b.End();
}
}
private static void ReportPage(CustomUIBuilder b)
{
var r = Session.Data.LastNight;
if (r == null) { b.AddLabel(L.T("report.none")); return; }
b.AddHeader(L.T("report.day", r.Day));
b.AddLabel(L.T("report.rigs", r.PoweredRigs, r.Rigs));
b.AddLabel(L.T("report.hash", Fmt.Num(r.Hash * 10), Fmt.Num(r.NetworkHash * 10)));
b.AddLabel(L.T("report.mined", Fmt.Num(r.Mined), Fmt.Credits(r.Mined * r.Price)));
b.AddLabel(L.T("report.energy", Fmt.Num(r.Kj)));
b.AddLabel(L.T("report.burnt", r.Burnt.Count));
foreach (var n in r.Burnt) b.AddLabel(" " + n);
b.AddLabel(L.T("report.price", Fmt.Num(r.Price)));
}
private static bool ReadAmount(out double v)
{
if (!double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out v) || v <= 0)
{
_message = L.T("msg.amount");
Open();
return false;
}
return true;
}
private static void Deposit()
{
if (!ReadAmount(out double v)) return;
int credits = (int)Math.Floor(v);
if (credits <= 0 || PlayerStore.Instance.playerCash < credits) { _message = L.T("msg.balance"); Open(); return; }
ModHelper.AddCredit(-credits, false);
var w = Session.Data.Hot;
w.Add(Assets.CRC, credits / Session.Data.Stable.Crc);
w.Basis += credits;
_message = L.T("msg.deposit", credits);
Session.Save();
Open();
}
private static void Withdraw()
{
if (!ReadAmount(out double v)) return;
var d = Session.Data;
if (d.Hot.Get(Assets.CRC) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
var r = d.Exchange.Cashout(d.Hot, v, Session.Price, StoreStation.GetDayCounter(), Session.Rent(), false, d.Rng);
int got = (int)Math.Floor(r.Received - r.Tax);
ModHelper.AddCredit(got, true);
_message = L.T("msg.cashout", got, Fmt.Credits(r.Tax));
if (r.Outcome == AmlOutcome.Light) _message += "\n" + L.T("msg.aml_light", Fmt.Credits(r.Confiscated));
if (r.Outcome == AmlOutcome.Heavy)
{
_message += "\n" + L.T("msg.aml_heavy", Fmt.Credits(r.Confiscated));
PlayerStore.Instance.secData.CommitCrime("FENCING", (int)Math.Round(r.Crime));
}
Session.Save();
Open();
}
private static void Trade(Pool p, bool buy)
{
if (!ReadAmount(out double v)) return;
var w = Session.Data.Hot;
string pay = buy ? p.Quote : p.Base, get = buy ? p.Base : p.Quote;
if (w.Get(pay) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
double got = buy ? p.BuyBase(v) : p.SellBase(v);
w.Add(pay, -v);
w.Add(get, got);
_message = L.T("msg.trade", Fmt.Num(v), pay, Fmt.Num(got), get);
Session.Save();
Open();
}
}
}