namespace LivingVillage.Kernel.Tests open Microsoft.VisualStudio.TestTools.UnitTesting open LivingVillage.Kernel open LivingVillage.Kernel.Sim module private TradeBiasHarness = let quotedWorld () : World = Sim.initialWorldN 42UL 4 let quote (buyer: NpcId) (seller: NpcId) (item: ItemKind) (world: World) : float32 = match Sim.quotePrice { Buyer = buyer; Seller = seller; Item = item; Quantity = 1 } world with | Some price -> price | None -> Assert.Fail("quote expected"); Unchecked.defaultof [] type TradeBiasTests () = // ---- 默认(无职业)= 旧行为基准 ---- [] member _.NoOccupationKeepsTheHistoricQuoteUnchanged () = Assert.AreEqual(1.0f, Occupation.quoteBiasOf None true) Assert.AreEqual(1.0f, Occupation.quoteBiasOf None false) Assert.AreEqual(Some 10.0f, Occupation.biasedQuote None true (Some 10.0f)) Assert.AreEqual(None, Occupation.biasedQuote None true None) [] member _.FarmerAndFisherStayUnbiasedLikeTheDefaultPath () = for kind in [ Occupation.Farmer; Occupation.Fisher ] do Assert.AreEqual(1.0f, Occupation.quoteBiasOf (Some kind) true) Assert.AreEqual(1.0f, Occupation.quoteBiasOf (Some kind) false) // ---- 货郎:买卖双向有利偏移(±3.00%,4 位定点基点)---- [] member _.PeddlerBuysCheaperAndSellsDearer () = Assert.AreEqual(0.97f, Occupation.quoteBiasOf (Some Occupation.Peddler) true) Assert.AreEqual(1.03f, Occupation.quoteBiasOf (Some Occupation.Peddler) false) // ---- 书生:解读行情的小幅加成(±1.00%)---- [] member _.ScholarGetsASmallerFavorableEdgeThanPeddler () = let scholarBuy = Occupation.quoteBiasOf (Some Occupation.Scholar) true let peddlerBuy = Occupation.quoteBiasOf (Some Occupation.Peddler) true Assert.AreEqual(0.99f, scholarBuy) Assert.AreEqual(1.01f, Occupation.quoteBiasOf (Some Occupation.Scholar) false) Assert.IsTrue(scholarBuy > peddlerBuy, "scholar edge must stay inside the peddler edge") // ---- 确定性与设计区间 [0.95, 1.05] ---- [] member _.BiasIsDeterministicAndInsideTheDesignBand () = for kind in Occupation.all do for playerIsBuyer in [ true; false ] do let first = Occupation.quoteBiasOf (Some kind) playerIsBuyer let second = Occupation.quoteBiasOf (Some kind) playerIsBuyer Assert.AreEqual(first, second) Assert.IsTrue(0.95f <= first && first <= 1.05f, $"{kind} bias {first} escaped the band") // ---- 与既有 Sim.quotePrice(Food 10.0f 路径)复合 ---- [] member _.BiasComposesWithTheExistingQuotePath () = let world = TradeBiasHarness.quotedWorld () let baseBuy = TradeBiasHarness.quote (NpcId 0) (NpcId 1) Food world let baseSell = TradeBiasHarness.quote (NpcId 1) (NpcId 0) Food world Assert.AreEqual(baseBuy * 0.97f, (Occupation.biasedQuote (Some Occupation.Peddler) true (Some baseBuy)).Value) Assert.AreEqual(baseSell * 1.03f, (Occupation.biasedQuote (Some Occupation.Peddler) false (Some baseSell)).Value) Assert.AreEqual(baseBuy, (Occupation.biasedQuote None true (Some baseBuy)).Value)