diff --git a/src/Decentralized/ModFiles/Localization/en.csv b/src/Decentralized/ModFiles/Localization/en.csv index ad4f72d..a030996 100644 --- a/src/Decentralized/ModFiles/Localization/en.csv +++ b/src/Decentralized/ModFiles/Localization/en.csv @@ -24,7 +24,6 @@ wallet.empty,The wallet is empty. wallet.total,Total value: {0} credits wallet.taint,Tainted value: {0} credits trade.amount,Amount -trade.hint,Buy spends the amount in the quote coin. Sell sells the amount of the traded coin. trade.deposit,Deposit credits as CRC trade.withdraw,Withdraw CRC as credits trade.pair,"{0}/{1} ({2})" @@ -146,8 +145,21 @@ entry.web3.l2,"About {0} credits" bank.cash,"Credits: {0}" bank.rent,"Rent: {0} credits, due in {1} days" bank.crc,"Poinbase account (CRC): {0}" -bank.hint,"Deposit turns credits into CRC; withdrawing turns CRC back into credits and passes compliance review." poin.account,"Poinbase account: CRC {0}, PSC {1}" avg.line,"{0} average buy price: {1} credits" avg.short,"avg. buy {0}" avg.none,"—" +col.asset,"Asset" +col.amount,"Amount" +col.value,"Value" +col.avg,"Avg. buy" +bank.cash.k,"Credits" +bank.rent.k,"Rent" +bank.rent.v,"{0}, due in {1} days" +bank.crc.k,"Poinbase account (CRC)" +bank.ops,"Deposit / withdraw" +poin.account.h,"Poinbase account" +trade.h,"Trade" +web3.wallet.h,"On-chain wallet" +trade.hint,"Buying pays in the quote coin; |selling sells the traded coin." +bank.hint,"Deposit turns credits into CRC; |withdrawing turns CRC back into credits |and passes compliance review." diff --git a/src/Decentralized/ModFiles/Localization/zh.csv b/src/Decentralized/ModFiles/Localization/zh.csv index 9fa0a11..61df222 100644 --- a/src/Decentralized/ModFiles/Localization/zh.csv +++ b/src/Decentralized/ModFiles/Localization/zh.csv @@ -23,7 +23,6 @@ wallet.empty,钱包为空。 wallet.total,总值:{0} 信用点 wallet.taint,污点:{0} 信用点 trade.amount,数量 -trade.hint,买入按计价币的数量支付;卖出按所交易币的数量卖出。 trade.deposit,存入信用点(换成 CRC) trade.withdraw,提取 CRC(换成信用点) trade.pair,{0}/{1}({2}) @@ -145,8 +144,21 @@ entry.web3.l2,"约 {0} 信用点" bank.cash,"信用点:{0}" bank.rent,"房租:{0} 信用点,{1} 天后支付" bank.crc,"Poinbase 账户(CRC):{0}" -bank.hint,"存入把信用点换成 CRC,提取把 CRC 换回信用点,提取要过合规审查。" poin.account,"Poinbase 账户:CRC {0},PSC {1}" avg.line,"{0} 买入均价:{1} 信用点" avg.short,"买入均价 {0}" avg.none,"—" +col.asset,"币种" +col.amount,"数量" +col.value,"估值" +col.avg,"买入均价" +bank.cash.k,"信用点" +bank.rent.k,"房租" +bank.rent.v,"{0},{1} 天后支付" +bank.crc.k,"Poinbase 账户(CRC)" +bank.ops,"存取" +poin.account.h,"Poinbase 账户" +trade.h,"交易" +web3.wallet.h,"链上钱包" +trade.hint,"买入按计价币的数量支付;|卖出按所交易币的数量卖出。" +bank.hint,"存入把信用点换成 CRC;|提取把 CRC 换回信用点,|提取要过合规审查。" diff --git a/src/Decentralized/TerminalWindow.cs b/src/Decentralized/TerminalWindow.cs index 4e05092..aea83af 100644 --- a/src/Decentralized/TerminalWindow.cs +++ b/src/Decentralized/TerminalWindow.cs @@ -24,7 +24,7 @@ namespace Decentralized if (Session.Data == null) return; var b = CustomUIManager.Window(Id, L.T("term.title")); if (b == null) return; - b.SetSize(640, 580).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle(); + b.SetSize(780, 580).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle(); b.BeginRow(); foreach (Page p in Enum.GetValues(typeof(Page))) { @@ -52,7 +52,7 @@ namespace Decentralized private static void Entry(CustomUIBuilder b, string icon, string name, string line1, string line2, Page target) { - b.BeginPanel(190f, 250f, TextAnchor.UpperCenter, 10f, 6f); + b.BeginPanel(220f, 250f, TextAnchor.UpperCenter, 10f, 6f); b.AddImage(ModInfo.Id + ":" + icon, 96f, 96f); b.AddHeader(name); b.AddLabel(line1); @@ -79,31 +79,69 @@ namespace Decentralized b.AddLabel(r == null ? L.T("report.none") : L.T("home.lastnight", r.Day, Fmt.Num(r.Mined), r.PoweredRigs, r.Rigs)); } + private const float LeftW = 430f, RightW = 300f; + + private static void Cell(CustomUIBuilder b, float w, string text, bool header = false) + { + b.BeginPanel(w, 30f, TextAnchor.MiddleLeft, 6f, 0f); + b.AddLabel(header ? "" + text + "" : text); + b.End(); + } + + private static void TableRow(CustomUIBuilder b, float[] widths, params string[] cells) + { + b.BeginRow(2f); + for (int i = 0; i < widths.Length; i++) Cell(b, widths[i], i < cells.Length ? cells[i] : ""); + b.End(); + } + + private static void TableHeader(CustomUIBuilder b, float[] widths, params string[] cells) + { + b.BeginRow(2f); + for (int i = 0; i < widths.Length; i++) Cell(b, widths[i], cells[i], true); + b.End(); + } + + /// 左右分栏:左边是账户与持仓表格,右边是操作区。 + private static void Columns(CustomUIBuilder b, Action left, Action right) + { + b.BeginRow(10f); + b.BeginPanel(LeftW, -1f, TextAnchor.UpperLeft, 8f, 4f); + left(b); + b.End(); + b.BeginPanel(RightW, -1f, TextAnchor.UpperLeft, 8f, 6f); + right(b); + b.End(); + b.End(); + } + private static void AmountRow(CustomUIBuilder b) { - b.BeginRow(); b.AddLabel(L.T("trade.amount")); - b.BeginPanel(240f, -1f, TextAnchor.MiddleCenter, 0f, 0f); // 给输入框一个固定宽度,容得下大额数字 + b.BeginPanel(RightW - 30f, -1f, TextAnchor.MiddleCenter, 0f, 0f); // 给输入框一个固定宽度,容得下大额数字 b.AddInput("0", _amount, s => _amount = s, "amount", s => _amount = s); b.End(); - b.End(); } /// 银行:真实的信用点。现金、房租,以及信用点与 Poinbase 账户(CRC)之间的存取。 private static void BankPage(CustomUIBuilder b) { var ps = PlayerStore.Instance; - b.AddHeader(L.T("entry.bank")); - b.AddLabel(L.T("bank.cash", ps.playerCash)); - b.AddLabel(L.T("bank.rent", Session.Rent(), ps.GetRentDayCounter())); - b.AddLabel(L.T("bank.crc", Fmt.Num(Session.Data.Hot.Get(Assets.CRC)))); - b.AddSeparator(); - b.AddLabel(L.T("bank.hint")); - AmountRow(b); - b.BeginRow(); - b.AddButton(L.T("trade.deposit"), Deposit); - b.AddButton(L.T("trade.withdraw"), Withdraw); - b.End(); + var w = new[] { 200f, 220f }; + Columns(b, l => + { + l.AddHeader(L.T("entry.bank")); + TableRow(l, w, L.T("bank.cash.k"), ps.playerCash.ToString()); + TableRow(l, w, L.T("bank.rent.k"), L.T("bank.rent.v", Session.Rent(), ps.GetRentDayCounter())); + TableRow(l, w, L.T("bank.crc.k"), Fmt.Num(Session.Data.Hot.Get(Assets.CRC))); + }, r => + { + r.AddHeader(L.T("bank.ops")); + foreach (var line in L.T("bank.hint").Split('|')) r.AddLabel(line); + AmountRow(r); + r.AddButton(L.T("trade.deposit"), Deposit); + r.AddButton(L.T("trade.withdraw"), Withdraw); + }); } private static void TradeRows(CustomUIBuilder b, Venue venue) @@ -119,34 +157,55 @@ namespace Decentralized } } - /// Poinbase:合规交易所。账户余额与交易对;信用点的存取在银行。 + private static readonly float[] HoldW = { 80f, 100f, 110f, 110f }; + + private static void Holdings(CustomUIBuilder b, Wallet w, Func show) + { + TableHeader(b, HoldW, L.T("col.asset"), L.T("col.amount"), L.T("col.value"), L.T("col.avg")); + bool any = false; + foreach (var kv in w.Balances.OrderBy(k => k.Key).Where(k => show(k.Key))) + { + any = true; + TableRow(b, HoldW, kv.Key, Fmt.Num(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key)), AvgText(w, kv.Key)); + } + if (!any) b.AddLabel(L.T("wallet.empty")); + } + + /// Poinbase:合规交易所。左边账户持仓,右边交易;信用点的存取在银行。 private static void ExchangePage(CustomUIBuilder b, Venue venue) { var w = Session.Data.Hot; - b.AddHeader(L.T("entry.poinbase")); - b.AddLabel(L.T("poin.account", Fmt.Num(w.Get(Assets.CRC)), Fmt.Num(w.Get(Assets.PSC)))); - b.AddLabel(L.T("avg.line", Assets.PSC, AvgText(w, Assets.PSC))); - b.AddLabel(L.T("trade.hint")); - AmountRow(b); - b.AddSeparator(); - TradeRows(b, venue); + Columns(b, l => + { + l.AddHeader(L.T("poin.account.h")); + Holdings(l, w, a => a == Assets.CRC || a == Assets.PSC); + }, r => + { + r.AddHeader(L.T("trade.h")); + foreach (var line in L.T("trade.hint").Split('|')) r.AddLabel(line); + AmountRow(r); + TradeRows(r, venue); + }); } /// Web3:链上钱包与去中心化交易。 private static void Web3Page(CustomUIBuilder b) { var w = Session.Data.Hot; - b.AddHeader(L.T("entry.web3")); - 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))) + " " + L.T("avg.short", AvgText(w, kv.Key))); - 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))); - b.AddSeparator(); - b.AddLabel(L.T("trade.hint")); - AmountRow(b); - b.AddSeparator(); - TradeRows(b, Venue.Dex); + Columns(b, l => + { + l.AddHeader(L.T("web3.wallet.h")); + Holdings(l, w, a => true); + l.AddSeparator(); + l.AddLabel(L.T("wallet.total", Fmt.Credits(w.Value(Session.Price)))); + if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint))); + }, r => + { + r.AddHeader(L.T("trade.h")); + foreach (var line in L.T("trade.hint").Split('|')) r.AddLabel(line); + AmountRow(r); + TradeRows(r, Venue.Dex); + }); } private static string AvgText(Wallet w, string asset) => w.AvgBuy(asset) is double a ? Fmt.Num(a) : L.T("avg.none");