From 202bdbbfbcba36bf40006385cd5d34260552e3ae Mon Sep 17 00:00:00 2001 From: ZHU MINCHAO <48154958+MinchaoZhu@users.noreply.github.com> Date: Tue, 3 Nov 2026 14:05:47 +0800 Subject: [PATCH] Four tiers per brand: RZX 60/70/80/90 and RZ 70/80/800/900 Model name is display only; performance and price follow brand and tier. Tier physical traits: power pins 6/8/8/8+8 and fans 1/2/3/3. Co-Authored-By: Claude Sonnet 5.5 --- src/Decentralized.Domain/Dealer.cs | 6 +++--- src/Decentralized.Domain/Mining.cs | 19 +++++++++++++------ src/Decentralized/DealerStock.cs | 8 ++++---- src/Decentralized/Items.cs | 2 +- src/Decentralized/Unlock.cs | 2 +- src/Decentralized/UsedDealerClient.cs | 2 +- tests/Decentralized.Domain.Tests/Program.cs | 12 ++++++------ 7 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/Decentralized.Domain/Dealer.cs b/src/Decentralized.Domain/Dealer.cs index e64d4cb..2074e28 100644 --- a/src/Decentralized.Domain/Dealer.cs +++ b/src/Decentralized.Domain/Dealer.cs @@ -9,9 +9,9 @@ namespace Decentralized.Domain { public const string Rig = "RIG"; - public static readonly string[] Basic = { "RZX50", "RZX60", "RZ470", "RZ580" }; - public static readonly string[] Advanced = { "RZX70", "RZX80Ti", "RZ6800" }; - public static readonly string[] Flagship = { "RZX90", "RZ7900" }; + public static readonly string[] Basic = { "RZX60", "RZ70" }; + public static readonly string[] Advanced = { "RZX70", "RZ80", "RZX80", "RZ800" }; + public static readonly string[] Flagship = { "RZX90", "RZ900" }; public const int AdvancedFromDay = 10, FlagshipFromDay = 30, SpecialFlagshipFromDay = 20; public const double RigRestockChance = 0.30, AdvancedChance = 0.60, AdvancedSecondChance = 0.30, FlagshipChance = 0.25; diff --git a/src/Decentralized.Domain/Mining.cs b/src/Decentralized.Domain/Mining.cs index 9b82b86..8ce749b 100644 --- a/src/Decentralized.Domain/Mining.cs +++ b/src/Decentralized.Domain/Mining.cs @@ -13,6 +13,8 @@ namespace Decentralized.Domain public double Kj; public int Price; /// 暴毙概率的品牌系数。 + /// 档次:0 低端、1 中端、2 高端、3 旗舰(显卡)。实物特征(供电口、风扇数)只看档次。 + public int Tier; public double DeathFactor; /// 每天损耗的系数。 public double WearFactor; @@ -25,20 +27,25 @@ namespace Decentralized.Domain public static class Hardware { + /// 各档次的实物特征:供电口针数(旗舰是两个 8 针)与风扇数量。 + public static readonly string[] PowerPins = { "6", "8", "8", "8+8" }; + public static readonly int[] FanCount = { 1, 2, 3, 3 }; + public const string Probidia = "Probidia", Pmd = "PMD", RatDigg = "RatDigg"; public static readonly IReadOnlyDictionary Specs = new[] { - Gpu("RZX50", Probidia, 1.0, 4, 220), Gpu("RZX60", Probidia, 1.5, 5, 330), Gpu("RZX70", Probidia, 5.0, 12, 800), - Gpu("RZX80Ti", Probidia, 8.0, 18, 1300), Gpu("RZX90", Probidia, 20.0, 30, 5000), - Gpu("RZ470", Pmd, 0.8, 2.5, 170), Gpu("RZ580", Pmd, 1.2, 3, 250), Gpu("RZ6800", Pmd, 4.0, 8, 680), - Gpu("RZ7900", Pmd, 15.0, 20, 4000), + // 四个档次(低端、中端、高端、旗舰),两个牌子通用:型号只是显示名,性能和价格由「牌子 + 档次」决定 + Gpu("RZX60", Probidia, 0, 1.0, 4, 220), Gpu("RZX70", Probidia, 1, 5.0, 12, 800), + Gpu("RZX80", Probidia, 2, 8.0, 18, 1300), Gpu("RZX90", Probidia, 3, 20.0, 30, 5000), + Gpu("RZ70", Pmd, 0, 0.8, 2.5, 170), Gpu("RZ80", Pmd, 1, 4.0, 8, 680), + Gpu("RZ800", Pmd, 2, 8.0, 12, 1500), Gpu("RZ900", Pmd, 3, 15.0, 20, 4000), Asic("M1", 50, 60, 11000), Asic("M2", 120, 110, 27000), Asic("M3", 300, 220, 72000), }.ToDictionary(s => s.Model); - private static HardwareSpec Gpu(string model, string brand, double h, double kj, int price) => new HardwareSpec + private static HardwareSpec Gpu(string model, string brand, int tier, double h, double kj, int price) => new HardwareSpec { - Model = model, Brand = brand, Hash = h, Kj = kj, Price = price, + Model = model, Brand = brand, Tier = tier, Hash = h, Kj = kj, Price = price, DeathFactor = brand == Probidia ? 0.7 : 1.0, WearFactor = brand == Probidia ? 1.0 : 1.2, }; diff --git a/src/Decentralized/DealerStock.cs b/src/Decentralized/DealerStock.cs index dbd62cc..8a2f3a2 100644 --- a/src/Decentralized/DealerStock.cs +++ b/src/Decentralized/DealerStock.cs @@ -19,10 +19,10 @@ namespace Decentralized ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Used cards x4 (test)", () => { var rng = Session.Data.Rng; - Items.Give(Items.NewCard("RZX80Ti", 40, null, rng)); - Items.Give(Items.NewCard("RZX80Ti", 70, "RZX60", rng)); - Items.Give(Items.NewCard("RZ6800", 30, "RZ580", rng)); - Items.Give(Items.NewCard("RZ7900", 90, "RZ470", rng)); + Items.Give(Items.NewCard("RZX80", 40, null, rng)); + Items.Give(Items.NewCard("RZX80", 70, "RZX60", rng)); + Items.Give(Items.NewCard("RZ800", 30, "RZ70", rng)); + Items.Give(Items.NewCard("RZ900", 90, "RZ70", rng)); }); ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Dump inspection UI (test)", () => Log.Guard("检视界面结构", () => { diff --git a/src/Decentralized/Items.cs b/src/Decentralized/Items.cs index 9325f9d..e4762d7 100644 --- a/src/Decentralized/Items.cs +++ b/src/Decentralized/Items.cs @@ -63,7 +63,7 @@ namespace Decentralized // ---------- 显卡 ---------- - /// RZX70 → "RZX 70",RZX80Ti → "RZX 80 Ti",RZ6800 → "RZ 6800"。 + /// RZX70 → "RZX 70",RZ800 → "RZ 800"。 public static string DisplayModel(string model) => Regex.Replace(Regex.Replace(model, @"(?<=[A-Za-z])(?=\d)", " "), @"(?<=\d)(?=[A-Z])", " "); private static GameItem CreateGpu(HardwareSpec spec) diff --git a/src/Decentralized/Unlock.cs b/src/Decentralized/Unlock.cs index 2a134f4..09c63a1 100644 --- a/src/Decentralized/Unlock.cs +++ b/src/Decentralized/Unlock.cs @@ -32,7 +32,7 @@ namespace Decentralized { Items.Give(ModHelper.SpawnItem(Items.Terminal)); Items.Give(ModHelper.SpawnItem(Items.Rig)); - Items.Give(ModHelper.SpawnItem(Items.GpuId("RZX50"))); + Items.Give(ModHelper.SpawnItem(Items.GpuId("RZX60"))); Log.Info("已加入 Web3 治理社区"); } } diff --git a/src/Decentralized/UsedDealerClient.cs b/src/Decentralized/UsedDealerClient.cs index c729285..a54bedc 100644 --- a/src/Decentralized/UsedDealerClient.cs +++ b/src/Decentralized/UsedDealerClient.cs @@ -18,7 +18,7 @@ namespace Decentralized public static void Subscribe() { ModHook.OnGenerateCustomerNormal += OnGenerate; - ModHelper.AddAppraisalItem(ModInfo.Id, Appraisal, Items.GpuId("RZX50"), 2, CreateForAppraisal, u => (int)CardValue.True(Items.ToUnit(u)), + ModHelper.AddAppraisalItem(ModInfo.Id, Appraisal, Items.GpuId("RZX60"), 2, CreateForAppraisal, u => (int)CardValue.True(Items.ToUnit(u)), Items.IsGpu, null, () => L.T("appraisal.gpu")); ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Appraisal client (test)", () => Log.Guard("鉴定客户(测试)", () => { diff --git a/tests/Decentralized.Domain.Tests/Program.cs b/tests/Decentralized.Domain.Tests/Program.cs index 1898bef..d5d0039 100644 --- a/tests/Decentralized.Domain.Tests/Program.cs +++ b/tests/Decentralized.Domain.Tests/Program.cs @@ -112,7 +112,7 @@ internal static class Program Test("显卡:型号、显示单位、健康度与算力衰减", () => { - Check(Hardware.Specs["RZX70"].DisplayHash == 50 && Hardware.Specs["RZ6800"].DisplayHash == 40, "RZX70 50 MH/s,RZ6800 40 MH/s"); + Check(Hardware.Specs["RZX70"].DisplayHash == 50 && Hardware.Specs["RZ80"].DisplayHash == 40, "RZX70 50 MH/s,RZ80 40 MH/s"); Check(Near(Hardware.Specs["M3"].DisplayHash, 3, 1e-9), "RatDigg M3 3 GH/s"); var u = new Unit { Model = "RZX70" }; Check(u.Hash(ModuleBonus.None) == 5, "满健康 5 H"); @@ -122,7 +122,7 @@ internal static class Program Check(Near(u.Hash(ModuleBonus.None), 3.0, 1e-9), "健康 0:60%"); Check(Near(new Unit { Model = "RZX70" }.Hash(ModuleBonus.From(36, -44, 0)), 5 * 1.09, 1e-9), "一个超频模块(+36 性能):算力 +9%"); var fake = new Unit { Model = "RZX90", FakeOf = "RZX60" }; - Check(fake.Hash(ModuleBonus.None) == 1.5 && fake.Label.Model == "RZX90", "假卡标着 RZX90,算力按 RZX60"); + Check(fake.Hash(ModuleBonus.None) == 1.0 && fake.Label.Model == "RZX90", "假卡标着 RZX90,算力按 RZX60"); Check(Near(fake.DeathChance(ModuleBonus.None), new Unit { Model = "RZX90" }.DeathChance(ModuleBonus.None) * 2, 1e-12), "假卡暴毙率 ×2"); var r = new Unit { Model = "RZX70", Health = 50 }; Check(r.Refurbish() && r.Health == 80 && !r.Refurbish(), "翻新一次 +30,不能再翻新"); @@ -152,7 +152,7 @@ internal static class Program Check(Near(fakeSigns / (double)n, 1.65, 0.12), $"假卡平均 1.65 处破绽:{fakeSigns / (double)n:0.00}"); Check(oldWorn > newWorn * 1.8, $"低健康度的真卡明显更旧:{oldWorn / (double)n:P0} 对 {newWorn / (double)n:P0}"); Check(seen.Count >= 120, $"抽样见到 {seen.Count} 种不同组合(上限 243)"); - Check(Hardware.Specs["RZX50"].Price == 220 && Hardware.Specs["RZX90"].Price == 5000 && Hardware.Specs["RZ7900"].Price == 4000, "价格已抬高到约 1.8 倍"); + Check(Hardware.Specs["RZX60"].Price == 220 && Hardware.Specs["RZX90"].Price == 5000 && Hardware.Specs["RZ900"].Price == 4000, "价格已抬高到约 1.8 倍"); var u = new Unit { Model = "RZX90", FakeOf = "RZX60", Health = 80 }; Check(CardValue.True(u) == CardValue.Of("RZX60", 80) && CardValue.Quoted(u, 80) == CardValue.Of("RZX90", 80), "真实价值按芯片型号,标称价按标称型号"); Check(CardValue.Quoted(u, 80) > CardValue.True(u) * 8, $"假 RZX 90 的标称价 {CardValue.Quoted(u, 80)} 远高于真值 {CardValue.True(u)}"); @@ -218,7 +218,7 @@ internal static class Program var p = Run("RZX70", ModuleBonus.None, 20000); Check(Near(p[0], 0.11, 0.02) && Near(p[1], 0.53, 0.02) && Near(p[2], 0.84, 0.02), $"Probidia 11% / 53% / 84%:{p[0]:P0} / {p[1]:P0} / {p[2]:P0}"); - var q = Run("RZ6800", ModuleBonus.None, 20000); + var q = Run("RZ80", ModuleBonus.None, 20000); Check(Near(q[0], 0.20, 0.02) && Near(q[1], 0.76, 0.02) && Near(q[2], 0.95, 0.02), $"PMD 20% / 76% / 95%:{q[0]:P0} / {q[1]:P0} / {q[2]:P0}"); }); @@ -358,11 +358,11 @@ internal static class Program Check(fakes > cards * 0.2 && fakes < cards * 0.5, $"骗子的假卡占两成多(入门卡便宜到没法冒充):{fakes}/{cards}"); Check(UsedDealers.Pool(5).All(m => Dealer.Basic.Contains(m)) && UsedDealers.Pool(30).Contains("RZX90"), "型号按天数放开"); // 标签:假 RZX 70(芯片 RZX 50)、健康 60、风扇缺角、金手指氧化、丝印印着真实型号 - var u = new Unit { Model = "RZX70", FakeOf = "RZX50", Health = 60, Look = new CardLook { Fan = 2, Fingers = 2, Print = 1 } }; + var u = new Unit { Model = "RZX70", FakeOf = "RZX60", Health = 60, Look = new CardLook { Fan = 2, Fingers = 2, Print = 1 } }; var claim = CardLabels.DealerClaim(u, DealerKind.Scammer, new Rng(3)); Check(claim.Model == "RZX70" && claim.Fan == 0 && claim.Fingers == 0 && claim.Print == 0, "骗子的说法:标称型号,外观全是没问题"); long hidden = CardLabels.Value(u, claim, 0), real = CardValue.True(u); - Check(hidden == CardValue.Of("RZX70", 60) && real == (long)Math.Round(CardValue.Of("RZX50", 60) * 0.76), "没指出时按说法算(标称型号满价),真实价值按芯片和外观算"); + Check(hidden == CardValue.Of("RZX70", 60) && real == (long)Math.Round(CardValue.Of("RZX60", 60) * 0.76), "没指出时按说法算(标称型号满价),真实价值按芯片和外观算"); int ex = 0; Check(CardLabels.Point(u, claim, CardLabels.RowFan, ref ex) == 1 && CardLabels.Value(u, claim, ex) == (long)Math.Round(CardValue.Of("RZX70", 60) * 0.88), "指出风扇缺角:扣 12%"); Check(CardLabels.Point(u, claim, CardLabels.RowPrint, ref ex) == 2 && (ex & CardLabels.RowSpec) != 0, "指出丝印印着真实型号:拆穿假货,型号标签一并拆穿");