Terminal: two-column pages with table cells (holdings on the left, trading on the right)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Sonnet 5.5 committed 2026-11-03 15:41:42 +08:00
1 parent a2dc1dd2f6
commit 00f7811e7c
3 files changed
+122 -39

No files matched your search

+14 -2
View File
@@ -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."
1 # Probably Decentralized localization table: English (en)
24 wallet.total
25 wallet.taint
26 trade.amount
trade.hint
27 trade.deposit
28 trade.withdraw
29 trade.pair
145 bank.cash
146 bank.rent
147 bank.crc
bank.hint
148 poin.account
149 avg.line
150 avg.short
151 avg.none
152 col.asset
153 col.amount
154 col.value
155 col.avg
156 bank.cash.k
157 bank.rent.k
158 bank.rent.v
159 bank.crc.k
160 bank.ops
161 poin.account.h
162 trade.h
163 web3.wallet.h
164 trade.hint
165 bank.hint
+14 -2
View File
@@ -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 换回信用点,|提取要过合规审查。"
1 # Probably Decentralized 本地化表:简体中文(zh)
23 wallet.total
24 wallet.taint
25 trade.amount
trade.hint
26 trade.deposit
27 trade.withdraw
28 trade.pair
144 bank.cash
145 bank.rent
146 bank.crc
bank.hint
147 poin.account
148 avg.line
149 avg.short
150 avg.none
151 col.asset
152 col.amount
153 col.value
154 col.avg
155 bank.cash.k
156 bank.rent.k
157 bank.rent.v
158 bank.crc.k
159 bank.ops
160 poin.account.h
161 trade.h
162 web3.wallet.h
163 trade.hint
164 bank.hint
+94 -35
View File
@@ -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 ? "<b>" + text + "</b>" : 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();
}
/// <summary>左右分栏:左边是账户与持仓表格,右边是操作区。</summary>
private static void Columns(CustomUIBuilder b, Action<CustomUIBuilder> left, Action<CustomUIBuilder> 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();
}
/// <summary>银行:真实的信用点。现金、房租,以及信用点与 Poinbase 账户(CRC)之间的存取。</summary>
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
}
}
/// <summary>Poinbase:合规交易所。账户余额与交易对;信用点的存取在银行。</summary>
private static readonly float[] HoldW = { 80f, 100f, 110f, 110f };
private static void Holdings(CustomUIBuilder b, Wallet w, Func<string, bool> 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"));
}
/// <summary>Poinbase:合规交易所。左边账户持仓,右边交易;信用点的存取在银行。</summary>
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);
});
}
/// <summary>Web3:链上钱包与去中心化交易。</summary>
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");