第十阶段 stage 2(二):CRA 部分抵押(储备、抵押率、挪用与崩盘线、劫掠补储备)、官方铸造与销毁排队、官方跑路、质押多币种入口

This commit is contained in:
ZHU MINCHAO committed 2026-11-05 07:14:38 +08:00
1 parent 3758049dcb
commit d0dfa93226
17 files changed
+493 -117

No files matched your search

+143 -32
View File
@@ -1,19 +1,43 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Decentralized.Domain namespace Decentralized.Domain
{ {
/// <summary> /// <summary>
/// 三种稳定币的价格与状态:CRC(上层,托管银行出事时脱锚、可能减记),CRT(黑市,镇压或火并时脱锚, /// 三种稳定币的价格与状态:CRC(上层,托管银行出事时脱锚、可能减记),CRT(黑市,镇压或火并时脱锚,
/// 镇压期间按黑市声望出卖客户),CRA(革命军,质押付息,补贴池告急或外生触发时进入三天死亡螺旋)。 /// 镇压期间按黑市声望出卖客户),CRA(革命军,部分抵押:流通量 S、储备 R(CRC)、抵押率 c;质押利息以无抵押的新 CRA 付出,
/// 稀释储备覆盖率 R/S;革命军挪用储备时 R/S 低于崩盘线进入三天死亡螺旋,劫掠上层补回储备)。
/// </summary> /// </summary>
public enum CraOrderKind { Minted, Burned, Lost }
/// <summary>官方一级市场的排队单:铸造(存入 CRC 和 SPARK)或销毁(存入 CRA),到期结算,官方可能把它黑掉。</summary>
public sealed class CraOrder
{
public int Id, Due;
public string Wallet;
public bool Mint;
public double Cra, Crc, Spark, C;
}
public sealed class CraOrderEvent
{
public CraOrder Order;
public CraOrderKind Kind;
public double Cra, Crc, Spark;
}
public sealed class Stablecoins public sealed class Stablecoins
{ {
public double Crc = 1, Crt = 1, Cra = 1; public double Crc = 1, Crt = 1, Cra = 1;
public int CrcDepegEnd = -1, CrtDepegEnd = -1; public int CrcDepegEnd = -1, CrtDepegEnd = -1;
public bool CrcHaircutPending; public bool CrcHaircutPending;
public double CraSubsidy = Tuning.CraSubsidy0; /// <summary>CRA 流通量与储备(CRC);c 是现在铸造要求的 CRC 份额(0~1)。</summary>
public int CraWarnDay = -1, CraSpiralDay = -1; public double Supply = Tuning.CraS0, Reserve = Tuning.CraS0 * Tuning.CraC0, C = Tuning.CraC0;
/// <summary>预兆日(新闻发出的那天)、预定的挪用日、崩盘开始日(-1 = 没有)。</summary>
public int CraWarnDay = -1, CraEventDay = -1, CraCrashDay = -1;
public List<CraOrder> Orders = new List<CraOrder>();
public int OrderSeq;
public double RevPower = 50; public double RevPower = 50;
/// <summary>平衡代币 SPARK 的价格(信用点);SparkPre 是螺旋开始前一刻的价格,螺旋三天按它的倍数走。</summary> /// <summary>平衡代币 SPARK 的价格(信用点);SparkPre 是螺旋开始前一刻的价格,螺旋三天按它的倍数走。</summary>
public double Spark = Tuning.SparkStart, SparkPre = -1; public double Spark = Tuning.SparkStart, SparkPre = -1;
@@ -45,7 +69,7 @@ namespace Decentralized.Domain
Crt = rng.Range(Tuning.CrtDepegMin, Tuning.CrtDepegMax); Crt = rng.Range(Tuning.CrtDepegMin, Tuning.CrtDepegMax);
CrtDepegEnd = day + rng.Range(Tuning.CrtDepegDaysMin, Tuning.CrtDepegDaysMax); CrtDepegEnd = day + rng.Range(Tuning.CrtDepegDaysMin, Tuning.CrtDepegDaysMax);
} }
if (ev == MarketEvent.RevRaidUpper) Spark *= Tuning.SparkRaidShock; if (ev == MarketEvent.RevRaidUpper) { Spark *= Tuning.SparkRaidShock; if (CraCrashDay < 0) Reserve += Tuning.CraLoot * Supply; }
if (ev == MarketEvent.LowerUnrest) Spark *= Tuning.SparkUnrestShock; if (ev == MarketEvent.LowerUnrest) Spark *= Tuning.SparkUnrestShock;
return 1; return 1;
} }
@@ -57,36 +81,68 @@ namespace Decentralized.Domain
/// <summary>镇压开始时是否冻结玩家的 CRT:按黑市声望,声望越低越容易被黑市"出卖"。</summary> /// <summary>镇压开始时是否冻结玩家的 CRT:按黑市声望,声望越低越容易被黑市"出卖"。</summary>
public static bool CrtFrozenByCrackdown(double blackMarketRep, Rng rng) => rng.Chance(CrtFreezeChance(blackMarketRep)); public static bool CrtFrozenByCrackdown(double blackMarketRep, Rng rng) => rng.Chance(CrtFreezeChance(blackMarketRep));
/// <summary>铸造:用 CRA 按当前价换 SPARK,收手续费。余额不足返回 -1。</summary> /// <summary>储备覆盖率 R/S。</summary>
public double Mint(Wallet w, double cra) public double Ratio => Supply > 0 ? Reserve / Supply : 1;
/// <summary>崩盘线之上的储备(CRC):吃空即必然崩盘。预测盘和线索用它估预兆。</summary>
public double Cushion => Reserve - Tuning.CraCrashRatio * Supply;
public static double Cushion0 => Tuning.CraS0 * (Tuning.CraC0 - Tuning.CraCrashRatio);
/// <summary>每晚的垫子消耗:利息按无抵押的新 CRA 付出,每份把崩盘线抬高 CraCrashRatio。</summary>
public static double CushionDrain(double stakedTotal, double rate) => stakedTotal * rate * Tuning.CraCrashRatio;
/// <summary>储备覆盖率对应的价格:高于安全线为 1,线性降到崩盘线的 1 − CraDiscountMax。</summary>
public static double PriceOfRatio(double r)
{ {
if (cra <= 0 || Spark <= 0 || w.Avail(Assets.CRA) + 1e-9 < cra) return -1; if (r >= Tuning.CraSafeRatio) return 1;
double got = cra * Cra / Spark * (1 - Tuning.SparkFee); double t = Math.Max(0, (r - Tuning.CraCrashRatio) / (Tuning.CraSafeRatio - Tuning.CraCrashRatio));
w.Add(Assets.CRA, -cra); w.Add(Assets.SPARK, got); return 1 - Tuning.CraDiscountMax * (1 - t);
w.RecordBuy(Assets.SPARK, got, cra * Cra);
return got;
} }
/// <summary>销毁:用 SPARK 按当前价换 CRA,收手续费。余额不足返回 -1。</summary> /// <summary>铸造 cra 个 CRA 要的 CRC 和 SPARK 数量(SPARK 部分按现价折算)。</summary>
public double Burn(Wallet w, double spark) public void Collateral(double cra, out double crc, out double spark)
{ {
if (spark <= 0 || Cra <= 0 || w.Avail(Assets.SPARK) + 1e-9 < spark) return -1; crc = cra * C;
double got = spark * Spark / Cra * (1 - Tuning.SparkFee); spark = Spark > 0 ? cra * (1 - C) / Spark : 0;
w.Add(Assets.SPARK, -spark); w.Add(Assets.CRA, got);
w.RecordBuy(Assets.CRA, got, spark * Spark);
return got;
} }
public bool CraSubsidyLow => CraSubsidy <= Tuning.CraSubsidy0 * Tuning.CraSubsidyWarn; /// <summary>
/// 铸造申请:从钱包扣 CRC 和 SPARK,排队 CraMintDaysMin..Max 天,到期铸出 CRA。余额不足返回 null。
/// </summary>
public CraOrder RequestMint(Wallet w, double cra, int day, Rng rng)
{
if (cra <= 0) return null;
Collateral(cra, out double crc, out double spark);
if (w.Avail(Assets.CRC) + 1e-9 < crc || w.Avail(Assets.SPARK) + 1e-9 < spark) return null;
w.Add(Assets.CRC, -crc); w.Add(Assets.SPARK, -spark);
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = true, Cra = cra, Crc = crc, Spark = spark, C = C, Due = day + rng.Range(Tuning.CraMintDaysMin, Tuning.CraMintDaysMax) };
Orders.Add(o);
return o;
}
/// <summary>销毁申请:从钱包扣 CRA,排队 CraUnlockDays 天,到期换回 CRC 和 SPARK。余额不足返回 null。</summary>
public CraOrder RequestBurn(Wallet w, double cra, int day)
{
if (cra <= 0 || w.Avail(Assets.CRA) + 1e-9 < cra) return null;
w.Add(Assets.CRA, -cra);
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = false, Cra = cra, C = C, Due = day + Tuning.CraUnlockDays };
Orders.Add(o);
return o;
}
/// <summary>官方每晚黑掉一笔排队单的概率:系数 × (1 − CRA 价格),价格不低于 1 时为 0。</summary>
public double RugChance => Math.Max(0, 1 - Cra) * Tuning.CraRugPerDepeg;
public bool CraSubsidyLow => Cushion <= Cushion0 * Tuning.CraSubsidyWarn;
/// <summary>CRA 的预兆:外生螺旋的新闻已出,或补贴池告急(利率下调)。螺旋开始后不再算预兆。</summary> /// <summary>CRA 的预兆:外生螺旋的新闻已出,或补贴池告急(利率下调)。螺旋开始后不再算预兆。</summary>
public bool CraWarning(int day) => (CraWarnDay >= 0 && CraWarnDay <= day || CraSubsidyLow) && Cra >= 0.97; public bool CraWarning(int day) => (CraWarnDay >= 0 && CraWarnDay <= day || CraSubsidyLow) && CraCrashDay < 0 && Cra >= 0.97;
public double CraRate => CraSubsidyLow ? Tuning.CraRateLow : Tuning.CraRate; public double CraRate => CraSubsidyLow ? Tuning.CraRateLow : Tuning.CraRate;
/// <summary> /// <summary>
/// 夜间结算。返回 CRC 持有量要乘的系数(减记兑现时为 0.95,否则为 1)。 /// 夜间结算。返回 CRC 持有量要乘的系数(减记兑现时为 0.95,否则为 1)。
/// playerStaked:玩家的 CRA 质押额,用来算补贴支出(玩家的利息由调用方按 <see cref="CraRate"/> 发放)。 /// playerStaked:玩家的 CRA 质押额,用来算利息带来的稀释(玩家的利息由调用方按 <see cref="CraRate"/> 发放)。
/// </summary> /// </summary>
public double Night(int day, Rng rng, double playerStaked) public double Night(int day, Rng rng, double playerStaked)
{ {
@@ -107,32 +163,87 @@ namespace Decentralized.Domain
if (RevHistory.Count > 7) RevHistory.RemoveAt(0); if (RevHistory.Count > 7) RevHistory.RemoveAt(0);
RevPower = Math.Max(0, Math.Min(100, RevPower + rng.Gauss() * 3)); RevPower = Math.Max(0, Math.Min(100, RevPower + rng.Gauss() * 3));
if (CraSpiralDay < 0) if (CraCrashDay < 0)
{ {
CraSubsidy -= (Tuning.CraNpcStake + playerStaked) * CraRate; double interest = (Tuning.CraNpcStake + playerStaked) * CraRate;
bool revFalling = RevHistory.Count == 7 && RevPower < RevHistory[0] - 5; Supply += interest;
double weekly = Tuning.CraSpiralWeekly * (revFalling ? 3 : 1) * StoryMods.Current.CraSpiral(day); // 抵押率调整:价格低于 1 上调,回到 1 下调;兑付的 CRC 份额不超过储备均值(见 <see cref="Redeem"/>)
double daily = 1 - Math.Pow(1 - weekly, 1.0 / 7); if (Cra < 0.995) C = Math.Min(1, C + Tuning.CraCrStep);
if (CraWarnDay < 0 && (rng.Chance(daily) || CraSubsidy <= 0)) else if (Cra >= 0.999) C = Math.Max(Tuning.CraCrMin, C - Tuning.CraCrStep);
if (CraEventDay < 0)
{ {
CraWarnDay = day; bool revFalling = RevHistory.Count == 7 && RevPower < RevHistory[0] - 5;
CraSpiralDay = day + rng.Range(Tuning.CraWarnLeadMin, Tuning.CraWarnLeadMax); double weekly = Tuning.CraSpiralWeekly * (revFalling ? 3 : 1) * StoryMods.Current.CraSpiral(day);
double daily = 1 - Math.Pow(1 - weekly, 1.0 / 7);
if (rng.Chance(daily) || Cushion <= 0)
{
CraWarnDay = day;
CraEventDay = day + rng.Range(Tuning.CraWarnLeadMin, Tuning.CraWarnLeadMax);
}
}
else if (day >= CraEventDay)
{
// 挪用:储备被革命军拿走一部分,R/S 掉到崩盘线以下就是挤兑
Reserve *= 1 - rng.Range(Tuning.CraEmbezzleMin, Tuning.CraEmbezzleMax);
CraEventDay = -1; CraWarnDay = -1;
if (Ratio < Tuning.CraCrashRatio) CraCrashDay = day;
} }
} }
if (CraSpiralDay > 0 && day >= CraSpiralDay) if (CraCrashDay >= 0)
{ {
int k = Math.Min(day - CraSpiralDay, Tuning.CraSpiralPath.Length - 1); int k = Math.Min(day - CraCrashDay, Tuning.CraSpiralPath.Length - 1);
Cra = Tuning.CraSpiralPath[k]; Cra = Tuning.CraSpiralPath[k];
if (SparkPre < 0) SparkPre = Spark; if (SparkPre < 0) SparkPre = Spark;
Spark = SparkPre * Tuning.SparkSpiralPath[Math.Min(day - CraSpiralDay, Tuning.SparkSpiralPath.Length - 1)]; Spark = SparkPre * Tuning.SparkSpiralPath[Math.Min(day - CraCrashDay, Tuning.SparkSpiralPath.Length - 1)];
} }
else else
{ {
Cra = PriceOfRatio(Ratio);
Spark *= Math.Exp(rng.Gauss() * Tuning.SparkVol) * StoryMods.Current.TakeSparkPush(); Spark *= Math.Exp(rng.Gauss() * Tuning.SparkVol) * StoryMods.Current.TakeSparkPush();
Spark += (Tuning.SparkStart - Spark) * Tuning.SparkRevert; Spark += (Tuning.SparkStart - Spark) * Tuning.SparkRevert;
Spark = Math.Max(Tuning.SparkStart * Tuning.SparkMinMult, Math.Min(Tuning.SparkStart * Tuning.SparkMaxMult, Spark)); Spark = Math.Max(Tuning.SparkStart * Tuning.SparkMinMult, Math.Min(Tuning.SparkStart * Tuning.SparkMaxMult, Spark));
} }
return crcFactor; return crcFactor;
} }
/// <summary>
/// 销毁一份 CRA 的兑付:CRC 份额 = min(申请时的 c, 储备均值 R/S),其余按现价用新增发的 SPARK 补。
/// 返回 (CRC 数量, SPARK 数量),并扣减储备和流通量。
/// </summary>
public void Redeem(double cra, double c, out double crc, out double spark)
{
double share = Math.Min(c, Ratio);
crc = Math.Min(Reserve, cra * share);
spark = Spark > 0 ? cra * (1 - crc / Math.Max(1e-9, cra)) / Spark : 0;
Reserve -= crc; Supply = Math.Max(0, Supply - cra);
}
/// <summary>
/// 夜间处理排队单:先对每一笔掷官方跑路(整笔丢失),再结算到期的。
/// 铸造到期:CRC 进储备、SPARK 销毁、流通量增加;销毁到期:按 <see cref="Redeem"/> 兑付。
/// </summary>
public List<CraOrderEvent> NightOrders(int day, Rng rng)
{
var evs = new List<CraOrderEvent>();
foreach (var o in Orders.ToList())
{
if (rng.Chance(RugChance)) { Orders.Remove(o); evs.Add(new CraOrderEvent { Order = o, Kind = CraOrderKind.Lost }); continue; }
if (day < o.Due) continue;
Orders.Remove(o);
var ev = new CraOrderEvent { Order = o };
if (o.Mint)
{
Supply += o.Cra; Reserve += o.Crc;
ev.Kind = CraOrderKind.Minted; ev.Cra = o.Cra;
}
else
{
Redeem(o.Cra, o.C, out ev.Crc, out ev.Spark);
ev.Kind = CraOrderKind.Burned;
}
evs.Add(ev);
}
return evs;
}
} }
} }
+9 -2
View File
@@ -51,8 +51,15 @@ namespace Decentralized.Domain
public const double CrtSwapFee = 0.02; public const double CrtSwapFee = 0.02;
public const double CraRate = 0.005, CraRateLow = 0.002; public const double CraRate = 0.005, CraRateLow = 0.002;
public const int CraUnlockDays = 4; public const int CraUnlockDays = 4;
public const double CraSubsidy0 = 30000, CraSubsidyWarn = 0.2, CraNpcStake = 20000; public const double CraSubsidyWarn = 0.2, CraNpcStake = 20000;
public const double CraSpiralWeekly = 0.02; /// <summary>CRA 部分抵押:初始流通量与抵押率、抵押率下限与每晚调整步长;R/S 安全线、崩盘线、安全线到崩盘线之间的最大折价;
/// 挪用储备的比例范围;劫掠上层补回的储备(占流通量);一级市场铸造等待天数;官方跑路系数(× (1 − CRA 价格))。数值由 research/crasim 定。</summary>
public const double CraS0 = 60000, CraC0 = 0.8, CraCrMin = 0.5, CraCrStep = 0.02;
public const double CraSafeRatio = 0.6, CraCrashRatio = 0.35, CraDiscountMax = 0.15;
public const double CraEmbezzleMin = 0.4, CraEmbezzleMax = 0.8, CraLoot = 0.09;
public const int CraMintDaysMin = 1, CraMintDaysMax = 2;
public const double CraRugPerDepeg = 1;
public const double CraSpiralWeekly = 0.03;
public const int CraWarnLeadMin = 4, CraWarnLeadMax = 7; public const int CraWarnLeadMin = 4, CraWarnLeadMax = 7;
public static readonly double[] CraSpiralPath = { 0.85, 0.30, 0.02 }; public static readonly double[] CraSpiralPath = { 0.85, 0.30, 0.02 };
/// <summary>平衡代币 SPARK:起始价与长期锚(信用点)、日波动率、每晚向锚回归的比例、价格上下限(锚的倍数);铸销手续费; /// <summary>平衡代币 SPARK:起始价与长期锚(信用点)、日波动率、每晚向锚回归的比例、价格上下限(锚的倍数);铸销手续费;
+13 -1
View File
@@ -172,11 +172,23 @@ namespace Decentralized.Domain
["CoinPayCrt"] = Tuning.CoinPayCrt, ["CoinPayCrt"] = Tuning.CoinPayCrt,
["CoinPayPremium"] = Tuning.CoinPayPremium, ["CoinPayPremium"] = Tuning.CoinPayPremium,
["CoinPayPsc"] = Tuning.CoinPayPsc, ["CoinPayPsc"] = Tuning.CoinPayPsc,
["CraC0"] = Tuning.CraC0,
["CraCrMin"] = Tuning.CraCrMin,
["CraCrStep"] = Tuning.CraCrStep,
["CraCrashRatio"] = Tuning.CraCrashRatio,
["CraDiscountMax"] = Tuning.CraDiscountMax,
["CraEmbezzleMax"] = Tuning.CraEmbezzleMax,
["CraEmbezzleMin"] = Tuning.CraEmbezzleMin,
["CraLoot"] = Tuning.CraLoot,
["CraMintDaysMax"] = Tuning.CraMintDaysMax,
["CraMintDaysMin"] = Tuning.CraMintDaysMin,
["CraNpcStake"] = Tuning.CraNpcStake, ["CraNpcStake"] = Tuning.CraNpcStake,
["CraRate"] = Tuning.CraRate, ["CraRate"] = Tuning.CraRate,
["CraRateLow"] = Tuning.CraRateLow, ["CraRateLow"] = Tuning.CraRateLow,
["CraRugPerDepeg"] = Tuning.CraRugPerDepeg,
["CraS0"] = Tuning.CraS0,
["CraSafeRatio"] = Tuning.CraSafeRatio,
["CraSpiralWeekly"] = Tuning.CraSpiralWeekly, ["CraSpiralWeekly"] = Tuning.CraSpiralWeekly,
["CraSubsidy0"] = Tuning.CraSubsidy0,
["CraSubsidyWarn"] = Tuning.CraSubsidyWarn, ["CraSubsidyWarn"] = Tuning.CraSubsidyWarn,
["CraUnlockDays"] = Tuning.CraUnlockDays, ["CraUnlockDays"] = Tuning.CraUnlockDays,
["CraWarnLeadMax"] = Tuning.CraWarnLeadMax, ["CraWarnLeadMax"] = Tuning.CraWarnLeadMax,
+4 -4
View File
@@ -89,8 +89,8 @@ namespace Decentralized
var d = Session.Data; int day = StoreStation.GetDayCounter(); var bk = d.Predict; var d = Session.Data; int day = StoreStation.GetDayCounter(); var bk = d.Predict;
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Era, "era", L.T("predict.era"), 0, day, day + 1, day + 3, PredictMath.EraProb(day, day + 1, day + 3, -1) + 0.05)); bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Era, "era", L.T("predict.era"), 0, day, day + 1, day + 3, PredictMath.EraProb(day, day + 1, day + 3, -1) + 0.05));
double h = 1 - System.Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7); double h = 1 - System.Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Cra, "cra", "CRA", 0, day, day + 1, day + 3, PredictMath.CraWarnProb(d.Stable.CraSubsidy, (Tuning.CraNpcStake + d.Staking.Earning) * d.Stable.CraRate, day, day + 1, day + 3, h))); bk.Markets.Add(PredictMarket.Create(++bk.Seq, PredictKind.Cra, "cra", "CRA", 0, day, day + 1, day + 3, PredictMath.CraWarnProb(d.Stable.Cushion, Stablecoins.CushionDrain(Tuning.CraNpcStake + d.Staking.Earning, d.Stable.CraRate), day, day + 1, day + 3, h)));
Log.Info($"测试:矿机时代 {d.Network.EraDay},CRA 补贴池 {d.Stable.CraSubsidy:0}"); Log.Info($"测试:矿机时代 {d.Network.EraDay},CRA 储备 {d.Stable.Reserve:0}(R/S {d.Stable.Ratio:0.00})");
}); });
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Informant: queue power shortage in 3 days (test)", () => Log.Guard("线人测试", () => ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Informant: queue power shortage in 3 days (test)", () => Log.Guard("线人测试", () =>
{ {
@@ -186,8 +186,8 @@ namespace Decentralized
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "CRA spiral warning (test)", () => ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "CRA spiral warning (test)", () =>
{ {
var st = Session.Data.Stable; int day = StoreStation.GetDayCounter(); var st = Session.Data.Stable; int day = StoreStation.GetDayCounter();
st.CraWarnDay = day; st.CraSpiralDay = day + 3; st.CraWarnDay = day; st.CraEventDay = day + 3;
Log.Info($"测试:CRA 预兆今天,螺旋第 {st.CraSpiralDay} 天"); Log.Info($"测试:CRA 预兆今天,挪用日第 {st.CraEventDay} 天");
}); });
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give terminal (test)", () => { Items.Give(ModHelper.SpawnItem(Items.Terminal)); }); ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Give terminal (test)", () => { Items.Give(ModHelper.SpawnItem(Items.Terminal)); });
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Hardware wallets (test)", () => { Items.Give(Items.NewHwWallet(false)); Items.Give(Items.NewHwWallet(true)); Log.Info("测试:给了一个正品、一个被投毒的硬件钱包"); }); ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Hardware wallets (test)", () => { Items.Give(Items.NewHwWallet(false)); Items.Give(Items.NewHwWallet(true)); Log.Info("测试:给了一个正品、一个被投毒的硬件钱包"); });
+18 -5
View File
@@ -460,9 +460,6 @@ stake.ops,{0}
stake.avail,CRA {0} Gestakt {1} stake.avail,CRA {0} Gestakt {1}
stake.do,Staken stake.do,Staken
stake.undo,Auszahlung beantragen stake.undo,Auszahlung beantragen
spark.h,Ausgleichstoken
spark.mint,SPARK prägen
spark.burn,SPARK verbrennen
stake.sum.in,{0} CRA staken stake.sum.in,{0} CRA staken
stake.sum.out,Auszahlung von {0} CRA beantragen (Gutschrift in {1} Tagen) stake.sum.out,Auszahlung von {0} CRA beantragen (Gutschrift in {1} Tagen)
stake.done.in,{0} CRA gestakt. stake.done.in,{0} CRA gestakt.
@@ -470,9 +467,7 @@ stake.done.out,Auszahlung von {0} CRA beantragt; Rückkehr in die Wallet an Tag
nightlog.stakeint,Staking-Zinsen +{0} CRA. nightlog.stakeint,Staking-Zinsen +{0} CRA.
nightlog.unstaked,{0} CRA aus dem Staking wurden an {1} zurückgebucht. nightlog.unstaked,{0} CRA aus dem Staking wurden an {1} zurückgebucht.
news.crawarn.title,Unruhe im Revolution-Staking-Pool news.crawarn.title,Unruhe im Revolution-Staking-Pool
news.crawarn.desc,"Großanleger ziehen Kapital ab und der Staking-Subventionspool leert sich. Die Entsperrung dauert vier Tage; manche meinen, es sei Zeit zu handeln."
news.cralow.title,Revolution senkt Staking-Zinssatz news.cralow.title,Revolution senkt Staking-Zinssatz
news.cralow.desc,Der Subventionspool ist fast leer und die Revolution hat den CRA-Staking-Zins auf einen Bruchteil gekürzt.
stake.avail2,SPARK {0} stake.avail2,SPARK {0}
poin.sub.spot,Spot poin.sub.spot,Spot
poin.sub.perp,Perps poin.sub.perp,Perps
@@ -906,3 +901,21 @@ swap.get,Erhalten
swap.preview,"Ca. {0} {1} {2} Pool(s), Verlust {3} %" swap.preview,"Ca. {0} {1} {2} Pool(s), Verlust {3} %"
swap.go,Tauschen swap.go,Tauschen
swap.same,Zahlungs- und Empfangswährung müssen verschieden sein. swap.same,Zahlungs- und Empfangswährung müssen verschieden sein.
cra.mint,Prägen
cra.burn,Einlösen
mint.h,Offizielle Prägung (CRC + SPARK)
mint.need,Benötigt {0} CRC und {1} SPARK
mint.reserve,Reservedeckung {0} % Besicherung {1} %
mint.queue,Offene Aufträge
mint.order,"{0} {1} CRA, Tag {2}"
mint.sum.in,{0} CRA mit {1} CRC und {2} SPARK prägen ({3}–{4} Tage)
mint.sum.out,{0} CRA gegen CRC und SPARK einlösen ({1} Tage)
mint.done.in,Prägeauftrag erteilt; fällig an Tag {0}.
mint.done.out,Einlöseauftrag erteilt; fällig an Tag {0}.
stake.coin,Einzahlungswährung
stake.sum.via,{0} {1} tauschen → ca. {2} CRA und staken
nightlog.cra.minted,{0} CRA geprägt und gestakt ({1}).
nightlog.cra.burned,"{0} CRA eingelöst: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,Der Herausgeber hat nicht reagiert: Der Auftrag ({1}) über {0} CRA ist verloren.
news.crawarn.desc,"Jemand zählt die Reserve der Revolution nach; gestaktes CRA lässt sich womöglich nicht vollständig einlösen. Das Entsperren dauert vier Tage; manche sagen, es sei Zeit zu handeln."
news.cralow.desc,Die Reservedeckung wird knapp; die Revolution hat den CRA-Staking-Zins auf einen Bruchteil gesenkt.
1 # Probably Decentralized localization table: German (de)
460 stake.avail
461 stake.do
462 stake.undo
spark.h
spark.mint
spark.burn
463 stake.sum.in
464 stake.sum.out
465 stake.done.in
467 nightlog.stakeint
468 nightlog.unstaked
469 news.crawarn.title
news.crawarn.desc
470 news.cralow.title
news.cralow.desc
471 stake.avail2
472 poin.sub.spot
473 poin.sub.perp
901 swap.preview
902 swap.go
903 swap.same
904 cra.mint
905 cra.burn
906 mint.h
907 mint.need
908 mint.reserve
909 mint.queue
910 mint.order
911 mint.sum.in
912 mint.sum.out
913 mint.done.in
914 mint.done.out
915 stake.coin
916 stake.sum.via
917 nightlog.cra.minted
918 nightlog.cra.burned
919 nightlog.cra.lost
920 news.crawarn.desc
921 news.cralow.desc
+18 -5
View File
@@ -460,9 +460,6 @@ stake.ops,{0}
stake.avail,CRA {0} Staked {1} stake.avail,CRA {0} Staked {1}
stake.do,Stake stake.do,Stake
stake.undo,Request withdrawal stake.undo,Request withdrawal
spark.h,Balance token
spark.mint,Mint SPARK
spark.burn,Burn SPARK
stake.sum.in,Stake {0} CRA stake.sum.in,Stake {0} CRA
stake.sum.out,Request withdrawal of {0} CRA (arrives in {1} days) stake.sum.out,Request withdrawal of {0} CRA (arrives in {1} days)
stake.done.in,Staked {0} CRA. stake.done.in,Staked {0} CRA.
@@ -470,9 +467,7 @@ stake.done.out,Requested withdrawal of {0} CRA; back in the wallet on day {1}.
nightlog.stakeint,Staking interest +{0} CRA. nightlog.stakeint,Staking interest +{0} CRA.
nightlog.unstaked,{0} CRA withdrawn from staking returned to {1}. nightlog.unstaked,{0} CRA withdrawn from staking returned to {1}.
news.crawarn.title,Unrest at the Revolution staking pool news.crawarn.title,Unrest at the Revolution staking pool
news.crawarn.desc,Big holders are pulling out and the staking subsidy pool is running dry. Unlocking takes four days; some say it is time to move.
news.cralow.title,Revolution cuts staking rate news.cralow.title,Revolution cuts staking rate
news.cralow.desc,"The subsidy pool is nearly empty, and the Revolution has cut the CRA staking rate to a fraction."
stake.avail2,SPARK {0} stake.avail2,SPARK {0}
poin.sub.spot,Spot poin.sub.spot,Spot
poin.sub.perp,Perps poin.sub.perp,Perps
@@ -906,3 +901,21 @@ swap.get,Receive
swap.preview,"Receive about {0} {1} {2} pool(s), loss {3}%" swap.preview,"Receive about {0} {1} {2} pool(s), loss {3}%"
swap.go,Swap swap.go,Swap
swap.same,Pay and receive must be different coins. swap.same,Pay and receive must be different coins.
cra.mint,Mint
cra.burn,Redeem
mint.h,Official mint (CRC + SPARK)
mint.need,Needs {0} CRC and {1} SPARK
mint.reserve,Reserve ratio {0}% Collateral ratio {1}%
mint.queue,Pending orders
mint.order,"{0} {1} CRA, day {2}"
mint.sum.in,Mint {0} CRA with {1} CRC and {2} SPARK ({3}–{4} days)
mint.sum.out,Redeem {0} CRA for CRC and SPARK ({1} days)
mint.done.in,Mint order placed; due on day {0}.
mint.done.out,Redeem order placed; due on day {0}.
stake.coin,Deposit coin
stake.sum.via,"Swap {0} {1} → about {2} CRA, then stake"
nightlog.cra.minted,"Minted {0} CRA, now staked ({1})."
nightlog.cra.burned,"Redeemed {0} CRA: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,The issuer did not respond: the {1} order of {0} CRA is lost.
news.crawarn.desc,"Someone is counting the Revolution's reserve, and staked CRA may not be redeemable in full. Unlocking takes four days; some say it is time to move."
news.cralow.desc,"The reserve ratio is running low, and the Revolution has cut the CRA staking rate to a fraction."
1 # Probably Decentralized localization table: English (en)
460 stake.avail
461 stake.do
462 stake.undo
spark.h
spark.mint
spark.burn
463 stake.sum.in
464 stake.sum.out
465 stake.done.in
467 nightlog.stakeint
468 nightlog.unstaked
469 news.crawarn.title
news.crawarn.desc
470 news.cralow.title
news.cralow.desc
471 stake.avail2
472 poin.sub.spot
473 poin.sub.perp
901 swap.preview
902 swap.go
903 swap.same
904 cra.mint
905 cra.burn
906 mint.h
907 mint.need
908 mint.reserve
909 mint.queue
910 mint.order
911 mint.sum.in
912 mint.sum.out
913 mint.done.in
914 mint.done.out
915 stake.coin
916 stake.sum.via
917 nightlog.cra.minted
918 nightlog.cra.burned
919 nightlog.cra.lost
920 news.crawarn.desc
921 news.cralow.desc
+18 -5
View File
@@ -460,9 +460,6 @@ stake.ops,{0}
stake.avail,CRA {0} En staking {1} stake.avail,CRA {0} En staking {1}
stake.do,Hacer staking stake.do,Hacer staking
stake.undo,Solicitar retiro stake.undo,Solicitar retiro
spark.h,Token de balance
spark.mint,Acuñar SPARK
spark.burn,Quemar SPARK
stake.sum.in,Poner {0} CRA en staking stake.sum.in,Poner {0} CRA en staking
stake.sum.out,Solicitar retiro de {0} CRA (llega en {1} día(s)) stake.sum.out,Solicitar retiro de {0} CRA (llega en {1} día(s))
stake.done.in,{0} CRA puestos en staking. stake.done.in,{0} CRA puestos en staking.
@@ -470,9 +467,7 @@ stake.done.out,Retiro de {0} CRA solicitado; vuelve a la billetera el día {1}.
nightlog.stakeint,Interés de staking +{0} CRA. nightlog.stakeint,Interés de staking +{0} CRA.
nightlog.unstaked,Los {0} CRA retirados de staking volvieron a {1}. nightlog.unstaked,Los {0} CRA retirados de staking volvieron a {1}.
news.crawarn.title,Agitación en el fondo de staking de la Revolución news.crawarn.title,Agitación en el fondo de staking de la Revolución
news.crawarn.desc,Los grandes inversores están retirándose y el fondo de subsidio de staking se agota. El desbloqueo tarda cuatro días; algunos dicen que es hora de actuar.
news.cralow.title,La Revolución reduce la tasa de staking news.cralow.title,La Revolución reduce la tasa de staking
news.cralow.desc,"El fondo de subsidio está casi vacío, y la Revolución redujo la tasa de staking de CRA a una fracción."
stake.avail2,SPARK {0} stake.avail2,SPARK {0}
poin.sub.spot,Spot poin.sub.spot,Spot
poin.sub.perp,Perpetuos poin.sub.perp,Perpetuos
@@ -906,3 +901,21 @@ swap.get,Recibir
swap.preview,"Aprox. {0} {1} {2} pool(s), pérdida {3} %" swap.preview,"Aprox. {0} {1} {2} pool(s), pérdida {3} %"
swap.go,Canjear swap.go,Canjear
swap.same,Las monedas a pagar y recibir deben ser distintas. swap.same,Las monedas a pagar y recibir deben ser distintas.
cra.mint,Acuñar
cra.burn,Redimir
mint.h,Acuñación oficial (CRC + SPARK)
mint.need,Requiere {0} CRC y {1} SPARK
mint.reserve,Cobertura {0} % Colateral {1} %
mint.queue,Órdenes pendientes
mint.order,"{0} {1} CRA, día {2}"
mint.sum.in,Acuñar {0} CRA con {1} CRC y {2} SPARK ({3}–{4} días)
mint.sum.out,Redimir {0} CRA por CRC y SPARK ({1} días)
mint.done.in,Orden de acuñación enviada; vence el día {0}.
mint.done.out,Orden de redención enviada; vence el día {0}.
stake.coin,Moneda a depositar
stake.sum.via,Canjear {0} {1} → aprox. {2} CRA y apostar
nightlog.cra.minted,{0} CRA acuñados y apostados ({1}).
nightlog.cra.burned,"{0} CRA redimidos: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,El emisor no respondió: la orden ({1}) de {0} CRA se perdió.
news.crawarn.desc,Alguien está contando la reserva de la Revolución y quizá los CRA apostados no se puedan redimir por completo. Desbloquear tarda cuatro días; algunos dicen que es hora de actuar.
news.cralow.desc,La cobertura de la reserva se agota y la Revolución ha recortado el tipo de apuesta de CRA a una fracción.
1 # Probably Decentralized localization table: Spanish (es)
460 stake.avail
461 stake.do
462 stake.undo
spark.h
spark.mint
spark.burn
463 stake.sum.in
464 stake.sum.out
465 stake.done.in
467 nightlog.stakeint
468 nightlog.unstaked
469 news.crawarn.title
news.crawarn.desc
470 news.cralow.title
news.cralow.desc
471 stake.avail2
472 poin.sub.spot
473 poin.sub.perp
901 swap.preview
902 swap.go
903 swap.same
904 cra.mint
905 cra.burn
906 mint.h
907 mint.need
908 mint.reserve
909 mint.queue
910 mint.order
911 mint.sum.in
912 mint.sum.out
913 mint.done.in
914 mint.done.out
915 stake.coin
916 stake.sum.via
917 nightlog.cra.minted
918 nightlog.cra.burned
919 nightlog.cra.lost
920 news.crawarn.desc
921 news.cralow.desc
+18 -5
View File
@@ -460,9 +460,6 @@ stake.ops,{0}
stake.avail,CRA {0} Staké {1} stake.avail,CRA {0} Staké {1}
stake.do,Staker stake.do,Staker
stake.undo,Demander un retrait stake.undo,Demander un retrait
spark.h,Jeton d'équilibre
spark.mint,Frapper SPARK
spark.burn,Brûler SPARK
stake.sum.in,Staker {0} CRA stake.sum.in,Staker {0} CRA
stake.sum.out,Demander le retrait de {0} CRA (disponible dans {1} jours) stake.sum.out,Demander le retrait de {0} CRA (disponible dans {1} jours)
stake.done.in,{0} CRA stakés. stake.done.in,{0} CRA stakés.
@@ -470,9 +467,7 @@ stake.done.out,Retrait de {0} CRA demandé ; retour au portefeuille le jour {1}.
nightlog.stakeint,Intérêts de staking +{0} CRA. nightlog.stakeint,Intérêts de staking +{0} CRA.
nightlog.unstaked,Les {0} CRA retirés du staking sont revenus sur {1}. nightlog.unstaked,Les {0} CRA retirés du staking sont revenus sur {1}.
news.crawarn.title,Troubles au pool de staking de la Révolution news.crawarn.title,Troubles au pool de staking de la Révolution
news.crawarn.desc,Les gros détenteurs se retirent et le pool de subvention de staking s'épuise. Le déverrouillage prend quatre jours ; certains disent qu'il est temps d'agir.
news.cralow.title,La Révolution réduit le taux de staking news.cralow.title,La Révolution réduit le taux de staking
news.cralow.desc,"Le pool de subvention est presque vide, et la Révolution a réduit le taux de staking du CRA à une fraction de sa valeur."
stake.avail2,SPARK {0} stake.avail2,SPARK {0}
poin.sub.spot,Spot poin.sub.spot,Spot
poin.sub.perp,Perps poin.sub.perp,Perps
@@ -906,3 +901,21 @@ swap.get,Recevoir
swap.preview,"Environ {0} {1} {2} pool(s), perte {3} %" swap.preview,"Environ {0} {1} {2} pool(s), perte {3} %"
swap.go,Échanger swap.go,Échanger
swap.same,Les monnaies payée et reçue doivent différer. swap.same,Les monnaies payée et reçue doivent différer.
cra.mint,Frapper
cra.burn,Racheter
mint.h,Frappe officielle (CRC + SPARK)
mint.need,Nécessite {0} CRC et {1} SPARK
mint.reserve,Couverture {0} % Collatéral {1} %
mint.queue,Ordres en attente
mint.order,"{0} {1} CRA, jour {2}"
mint.sum.in,Frapper {0} CRA avec {1} CRC et {2} SPARK ({3}–{4} jours)
mint.sum.out,Racheter {0} CRA contre CRC et SPARK ({1} jours)
mint.done.in,Ordre de frappe passé ; échéance au jour {0}.
mint.done.out,Ordre de rachat passé ; échéance au jour {0}.
stake.coin,Monnaie déposée
stake.sum.via,Échanger {0} {1} → environ {2} CRA puis staker
nightlog.cra.minted,{0} CRA frappés et stakés ({1}).
nightlog.cra.burned,"{0} CRA rachetés : +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,L'émetteur n'a pas répondu : l'ordre ({1}) de {0} CRA est perdu.
news.crawarn.desc,Quelqu'un fait l'inventaire de la réserve de la Révolution ; les CRA stakés pourraient ne pas être remboursés en totalité. Le déblocage prend quatre jours ; certains disent qu'il est temps d'agir.
news.cralow.desc,La couverture de la réserve s'amenuise ; la Révolution a réduit le taux de staking du CRA à une fraction.
1 # Probably Decentralized localization table: French (fr)
460 stake.avail
461 stake.do
462 stake.undo
spark.h
spark.mint
spark.burn
463 stake.sum.in
464 stake.sum.out
465 stake.done.in
467 nightlog.stakeint
468 nightlog.unstaked
469 news.crawarn.title
news.crawarn.desc
470 news.cralow.title
news.cralow.desc
471 stake.avail2
472 poin.sub.spot
473 poin.sub.perp
901 swap.preview
902 swap.go
903 swap.same
904 cra.mint
905 cra.burn
906 mint.h
907 mint.need
908 mint.reserve
909 mint.queue
910 mint.order
911 mint.sum.in
912 mint.sum.out
913 mint.done.in
914 mint.done.out
915 stake.coin
916 stake.sum.via
917 nightlog.cra.minted
918 nightlog.cra.burned
919 nightlog.cra.lost
920 news.crawarn.desc
921 news.cralow.desc
+18 -5
View File
@@ -460,9 +460,6 @@ stake.ops,{0}
stake.avail,CRA {0} ステーキング中 {1} stake.avail,CRA {0} ステーキング中 {1}
stake.do,ステーキング stake.do,ステーキング
stake.undo,出金申請 stake.undo,出金申請
spark.h,バランストークン
spark.mint,SPARKをミント
spark.burn,SPARKをバーン
stake.sum.in,{0} CRA をステーキング stake.sum.in,{0} CRA をステーキング
stake.sum.out,{0} CRA の出金申請({1}日後に着金) stake.sum.out,{0} CRA の出金申請({1}日後に着金)
stake.done.in,{0} CRA をステーキングしました。 stake.done.in,{0} CRA をステーキングしました。
@@ -470,9 +467,7 @@ stake.done.out,{0} CRA の出金を申請しました。{1}日目にウォレッ
nightlog.stakeint,ステーキング利息 +{0} CRA。 nightlog.stakeint,ステーキング利息 +{0} CRA。
nightlog.unstaked,ステーキングから出金された {0} CRA が {1} に戻った。 nightlog.unstaked,ステーキングから出金された {0} CRA が {1} に戻った。
news.crawarn.title,革命家のステーキングプールに不穏な動き news.crawarn.title,革命家のステーキングプールに不穏な動き
news.crawarn.desc,大口保有者が相次いで資金を引き揚げており、補助金プールが枯渇寸前だ。ロック解除には4日かかるため、今すぐ動くべきだとの声も上がっている。
news.cralow.title,革命家がステーキングの日利を引き下げ news.cralow.title,革命家がステーキングの日利を引き下げ
news.cralow.desc,補助金プールがほぼ底をつき、革命家はCRAステーキングの日利を従来のごくわずかな水準まで引き下げた。
stake.avail2,SPARK {0} stake.avail2,SPARK {0}
poin.sub.spot,現物 poin.sub.spot,現物
poin.sub.perp,無期限先物 poin.sub.perp,無期限先物
@@ -906,3 +901,21 @@ swap.get,受取
swap.preview,約 {0} {1} プール {2} 個、損失 {3}% swap.preview,約 {0} {1} プール {2} 個、損失 {3}%
swap.go,スワップ swap.go,スワップ
swap.same,支払いと受取は別の通貨にしてください。 swap.same,支払いと受取は別の通貨にしてください。
cra.mint,発行
cra.burn,償還
mint.h,公式発行(CRC+SPARK)
mint.need,必要:{0} CRC と {1} SPARK
mint.reserve,準備率 {0}% 担保率 {1}%
mint.queue,処理待ち
mint.order,{0} {1} CRA、{2} 日目
mint.sum.in,{1} CRC と {2} SPARK で {0} CRA を発行({3}~{4} 日)
mint.sum.out,{0} CRA を償還して CRC と SPARK に({1} 日)
mint.done.in,発行を申請しました。{0} 日目に決済されます。
mint.done.out,償還を申請しました。{0} 日目に決済されます。
stake.coin,預入通貨
stake.sum.via,{0} {1} をスワップ → 約 {2} CRA をステーク
nightlog.cra.minted,発行した {0} CRA をステークしました({1})。
nightlog.cra.burned,{0} CRA を償還:+{1} CRC、+{2} SPARK({3})。
nightlog.cra.lost,発行元から応答がありません:{0} CRA の{1}注文は失われました。
news.crawarn.desc,革命軍の準備金を数え直す者がいる。ステークした CRA は全額償還できないかもしれない。解除には四日かかる。動くなら今だという声もある。
news.cralow.desc,準備率が危うくなり、革命軍は CRA のステーキング日利を元の数分の一に引き下げた。
Can't render this file because it contains an unexpected character in line 511 and column 24.
+18 -5
View File
@@ -460,9 +460,6 @@ stake.ops,{0}
stake.avail,CRA {0} W stakingu {1} stake.avail,CRA {0} W stakingu {1}
stake.do,Stakuj stake.do,Stakuj
stake.undo,Zgłoś wypłatę stake.undo,Zgłoś wypłatę
spark.h,Token równoważący
spark.mint,Wybij SPARK
spark.burn,Spal SPARK
stake.sum.in,Zastakuj {0} CRA stake.sum.in,Zastakuj {0} CRA
stake.sum.out,Zgłoś wypłatę {0} CRA (dostępne za: {1} d.) stake.sum.out,Zgłoś wypłatę {0} CRA (dostępne za: {1} d.)
stake.done.in,Zastakowano {0} CRA. stake.done.in,Zastakowano {0} CRA.
@@ -470,9 +467,7 @@ stake.done.out,Zgłoszono wypłatę {0} CRA; powrót do portfela w dniu {1}.
nightlog.stakeint,Odsetki ze stakingu +{0} CRA. nightlog.stakeint,Odsetki ze stakingu +{0} CRA.
nightlog.unstaked,{0} CRA wycofane ze stakingu zwrócono do {1}. nightlog.unstaked,{0} CRA wycofane ze stakingu zwrócono do {1}.
news.crawarn.title,Niepokoje wokół puli stakingowej Rewolucji news.crawarn.title,Niepokoje wokół puli stakingowej Rewolucji
news.crawarn.desc,"Duzi posiadacze wycofują środki, a pula dotacji stakingowych wysycha. Odblokowanie trwa cztery dni; niektórzy mówią, że czas działać."
news.cralow.title,Rewolucja obniża stawkę stakingu news.cralow.title,Rewolucja obniża stawkę stakingu
news.cralow.desc,"Pula dotacji jest niemal pusta, a Rewolucja obniżyła stawkę stakingu CRA do ułamka pierwotnej wartości."
stake.avail2,SPARK {0} stake.avail2,SPARK {0}
poin.sub.spot,Spot poin.sub.spot,Spot
poin.sub.perp,Wieczyste poin.sub.perp,Wieczyste
@@ -906,3 +901,21 @@ swap.get,Otrzymuję
swap.preview,"Około {0} {1} pule: {2}, strata {3}%" swap.preview,"Około {0} {1} pule: {2}, strata {3}%"
swap.go,Wymień swap.go,Wymień
swap.same,Waluty płatności i odbioru muszą się różnić. swap.same,Waluty płatności i odbioru muszą się różnić.
cra.mint,Wybij
cra.burn,Umorz
mint.h,Oficjalna emisja (CRC + SPARK)
mint.need,Wymaga {0} CRC i {1} SPARK
mint.reserve,Pokrycie rezerwy {0}% Zabezpieczenie {1}%
mint.queue,Oczekujące zlecenia
mint.order,"{0} {1} CRA, dzień {2}"
mint.sum.in,Wybij {0} CRA za {1} CRC i {2} SPARK ({3}–{4} dni)
mint.sum.out,Umorz {0} CRA na CRC i SPARK ({1} dni)
mint.done.in,Zlecenie emisji złożone; termin: dzień {0}.
mint.done.out,Zlecenie umorzenia złożone; termin: dzień {0}.
stake.coin,Waluta wpłaty
stake.sum.via,Wymień {0} {1} → około {2} CRA i stakuj
nightlog.cra.minted,Wybito {0} CRA i zastakowano ({1}).
nightlog.cra.burned,"Umorzono {0} CRA: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,Emitent nie odpowiedział: zlecenie ({1}) na {0} CRA przepadło.
news.crawarn.desc,"Ktoś liczy rezerwę Rewolucji i zastakowane CRA mogą nie zostać w pełni wypłacone. Odblokowanie trwa cztery dni; niektórzy mówią, że czas działać."
news.cralow.desc,"Pokrycie rezerwy maleje, a Rewolucja obniżyła stopę stakingu CRA do ułamka."
1 # Probably Decentralized localization table: Polish (pl)
460 stake.avail
461 stake.do
462 stake.undo
spark.h
spark.mint
spark.burn
463 stake.sum.in
464 stake.sum.out
465 stake.done.in
467 nightlog.stakeint
468 nightlog.unstaked
469 news.crawarn.title
news.crawarn.desc
470 news.cralow.title
news.cralow.desc
471 stake.avail2
472 poin.sub.spot
473 poin.sub.perp
901 swap.preview
902 swap.go
903 swap.same
904 cra.mint
905 cra.burn
906 mint.h
907 mint.need
908 mint.reserve
909 mint.queue
910 mint.order
911 mint.sum.in
912 mint.sum.out
913 mint.done.in
914 mint.done.out
915 stake.coin
916 stake.sum.via
917 nightlog.cra.minted
918 nightlog.cra.burned
919 nightlog.cra.lost
920 news.crawarn.desc
921 news.cralow.desc
+18 -5
View File
@@ -460,9 +460,6 @@ stake.ops,{0}
stake.avail,CRA {0} В стейкинге {1} stake.avail,CRA {0} В стейкинге {1}
stake.do,В стейкинг stake.do,В стейкинг
stake.undo,Запросить вывод stake.undo,Запросить вывод
spark.h,Балансовый токен
spark.mint,Минт SPARK
spark.burn,Сжигание SPARK
stake.sum.in,Внести {0} CRA в стейкинг stake.sum.in,Внести {0} CRA в стейкинг
stake.sum.out,Запросить вывод {0} CRA (дней до зачисления: {1}) stake.sum.out,Запросить вывод {0} CRA (дней до зачисления: {1})
stake.done.in,{0} CRA внесено в стейкинг. stake.done.in,{0} CRA внесено в стейкинг.
@@ -470,9 +467,7 @@ stake.done.out,Запрошен вывод {0} CRA; возврат в кошел
nightlog.stakeint,Доход от стейкинга: +{0} CRA. nightlog.stakeint,Доход от стейкинга: +{0} CRA.
nightlog.unstaked,Выведенные из стейкинга {0} CRA вернулись в {1}. nightlog.unstaked,Выведенные из стейкинга {0} CRA вернулись в {1}.
news.crawarn.title,Волнения вокруг пула стейкинга Революционеров news.crawarn.title,Волнения вокруг пула стейкинга Революционеров
news.crawarn.desc,"Крупные держатели выводят средства, и пул субсидий для стейкинга истощается. Разблокировка занимает четыре дня; ходят слухи, что пора действовать."
news.cralow.title,Революционеры снижают ставку стейкинга news.cralow.title,Революционеры снижают ставку стейкинга
news.cralow.desc,"Пул субсидий почти опустел, и Революционеры снизили ставку стейкинга CRA до малой доли прежней."
stake.avail2,SPARK {0} stake.avail2,SPARK {0}
poin.sub.spot,Спот poin.sub.spot,Спот
poin.sub.perp,Бессрочные poin.sub.perp,Бессрочные
@@ -906,3 +901,21 @@ swap.get,Получаю
swap.preview,"Около {0} {1} пулов: {2}, потери {3}%" swap.preview,"Около {0} {1} пулов: {2}, потери {3}%"
swap.go,Обменять swap.go,Обменять
swap.same,Монеты оплаты и получения должны различаться. swap.same,Монеты оплаты и получения должны различаться.
cra.mint,Выпустить
cra.burn,Погасить
mint.h,Официальный выпуск (CRC + SPARK)
mint.need,Нужно {0} CRC и {1} SPARK
mint.reserve,Покрытие резерва {0}% Залог {1}%
mint.queue,Очередь
mint.order,"{0} {1} CRA, день {2}"
mint.sum.in,Выпустить {0} CRA за {1} CRC и {2} SPARK ({3}–{4} дн.)
mint.sum.out,Погасить {0} CRA в CRC и SPARK ({1} дн.)
mint.done.in,Заявка на выпуск подана; срок — день {0}.
mint.done.out,Заявка на погашение подана; срок — день {0}.
stake.coin,Монета для вклада
stake.sum.via,Обменять {0} {1} → около {2} CRA и внести в стейкинг
nightlog.cra.minted,"Выпущено {0} CRA, внесены в стейкинг ({1})."
nightlog.cra.burned,"Погашено {0} CRA: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,Эмитент не ответил: заявка ({1}) на {0} CRA потеряна.
news.crawarn.desc,"Кто-то пересчитывает резерв Революции, и CRA в стейкинге могут не выкупить полностью. Разблокировка занимает четыре дня; кое-кто говорит, что пора действовать."
news.cralow.desc,"Покрытие резерва тает, и Революция снизила ставку по стейкингу CRA до малой доли."
1 # Probably Decentralized localization table: Russian (ru)
460 stake.avail
461 stake.do
462 stake.undo
spark.h
spark.mint
spark.burn
463 stake.sum.in
464 stake.sum.out
465 stake.done.in
467 nightlog.stakeint
468 nightlog.unstaked
469 news.crawarn.title
news.crawarn.desc
470 news.cralow.title
news.cralow.desc
471 stake.avail2
472 poin.sub.spot
473 poin.sub.perp
901 swap.preview
902 swap.go
903 swap.same
904 cra.mint
905 cra.burn
906 mint.h
907 mint.need
908 mint.reserve
909 mint.queue
910 mint.order
911 mint.sum.in
912 mint.sum.out
913 mint.done.in
914 mint.done.out
915 stake.coin
916 stake.sum.via
917 nightlog.cra.minted
918 nightlog.cra.burned
919 nightlog.cra.lost
920 news.crawarn.desc
921 news.cralow.desc
+18 -5
View File
@@ -459,9 +459,6 @@ stake.ops,"{0}"
stake.avail,"CRA {0} 已质押 {1}" stake.avail,"CRA {0} 已质押 {1}"
stake.do,质押 stake.do,质押
stake.undo,申请取出 stake.undo,申请取出
spark.h,平衡代币
spark.mint,铸造 SPARK
spark.burn,销毁 SPARK
stake.sum.in,"质押 {0} CRA" stake.sum.in,"质押 {0} CRA"
stake.sum.out,"申请取出 {0} CRA({1} 天后到账)" stake.sum.out,"申请取出 {0} CRA({1} 天后到账)"
stake.done.in,"已质押 {0} CRA。" stake.done.in,"已质押 {0} CRA。"
@@ -469,9 +466,7 @@ stake.done.out,"已申请取出 {0} CRA,第 {1} 天回到钱包。"
nightlog.stakeint,"质押利息 +{0} CRA。" nightlog.stakeint,"质押利息 +{0} CRA。"
nightlog.unstaked,"质押取出的 {0} CRA 回到了{1}。" nightlog.unstaked,"质押取出的 {0} CRA 回到了{1}。"
news.crawarn.title,革命军质押池传出异动 news.crawarn.title,革命军质押池传出异动
news.crawarn.desc,有大户在大量撤出,质押补贴池告急。解锁需要四天,有人说该动手了。
news.cralow.title,革命军下调质押日息 news.cralow.title,革命军下调质押日息
news.cralow.desc,补贴池余额见底,革命军把 CRA 质押日息降到了原来的零头。
stake.avail2,"SPARK {0}" stake.avail2,"SPARK {0}"
poin.sub.spot,现货 poin.sub.spot,现货
poin.sub.perp,永续 poin.sub.perp,永续
@@ -905,3 +900,21 @@ swap.get,获得
swap.preview,约得 {0} {1} 经 {2} 个池,损耗 {3}% swap.preview,约得 {0} {1} 经 {2} 个池,损耗 {3}%
swap.go,兑换 swap.go,兑换
swap.same,支付和获得的币种不能相同。 swap.same,支付和获得的币种不能相同。
cra.mint,铸造
cra.burn,销毁
mint.h,官方铸造(CRC 加 SPARK)
mint.need,需要 {0} CRC 和 {1} SPARK
mint.reserve,储备覆盖率 {0}% 抵押率 {1}%
mint.queue,待处理
mint.order,{0} {1} CRA,第 {2} 天
mint.sum.in,用 {1} CRC 和 {2} SPARK 铸造 {0} CRA({3}~{4} 天)
mint.sum.out,销毁 {0} CRA 换回 CRC 和 SPARK({1} 天)
mint.done.in,已提交铸造,第 {0} 天结算。
mint.done.out,已提交销毁,第 {0} 天结算。
stake.coin,存入币种
stake.sum.via,兑换 {0} {1} → 约 {2} CRA 并质押
nightlog.cra.minted,铸造的 {0} CRA 已进入质押({1})。
nightlog.cra.burned,销毁 {0} CRA:收回 {1} CRC、{2} SPARK({3})。
nightlog.cra.lost,官方没有回应:{0} CRA 的{1}单丢失。
news.crawarn.desc,有人在清点革命军的储备,质押的 CRA 恐怕兑付不了。解锁需要四天,有人说该动手了。
news.cralow.desc,储备覆盖率告急,革命军把 CRA 质押日息降到了原来的零头。
1 # Probably Decentralized 本地化表:简体中文(zh)
459 stake.avail
460 stake.do
461 stake.undo
spark.h
spark.mint
spark.burn
462 stake.sum.in
463 stake.sum.out
464 stake.done.in
466 nightlog.stakeint
467 nightlog.unstaked
468 news.crawarn.title
news.crawarn.desc
469 news.cralow.title
news.cralow.desc
470 stake.avail2
471 poin.sub.spot
472 poin.sub.perp
900 swap.preview
901 swap.go
902 swap.same
903 cra.mint
904 cra.burn
905 mint.h
906 mint.need
907 mint.reserve
908 mint.queue
909 mint.order
910 mint.sum.in
911 mint.sum.out
912 mint.done.in
913 mint.done.out
914 stake.coin
915 stake.sum.via
916 nightlog.cra.minted
917 nightlog.cra.burned
918 nightlog.cra.lost
919 news.crawarn.desc
920 news.cralow.desc
+15
View File
@@ -228,6 +228,13 @@ namespace Decentralized
if (perpEvents.Any(e => e.Kind == "seize")) SeizeForDebt(d, day); if (perpEvents.Any(e => e.Kind == "seize")) SeizeForDebt(d, day);
var stakeEvents = d.Staking.Night(day, d.Stable.CraRate, d.WalletAt); var stakeEvents = d.Staking.Night(day, d.Stable.CraRate, d.WalletAt);
double crcFactor = d.Stable.Night(day, d.Rng, d.Staking.Earning); double crcFactor = d.Stable.Night(day, d.Rng, d.Staking.Earning);
var orderEvents = d.Stable.NightOrders(day, d.Rng);
foreach (var oe in orderEvents)
{
var ow = d.WalletAt(oe.Order.Wallet);
if (oe.Kind == CraOrderKind.Minted) { ow.Add(Assets.CRA, oe.Cra); d.Staking.Stake(ow, oe.Cra, Session.Price); }
else if (oe.Kind == CraOrderKind.Burned) { ow.Add(Assets.CRC, oe.Crc); ow.Add(Assets.SPARK, oe.Spark); }
}
if (d.Stable.CraWarnDay == day) News.Show("pd_news_crawarn_" + day, L.T("news.crawarn.title"), L.T("news.crawarn.desc"), 4); if (d.Stable.CraWarnDay == day) News.Show("pd_news_crawarn_" + day, L.T("news.crawarn.title"), L.T("news.crawarn.desc"), 4);
if (d.Stable.CraSubsidyLow && !d.CraLowNews) { d.CraLowNews = true; News.Show("pd_news_cralow_" + day, L.T("news.cralow.title"), L.T("news.cralow.desc"), 3); } if (d.Stable.CraSubsidyLow && !d.CraLowNews) { d.CraLowNews = true; News.Show("pd_news_cralow_" + day, L.T("news.cralow.title"), L.T("news.cralow.desc"), 3); }
if (crcFactor < 1) if (crcFactor < 1)
@@ -326,6 +333,14 @@ namespace Decentralized
var sw = d.Own(e.Wallet); var sw = d.Own(e.Wallet);
if (e.Released > 0) ps.AddNightLog(L.T("nightlog.unstaked", Fmt.Num(e.Released), sw != null ? WalletWindow.NameOf(sw) : e.Wallet)); if (e.Released > 0) ps.AddNightLog(L.T("nightlog.unstaked", Fmt.Num(e.Released), sw != null ? WalletWindow.NameOf(sw) : e.Wallet));
} }
foreach (var oe in orderEvents)
{
var ow = d.Own(oe.Order.Wallet);
string wn = ow != null ? WalletWindow.NameOf(ow) : oe.Order.Wallet;
if (oe.Kind == CraOrderKind.Minted) ps.AddNightLog(L.T("nightlog.cra.minted", Fmt.Num(oe.Cra), wn));
else if (oe.Kind == CraOrderKind.Burned) ps.AddNightLog(L.T("nightlog.cra.burned", Fmt.Num(oe.Order.Cra), Fmt.Num(oe.Crc), Fmt.Num(oe.Spark), wn));
else ps.AddNightLog(L.T("nightlog.cra.lost", Fmt.Num(oe.Order.Cra), oe.Order.Mint ? L.T("cra.mint") : L.T("cra.burn")), "cc7755");
}
double interest = stakeEvents.Sum(e => e.Interest); double interest = stakeEvents.Sum(e => e.Interest);
if (interest > 0) ps.AddNightLog(L.T("nightlog.stakeint", Fmt.Num(interest))); if (interest > 0) ps.AddNightLog(L.T("nightlog.stakeint", Fmt.Num(interest)));
foreach (var name in report.Burnt) ps.AddNightLog(L.T("nightlog.burnt", name), "cc7755"); foreach (var name in report.Burnt) ps.AddNightLog(L.T("nightlog.burnt", name), "cc7755");
+6 -6
View File
@@ -120,8 +120,8 @@ namespace Decentralized
double thr = t; double thr = t;
list.Add(new PredictCandidate { Kind = PredictKind.Gas, Key = "gas", Title = "Gas", Param = thr, Tomorrow = true, Prob = (a, b) => GasPublic(d, day + 1, thr) }); list.Add(new PredictCandidate { Kind = PredictKind.Gas, Key = "gas", Title = "Gas", Param = thr, Tomorrow = true, Prob = (a, b) => GasPublic(d, day + 1, thr) });
} }
if (d.Stable.CraWarnDay < 0 && d.Stable.CraSpiralDay < 0) if (d.Stable.CraWarnDay < 0 && d.Stable.CraCrashDay < 0)
list.Add(new PredictCandidate { Kind = PredictKind.Cra, Key = "cra", Title = "CRA", Prob = (from, to) => PredictMath.CraWarnProb(d.Stable.CraSubsidy, CraDrain(d), day, from, to, CraHazard) }); list.Add(new PredictCandidate { Kind = PredictKind.Cra, Key = "cra", Title = "CRA", Prob = (from, to) => PredictMath.CraWarnProb(d.Stable.Cushion, CraDrain(d), day, from, to, CraHazard) });
if (!d.Network.EraDone && d.Network.EraDay > 0 && day + 4 >= (d.Network.EraWarned ? d.Network.EraWarnDay : Tuning.EraMin)) if (!d.Network.EraDone && d.Network.EraDay > 0 && day + 4 >= (d.Network.EraWarned ? d.Network.EraWarnDay : Tuning.EraMin))
list.Add(new PredictCandidate { Kind = PredictKind.Era, Key = "era", Title = L.T("predict.era"), Prob = (from, to) => PredictMath.EraProb(day, from, to, d.Network.EraWarned ? d.Network.EraWarnDay : -1) }); list.Add(new PredictCandidate { Kind = PredictKind.Era, Key = "era", Title = L.T("predict.era"), Prob = (from, to) => PredictMath.EraProb(day, from, to, d.Network.EraWarned ? d.Network.EraWarnDay : -1) });
return list; return list;
@@ -132,7 +132,7 @@ namespace Decentralized
d.GasPhase < 0 ? PredictMath.GasFlat(day, thr) : (1 - Tuning.PredictGasBlind) * PredictMath.GasAtLeast(day, d.GasPhase, thr) + Tuning.PredictGasBlind * PredictMath.GasFlat(day, thr); d.GasPhase < 0 ? PredictMath.GasFlat(day, thr) : (1 - Tuning.PredictGasBlind) * PredictMath.GasAtLeast(day, d.GasPhase, thr) + Tuning.PredictGasBlind * PredictMath.GasFlat(day, thr);
private static double CraHazard => 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7); private static double CraHazard => 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
private static double CraDrain(SaveData d) => (Tuning.CraNpcStake + d.Staking.Earning) * d.Stable.CraRate; private static double CraDrain(SaveData d) => Stablecoins.CushionDrain(Tuning.CraNpcStake + d.Staking.Earning, d.Stable.CraRate);
/// <summary>开门后补盘。价格盘一次只留一个(阈值不同的盘口会互相对冲)。</summary> /// <summary>开门后补盘。价格盘一次只留一个(阈值不同的盘口会互相对冲)。</summary>
public static void Morning(SaveData d, int day) public static void Morning(SaveData d, int day)
@@ -199,8 +199,8 @@ namespace Decentralized
case PredictKind.Gas: case PredictKind.Gas:
return d.GasPhase < 0 ? (double?)null : GasPublic(d, m.ToDay, m.Param); return d.GasPhase < 0 ? (double?)null : GasPublic(d, m.ToDay, m.Param);
case PredictKind.Cra: case PredictKind.Cra:
if (d.Stable.CraWarnDay >= 0 || d.Stable.CraSpiralDay >= 0) return 0.02; if (d.Stable.CraWarnDay >= 0 || d.Stable.CraCrashDay >= 0) return 0.02;
return PredictMath.CraWarnProb(d.Stable.CraSubsidy, CraDrain(d), day + 1, m.FromDay, m.ToDay, CraHazard); return PredictMath.CraWarnProb(d.Stable.Cushion, CraDrain(d), day + 1, m.FromDay, m.ToDay, CraHazard);
case PredictKind.Era: case PredictKind.Era:
return PredictMath.EraProb(day, m.FromDay, m.ToDay, d.Network.EraWarned ? d.Network.EraWarnDay : -1); return PredictMath.EraProb(day, m.FromDay, m.ToDay, d.Network.EraWarned ? d.Network.EraWarnDay : -1);
} }
@@ -309,7 +309,7 @@ namespace Decentralized
if (d.GasHist.Count > 0) list.Add(L.T("predict.clue.gas", string.Join(" ", d.GasHist.Skip(Math.Max(0, d.GasHist.Count - 7)).Select(x => x.ToString("0.0", System.Globalization.CultureInfo.InvariantCulture))))); if (d.GasHist.Count > 0) list.Add(L.T("predict.clue.gas", string.Join(" ", d.GasHist.Skip(Math.Max(0, d.GasHist.Count - 7)).Select(x => x.ToString("0.0", System.Globalization.CultureInfo.InvariantCulture)))));
break; break;
case PredictKind.Cra: case PredictKind.Cra:
list.Add(L.T("predict.clue.subsidy", (d.Stable.CraSubsidy / Tuning.CraSubsidy0 * 100).ToString("0"))); list.Add(L.T("predict.clue.subsidy", (d.Stable.Cushion / Stablecoins.Cushion0 * 100).ToString("0")));
list.Add(L.T("predict.clue.drain", Fmt.Num(CraDrain(d)))); list.Add(L.T("predict.clue.drain", Fmt.Num(CraDrain(d))));
break; break;
case PredictKind.Era: case PredictKind.Era:
+1 -1
View File
@@ -27,7 +27,7 @@ namespace Decentralized
private static void Apply(SaveData d, int day, string key) private static void Apply(SaveData d, int day, string key)
{ {
if (!d.Story.Apply(key, day)) return; if (!d.Story.Apply(key, day)) return;
if (key == "serpico_rev") d.Stable.CraSubsidy += Tuning.StoryRevSubsidy; if (key == "serpico_rev") d.Stable.Reserve += Tuning.StoryRevSubsidy;
News.Show("pd_news_story_" + key, L.T("news.story." + key + ".title"), L.T("news.story." + key + ".desc"), 4, 9); News.Show("pd_news_story_" + key, L.T("news.story." + key + ".title"), L.T("news.story." + key + ".desc"), 4, 9);
Log.Info($"剧情联动生效:{key}(第 {day} 天)"); Log.Info($"剧情联动生效:{key}(第 {day} 天)");
} }
+55 -16
View File
@@ -2234,7 +2234,15 @@ namespace Decentralized
} }
} }
l.AddSeparator(); l.AddSeparator();
l.AddLabel(L.T("mint.reserve", (st.Ratio * 100).ToString("0", CultureInfo.InvariantCulture), (st.C * 100).ToString("0", CultureInfo.InvariantCulture)), "mint_reserve_dim");
l.AddLabel(L.T("spark.price", Fmt.Num(st.Spark))); l.AddLabel(L.T("spark.price", Fmt.Num(st.Spark)));
var mine = st.Orders.Where(o => d.Own(o.Wallet) != null).ToList();
if (mine.Count > 0)
{
l.AddSeparator();
l.AddLabel(L.T("mint.queue"));
foreach (var o in mine) l.AddLabel(L.T("mint.order", L.T(o.Mint ? "cra.mint" : "cra.burn"), Fmt.Num(o.Cra), o.Due), "mint_order_dim");
}
}, r => }, r =>
{ {
r.AddHeader(L.T("stake.ops", WalletWindow.NameOf(w))); r.AddHeader(L.T("stake.ops", WalletWindow.NameOf(w)));
@@ -2242,19 +2250,35 @@ namespace Decentralized
r.AddLabel(L.T("stake.avail2", Fmt.Num(w.Avail(Assets.SPARK))), "stake_avail2_dim"); r.AddLabel(L.T("stake.avail2", Fmt.Num(w.Avail(Assets.SPARK))), "stake_avail2_dim");
AmountRow(r); AmountRow(r);
r.AddSpace(4f); r.AddSpace(4f);
r.AddLabel(L.T("stake.coin"));
r.BeginRow(4f);
foreach (var c in StakeCoins)
{
var coin = c;
PledgerSkin.Pick(r, coin, coin == _stakeCoin, () => { _stakeCoin = coin; Open(); }, _picked);
}
r.End();
r.BeginRow(6f); r.BeginRow(6f);
r.AddButton(L.T("stake.do"), () => StakeCall(true)); r.AddButton(L.T("stake.do"), () => StakeCall(true));
r.AddButton(L.T("stake.undo"), () => StakeCall(false)); r.AddButton(L.T("stake.undo"), () => StakeCall(false));
r.End(); r.End();
r.AddSeparator(); r.AddSeparator();
r.AddHeader(L.T("spark.h")); r.AddHeader(L.T("mint.h"));
if (double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double mv) && mv > 0)
{
st.Collateral(mv, out double needCrc, out double needSpark);
r.AddLabel(L.T("mint.need", Fmt.Num(needCrc), Fmt.Num(needSpark)), "mint_need_dim");
}
r.BeginRow(6f); r.BeginRow(6f);
r.AddButton(L.T("spark.mint"), () => SparkCall(true)); r.AddButton(L.T("cra.mint"), () => MintCall(true));
r.AddButton(L.T("spark.burn"), () => SparkCall(false)); r.AddButton(L.T("cra.burn"), () => MintCall(false));
r.End(); r.End();
}); });
} }
private static readonly string[] StakeCoins = { Assets.CRA, Assets.CRC, Assets.CRT, Assets.SPARK };
private static string _stakeCoin = Assets.CRA;
/// <summary>手续费用钱包里价值最高的那种币付。</summary> /// <summary>手续费用钱包里价值最高的那种币付。</summary>
private static string BestFeeAsset(Wallet w) => private static string BestFeeAsset(Wallet w) =>
w.Balances.Where(k => k.Value > 1e-9 && Session.Price(k.Key) > 0).OrderByDescending(k => k.Value * Session.Price(k.Key)).Select(k => k.Key).FirstOrDefault() ?? Assets.PSC; w.Balances.Where(k => k.Value > 1e-9 && Session.Price(k.Key) > 0).OrderByDescending(k => k.Value * Session.Price(k.Key)).Select(k => k.Key).FirstOrDefault() ?? Assets.PSC;
@@ -2264,42 +2288,57 @@ namespace Decentralized
if (!ReadAmount(out double v)) return; if (!ReadAmount(out double v)) return;
var d = Session.Data; var d = Session.Data;
var w = d.Hot; var w = d.Hot;
if (into ? w.Avail(Assets.CRA) + 1e-9 < v : (d.Staking.Of(w.Address)?.Amount ?? 0) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; } string coin = into ? _stakeCoin : Assets.CRA;
if (into ? w.Avail(coin) + 1e-9 < v : (d.Staking.Of(w.Address)?.Amount ?? 0) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
var q = into && coin != Assets.CRA ? d.Market.Quote(coin, Assets.CRA, v) : null;
_message = L.T("hw.wait"); _message = L.T("hw.wait");
Open(); Open();
WalletWindow.OpenForBill(new WalletWindow.Bill WalletWindow.OpenForBill(new WalletWindow.Bill
{ {
Contract = true, Asset = Assets.CRA, Amount = v, Spend = into ? v : 0, FeeAsset = into ? null : BestFeeAsset(w), Contract = true, Asset = coin, Amount = v, Spend = into ? v : 0, FeeAsset = into ? null : BestFeeAsset(w),
Summary = L.T(into ? "stake.sum.in" : "stake.sum.out", Fmt.Num(v), Tuning.CraUnlockDays), Summary = into && q != null ? L.T("stake.sum.via", Fmt.Num(v), coin, Fmt.Num(q.Out)) : L.T(into ? "stake.sum.in" : "stake.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
Execute = pw => Execute = pw =>
{ {
int day = StoreStation.GetDayCounter(); int day = StoreStation.GetDayCounter();
bool ok = into ? d.Staking.Stake(pw, v, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day); double cra = v;
_message = ok ? L.T(into ? "stake.done.in" : "stake.done.out", Fmt.Num(v), day + Tuning.CraUnlockDays) : L.T("msg.balance"); if (into && coin != Assets.CRA)
{
if (pw.Avail(coin) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
double spent = v * Session.Price(coin);
cra = d.Market.Swap(coin, Assets.CRA, v);
pw.Add(coin, -v); pw.Add(Assets.CRA, cra); pw.RecordBuy(Assets.CRA, cra, spent);
CandleChart.Trade(coin, spent); CandleChart.Trade(Assets.CRA, spent);
}
bool ok = into ? d.Staking.Stake(pw, cra, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day);
_message = ok ? L.T(into ? "stake.done.in" : "stake.done.out", Fmt.Num(cra), day + Tuning.CraUnlockDays) : L.T("msg.balance");
Session.Save(); Session.Save();
Open(); Open();
}, },
}); });
} }
private static void SparkCall(bool mint) /// <summary>官方一级市场:存入 CRC 和 SPARK 铸造 CRA(铸出后直接进质押),或销毁 CRA 换回两者。排队等待,官方可能不兑现。</summary>
private static void MintCall(bool mint)
{ {
if (!ReadAmount(out double v)) return; if (!ReadAmount(out double v)) return;
var d = Session.Data; var d = Session.Data;
var w = d.Hot; var w = d.Hot;
string pay = mint ? Assets.CRA : Assets.SPARK, get = mint ? Assets.SPARK : Assets.CRA; var st = d.Stable;
if (w.Avail(pay) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; } st.Collateral(v, out double needCrc, out double needSpark);
double quote = mint ? v * d.Stable.Cra / d.Stable.Spark * (1 - Tuning.SparkFee) : v * d.Stable.Spark / d.Stable.Cra * (1 - Tuning.SparkFee); bool enough = mint ? w.Avail(Assets.CRC) + 1e-9 >= needCrc && w.Avail(Assets.SPARK) + 1e-9 >= needSpark : w.Avail(Assets.CRA) + 1e-9 >= v;
if (!enough) { _message = L.T("msg.balance"); Open(); return; }
int minD = Tuning.CraMintDaysMin, maxD = Tuning.CraMintDaysMax;
_message = L.T("hw.wait"); _message = L.T("hw.wait");
Open(); Open();
WalletWindow.OpenForBill(new WalletWindow.Bill WalletWindow.OpenForBill(new WalletWindow.Bill
{ {
Contract = true, Asset = pay, Amount = v, Summary = L.T("hw.swap", Fmt.Num(v), pay, Fmt.Num(quote), get), Contract = true, Asset = mint ? Assets.CRC : Assets.CRA, Amount = mint ? needCrc : v, Spend = mint ? needCrc : v,
Summary = mint ? L.T("mint.sum.in", Fmt.Num(v), Fmt.Num(needCrc), Fmt.Num(needSpark), minD, maxD) : L.T("mint.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
Execute = pw => Execute = pw =>
{ {
double got = mint ? d.Stable.Mint(pw, v) : d.Stable.Burn(pw, v); int day = StoreStation.GetDayCounter();
if (got >= 0) { double cr = v * Session.Price(pay); CandleChart.Trade(Assets.SPARK, cr); CandleChart.Trade(Assets.CRA, cr); } var o = mint ? st.RequestMint(pw, v, day, d.Rng) : st.RequestBurn(pw, v, day);
_message = got < 0 ? L.T("msg.balance") : L.T("msg.trade", Fmt.Num(v), pay, Fmt.Num(got), get); _message = o == null ? L.T("msg.balance") : L.T(mint ? "mint.done.in" : "mint.done.out", o.Due);
Session.Save(); Session.Save();
Open(); Open();
}, },
+103 -15
View File
@@ -376,18 +376,108 @@ internal static class Program
"CRT 冻结概率:声望 0 为 40%,25 为 20%,50 为 0"); "CRT 冻结概率:声望 0 为 40%,25 为 20%,50 为 0");
}); });
Test("稳定币:CRA 补贴池告急即为预兆;螺旋三天 0.85 / 0.30 / 0.02", () => Test("稳定币:CRA 垫子告急即为预兆;储备吃空必崩,螺旋三天 0.85 / 0.30 / 0.02", () =>
{ {
var s = new Stablecoins { CraSubsidy = Tuning.CraSubsidy0 * 0.19 }; var s = new Stablecoins { Reserve = Tuning.CraCrashRatio * Tuning.CraS0 + Stablecoins.Cushion0 * 0.19 };
Check(s.CraWarning(1) && s.CraRate == Tuning.CraRateLow, "补贴池低于 20%:预兆出现、利率降到 0.2%"); Check(s.CraWarning(1) && s.CraRate == Tuning.CraRateLow, "垫子低于 20%:预兆出现、利率降到 0.2%");
var t = new Stablecoins { CraSubsidy = 1 }; var t = new Stablecoins { Reserve = Tuning.CraS0 * 0.2 };
var rng = new Rng(3); var rng = new Rng(3);
t.Night(1, rng, 100000); t.Night(1, rng, 100000);
Check(t.CraWarnDay == 1 && t.CraSpiralDay >= 5 && t.CraSpiralDay <= 8, $"补贴池吃空触发螺旋,提前 4–7 天:第 {t.CraSpiralDay} 天开始"); Check(t.CraWarnDay == 1 && t.CraEventDay >= 5 && t.CraEventDay <= 8, $"垫子吃空触发预兆,提前 4–7 天:第 {t.CraEventDay} 天挪用");
int ev = t.CraEventDay;
var path = new List<double>(); var path = new List<double>();
for (int d = 2; d <= t.CraSpiralDay + 3; d++) { t.Night(d, rng, 0); if (d >= t.CraSpiralDay) path.Add(t.Cra); } for (int d = 2; d <= ev + 3; d++) { t.Night(d, rng, 0); if (d >= ev) path.Add(t.Cra); }
Check(path.Take(3).SequenceEqual(new[] { 0.85, 0.30, 0.02 }), $"螺旋路径:{string.Join(" / ", path)}"); Check(t.CraCrashDay == ev && path.Take(3).SequenceEqual(new[] { 0.85, 0.30, 0.02 }), $"崩盘路径:{string.Join(" / ", path)}");
Check(!t.CraWarning(t.CraSpiralDay + 1), "螺旋开始后不再算预兆"); Check(!t.CraWarning(ev + 1), "崩盘开始后不再算预兆");
});
Test("稳定币:挪用后 R/S 低于崩盘线才崩,否则只是折价;劫掠上层补回储备", () =>
{
int crashes = 0, discounts = 0;
for (ulong seed = 1; seed <= 60; seed++)
{
var s = new Stablecoins { Supply = 100000, Reserve = 100000, C = 0.8, CraWarnDay = 1, CraEventDay = 2 };
s.Night(2, new Rng(seed), 0);
double r = s.Ratio;
Check(r >= 1 - Tuning.CraEmbezzleMax - 0.01 && r <= 1 - Tuning.CraEmbezzleMin + 0.01 && s.CraEventDay < 0 && s.CraWarnDay < 0, $"储备被拿走 40%–80%:R/S {r:0.00}");
if (r < Tuning.CraCrashRatio) { crashes++; Check(s.CraCrashDay == 2 && s.Cra == Tuning.CraSpiralPath[0], "R/S 跌破崩盘线:当天进入螺旋"); }
else { discounts++; Check(s.CraCrashDay < 0 && Near(s.Cra, Stablecoins.PriceOfRatio(r), 1e-9), $"折价:{s.Cra:0.000}"); }
}
Check(crashes > 5 && discounts > 5, $"两种结果都会出现:崩盘 {crashes}、折价 {discounts}");
var t = new Stablecoins(); double before = t.Reserve;
t.OnEventStart(MarketEvent.RevRaidUpper, 3, new Rng(1));
Check(Near(t.Reserve, before + Tuning.CraLoot * t.Supply, 1e-6), "劫掠上层把流通量 × 9% 的 CRC 并入储备");
Check(Stablecoins.PriceOfRatio(Tuning.CraSafeRatio) == 1 && Near(Stablecoins.PriceOfRatio(Tuning.CraCrashRatio), 1 - Tuning.CraDiscountMax, 1e-9), "价格曲线:安全线 1,崩盘线折价 15%");
});
Test("CRA 长期行为:200 天里有的局崩盘有的不崩,质押越多崩得越多,崩盘前有预兆", () =>
{
Func<double, (double crash, double lead)> run = staked =>
{
int crashes = 0, n = 300; double leadSum = 0; int leads = 0;
for (int i = 0; i < n; i++)
{
var s = new Stablecoins(); var rng = new Rng((ulong)(i + 1));
int warn = -1;
for (int d = 1; d <= 200 && s.CraCrashDay < 0; d++)
{
if (rng.Chance(0.03)) s.OnEventStart(MarketEvent.RevRaidUpper, d, rng);
s.Night(d, rng, staked);
if (warn < 0 && s.CraWarnDay >= 0) warn = s.CraWarnDay;
if (s.CraWarnDay < 0 && s.CraCrashDay < 0) warn = -1;
}
if (s.CraCrashDay >= 0) { crashes++; if (warn >= 0) { leadSum += s.CraCrashDay - warn; leads++; } }
}
return (crashes / (double)n, leads > 0 ? leadSum / leads : 0);
};
var lo = run(0); var hi = run(100000);
Check(lo.crash > 0.02 && lo.crash < 0.9, $"无质押 200 天崩盘比例 {lo.crash:P0}");
Check(hi.crash >= lo.crash, $"质押 10 万:{hi.crash:P0} ≥ 无质押 {lo.crash:P0}");
Check(lo.lead >= Tuning.CraWarnLeadMin - 0.01 && lo.lead <= Tuning.CraWarnLeadMax + 0.01, $"预兆到崩盘平均 {lo.lead:0.0} 天");
});
Test("CRA 一级市场:铸造按抵押率存 CRC 加 SPARK,排队后进流通量与储备;销毁按 min(c, R/S) 兑付", () =>
{
var s = new Stablecoins(); var rng = new Rng(2);
var w = new Wallet { Address = "w" };
s.Collateral(1000, out double crc, out double spark);
Check(Near(crc, 1000 * Tuning.CraC0, 1e-9) && Near(spark * s.Spark, 1000 * (1 - Tuning.CraC0), 1e-9), $"抵押:CRC {crc:0},SPARK {spark:0.##}");
Check(s.RequestMint(w, 1000, 1, rng) == null, "钱包里没有币:拒绝");
w.Add(Assets.CRC, crc); w.Add(Assets.SPARK, spark);
double S0 = s.Supply, R0 = s.Reserve;
var o = s.RequestMint(w, 1000, 1, rng);
Check(o != null && w.Get(Assets.CRC) == 0 && w.Get(Assets.SPARK) == 0 && o.Due >= 2 && o.Due <= 3, "存入后排队 1~2 天");
var evs = s.NightOrders(1, rng);
Check(evs.Count == 0 && s.Supply == S0, "没到期不结算");
evs = s.NightOrders(o.Due, rng);
Check(evs.Count == 1 && evs[0].Kind == CraOrderKind.Minted && Near(s.Supply, S0 + 1000, 1e-9) && Near(s.Reserve, R0 + crc, 1e-9), "到期:流通量加 1000,储备加 CRC 部分");
w.Add(Assets.CRA, 500);
double ratio = s.Ratio;
var b = s.RequestBurn(w, 500, 5);
Check(b != null && b.Due == 5 + Tuning.CraUnlockDays && w.Get(Assets.CRA) == 0, "销毁排队解锁期");
evs = s.NightOrders(b.Due, rng);
Check(evs.Count == 1 && evs[0].Kind == CraOrderKind.Burned && Near(evs[0].Crc, 500 * Math.Min(Tuning.CraC0, ratio), 1e-6) && evs[0].Spark > 0, $"兑付 CRC {evs[0].Crc:0}、SPARK {evs[0].Spark:0.##}");
var low = new Stablecoins { Supply = 1000, Reserve = 200 };
low.Redeem(100, 0.8, out double c2, out double sp2);
Check(Near(c2, 20, 1e-9) && Near(sp2 * low.Spark, 80, 1e-9), "储备只有 R/S = 0.2:CRC 份额降到 0.2,其余用 SPARK 补");
});
Test("CRA 一级市场:官方跑路概率 = 系数 × (1 − CRA 价格),命中整笔丢失", () =>
{
var s = new Stablecoins();
Check(s.RugChance == 0, "价格 1 时不会跑路");
s.Cra = 0.9;
Check(Near(s.RugChance, Tuning.CraRugPerDepeg * 0.1, 1e-9), "价格 0.9 时概率 10%");
int lost = 0, n = 4000;
for (int i = 0; i < n; i++)
{
var t = new Stablecoins { Cra = 0.9, Supply = 1000, Reserve = 800 };
var w = new Wallet { Address = "w" }; w.Add(Assets.CRA, 10);
t.RequestBurn(w, 10, 1);
var ev = t.NightOrders(1, new Rng((ulong)i));
if (ev.Count == 1 && ev[0].Kind == CraOrderKind.Lost) { lost++; Check(t.Orders.Count == 0 && w.Get(Assets.CRA) == 0, "丢失不退款"); }
}
Check(Math.Abs(lost / (double)n - 0.1) < 0.03, $"命中率 {lost / (double)n:P1}");
}); });
Test("合规出金:干净小额不查;污点高时重度命中记罪证;轻度命中只没收污点部分;只对收益计税", () => Test("合规出金:干净小额不查;污点高时重度命中记罪证;轻度命中只没收污点部分;只对收益计税", () =>
@@ -599,7 +689,7 @@ internal static class Program
Check(Near(back.Market.Price, m.Price, 1e-9) && back.Market.Pools.Count == m.Pools.Count && back.Market.Pools[1].Id == m.Pools[1].Id, "交易对与价格"); Check(Near(back.Market.Price, m.Price, 1e-9) && back.Market.Pools.Count == m.Pools.Count && back.Market.Pools[1].Id == m.Pools[1].Id, "交易对与价格");
Check(back.Hot.Get(Assets.PSC) == 5 && back.Hot.Taint == 12 && back.Hot.Basis == 34, "钱包余额、污点、成本"); Check(back.Hot.Get(Assets.PSC) == 5 && back.Hot.Taint == 12 && back.Hot.Basis == 34, "钱包余额、污点、成本");
Check(back.Exchange.History.Count == 1 && back.Exchange.History[0].Value == 100, "出金记录"); Check(back.Exchange.History.Count == 1 && back.Exchange.History[0].Value == 100, "出金记录");
Check(Near(back.Network.NpcHash, net.NpcHash, 1e-9) && Near(back.Stable.CraSubsidy, st.CraSubsidy, 1e-9), "全网算力、CRA 补贴池"); Check(Near(back.Network.NpcHash, net.NpcHash, 1e-9) && Near(back.Stable.Reserve, st.Reserve, 1e-9), "全网算力、CRA 储备");
for (int d = 6; d <= 10; d++) for (int d = 6; d <= 10; d++)
{ {
m.Night(new MarketEvent[0], rng, d, a => 1); m.Night(new MarketEvent[0], rng, d, a => 1);
@@ -1042,12 +1132,12 @@ internal static class Program
Check(Math.Abs(w.Get(Assets.CRA) - 700) < 1e-6, $"到期自动回钱包 200:{w.Get(Assets.CRA):0.##}"); Check(Math.Abs(w.Get(Assets.CRA) - 700) < 1e-6, $"到期自动回钱包 200:{w.Get(Assets.CRA):0.##}");
Check(w.Taint > 400 - lotTaint + 1, "污点按比例回来"); Check(w.Taint > 400 - lotTaint + 1, "污点按比例回来");
// 螺旋:质押的 CRA 取回后只值当时的价格 // 螺旋:质押的 CRA 取回后只值当时的价格
var s = new Stablecoins(); s.CraSpiralDay = 5; var s = new Stablecoins(); s.CraCrashDay = 5;
for (int d = 5; d <= 7; d++) s.Night(d, new Rng(1), 0); for (int d = 5; d <= 7; d++) s.Night(d, new Rng(1), 0);
Check(s.Cra < 0.05 && s.Spark < Tuning.SparkStart * 0.1, $"螺旋后 CRA {s.Cra},SPARK {s.Spark:0.00}"); Check(s.Cra < 0.05 && s.Spark < Tuning.SparkStart * 0.1, $"螺旋后 CRA {s.Cra},SPARK {s.Spark:0.00}");
}); });
Test("SPARK:随机游走有界,铸销来回只损手续费,事件冲击", () => Test("SPARK:随机游走有界,铸销事件冲击", () =>
{ {
double lo = 99, hi = 0; double lo = 99, hi = 0;
for (ulong seed = 1; seed <= 20; seed++) for (ulong seed = 1; seed <= 20; seed++)
@@ -1056,9 +1146,7 @@ internal static class Program
for (int d = 1; d <= 150 && s.CraWarnDay < 0; d++) { s.Night(d, rng, 0); lo = Math.Min(lo, s.Spark); hi = Math.Max(hi, s.Spark); } // 螺旋前 for (int d = 1; d <= 150 && s.CraWarnDay < 0; d++) { s.Night(d, rng, 0); lo = Math.Min(lo, s.Spark); hi = Math.Max(hi, s.Spark); } // 螺旋前
} }
Check(lo >= Tuning.SparkStart * Tuning.SparkMinMult - 1e-9 && hi <= Tuning.SparkStart * Tuning.SparkMaxMult + 1e-9 && hi / lo > 1.5, $"螺旋前的范围 {lo:0.0}–{hi:0.0}"); Check(lo >= Tuning.SparkStart * Tuning.SparkMinMult - 1e-9 && hi <= Tuning.SparkStart * Tuning.SparkMaxMult + 1e-9 && hi / lo > 1.5, $"螺旋前的范围 {lo:0.0}–{hi:0.0}");
var s2 = new Stablecoins(); var w = new Wallet { Address = "w" }; w.Add(Assets.CRA, 100); var s2 = new Stablecoins();
double sp = s2.Mint(w, 100), back = s2.Burn(w, sp);
Check(Math.Abs(back - 100 * Math.Pow(1 - Tuning.SparkFee, 2)) < 1e-6 && s2.Mint(w, 1e6) < 0, $"来回 100 → {back:0.00},余额不足返回 -1");
double before = s2.Spark; s2.OnEventStart(MarketEvent.RevRaidUpper, 1, new Rng(1)); double before = s2.Spark; s2.OnEventStart(MarketEvent.RevRaidUpper, 1, new Rng(1));
Check(Math.Abs(s2.Spark - before * Tuning.SparkRaidShock) < 1e-9, "袭击上层 +15%"); Check(Math.Abs(s2.Spark - before * Tuning.SparkRaidShock) < 1e-9, "袭击上层 +15%");
}); });
@@ -1333,7 +1421,7 @@ internal static class Program
Check(Math.Abs(hit / (double)runs - PredictMath.GasAtLeast(10, 3, 1.3)) < 0.02, "gas 概率和真实抽样对得上"); Check(Math.Abs(hit / (double)runs - PredictMath.GasAtLeast(10, 3, 1.3)) < 0.02, "gas 概率和真实抽样对得上");
double h = 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7); double h = 1 - Math.Pow(1 - Tuning.CraSpiralWeekly, 1.0 / 7);
Check(Math.Abs(PredictMath.CraWarnProb(1e9, 100, 10, 12, 14, h) - (1 - Math.Pow(1 - h, 3)) * Math.Pow(1 - h, 2)) < 1e-9, "补贴池充足时按日概率,窗口前发出的不算"); Check(Math.Abs(PredictMath.CraWarnProb(1e9, 100, 10, 12, 14, h) - (1 - Math.Pow(1 - h, 3)) * Math.Pow(1 - h, 2)) < 1e-9, "补贴池充足时按日概率,窗口前发出的不算");
Check(PredictMath.CraWarnProb(150, 100, 10, 11, 12, h) > 0.99, "补贴池撑不过窗口前一晚就必发"); Check(Math.Abs(PredictMath.CraWarnProb(150, 100, 10, 11, 12, h) - (1 - h)) < 1e-9, "垫子撑不过窗口前一晚:窗口第一晚必发,只要之前没按日概率发出");
Check(PredictMath.CraWarnProb(50, 100, 10, 10, 10, h) == 1, "归零那晚必发"); Check(PredictMath.CraWarnProb(50, 100, 10, 10, 10, h) == 1, "归零那晚必发");
Check(PredictMath.EraProb(60, 61, 63, -1) > 0 && PredictMath.EraProb(60, 61, 63, -1) < 0.2, "没预警时在 50–90 里均匀,3 天窗口很小"); Check(PredictMath.EraProb(60, 61, 63, -1) > 0 && PredictMath.EraProb(60, 61, 63, -1) < 0.2, "没预警时在 50–90 里均匀,3 天窗口很小");
Check(Math.Abs(PredictMath.EraProb(60, 62, 63, 58) - 0.5) < 1e-9 || PredictMath.EraProb(60, 62, 63, 58) > 0, "预警后落在 4–7 天内"); Check(Math.Abs(PredictMath.EraProb(60, 62, 63, 58) - 0.5) < 1e-9 || PredictMath.EraProb(60, 62, 63, 58) > 0, "预警后落在 4–7 天内");