241 lines
5.8 KiB
Go
241 lines
5.8 KiB
Go
package pricing
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
func TestScreenshotExample(t *testing.T) {
|
|
config := DefaultConfig()
|
|
result := config.Calculate(Input{
|
|
CoinM: 226,
|
|
Insurance: "3*3",
|
|
States: map[string]bool{},
|
|
DailyLossM: 10,
|
|
})
|
|
if result.ReferenceRatio != 46 {
|
|
t.Fatalf("reference ratio = %v, want 46", result.ReferenceRatio)
|
|
}
|
|
if result.FinalRatio != 46 {
|
|
t.Fatalf("final ratio = %v, want 46", result.FinalRatio)
|
|
}
|
|
if result.CoinBasePrice != 491.3 {
|
|
t.Fatalf("coin base price = %v, want 491.3", result.CoinBasePrice)
|
|
}
|
|
if result.ItemPrice != 0 {
|
|
t.Fatalf("item price = %v, want 0", result.ItemPrice)
|
|
}
|
|
if result.TotalPrice != 491.3 {
|
|
t.Fatalf("total price = %v, want 491.3", result.TotalPrice)
|
|
}
|
|
}
|
|
|
|
func TestAllStatesMatched(t *testing.T) {
|
|
config := DefaultConfig()
|
|
result := config.Calculate(Input{
|
|
CoinM: 100,
|
|
Insurance: "3*3",
|
|
States: map[string]bool{
|
|
"melee": true,
|
|
"operatorRed": true,
|
|
"staminaMax": true,
|
|
"loadMax": true,
|
|
"weapon": true,
|
|
},
|
|
DailyLossM: 10,
|
|
})
|
|
if result.ReferenceRatio != 40 {
|
|
t.Fatalf("reference ratio = %v, want 40", result.ReferenceRatio)
|
|
}
|
|
if result.CoinBasePrice != 250 {
|
|
t.Fatalf("coin base price = %v, want 250", result.CoinBasePrice)
|
|
}
|
|
}
|
|
|
|
func TestMissingPenalty(t *testing.T) {
|
|
config := DefaultConfig()
|
|
result := config.Calculate(Input{
|
|
CoinM: 100,
|
|
Insurance: "3*3",
|
|
States: map[string]bool{
|
|
"melee": true,
|
|
"operatorRed": true,
|
|
"staminaMax": true,
|
|
"loadMax": true,
|
|
},
|
|
DailyLossM: 10,
|
|
})
|
|
if result.ConfigPenalty != 1 {
|
|
t.Fatalf("config penalty = %v, want 1", result.ConfigPenalty)
|
|
}
|
|
if result.ReferenceRatio != 41 {
|
|
t.Fatalf("reference ratio = %v, want 41", result.ReferenceRatio)
|
|
}
|
|
if result.CoinBasePrice != 243.9 {
|
|
t.Fatalf("coin base price = %v, want 243.9", result.CoinBasePrice)
|
|
}
|
|
}
|
|
|
|
func TestCoinCorrectionUsesHighestCrossedThreshold(t *testing.T) {
|
|
config := DefaultConfig()
|
|
cases := []struct {
|
|
coinM float64
|
|
want float64
|
|
}{
|
|
{130, 0},
|
|
{130.1, 1},
|
|
{230, 1},
|
|
{230.1, 2.5},
|
|
{380.1, 4},
|
|
{600, 5},
|
|
}
|
|
for _, item := range cases {
|
|
result := config.Calculate(Input{CoinM: item.coinM, Insurance: "3*3", DailyLossM: 10})
|
|
if result.CoinCorrection != item.want {
|
|
t.Fatalf("coinM=%v correction=%v, want %v", item.coinM, result.CoinCorrection, item.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDailyLossAdjustment(t *testing.T) {
|
|
config := DefaultConfig()
|
|
cases := []struct {
|
|
loss float64
|
|
want float64
|
|
}{
|
|
{0, 0},
|
|
{10, 0},
|
|
{20, 1},
|
|
{30, 2},
|
|
{40, 3},
|
|
{50, 4},
|
|
{90, 4},
|
|
}
|
|
for _, item := range cases {
|
|
result := config.Calculate(Input{CoinM: 100, Insurance: "3*3", DailyLossM: item.loss})
|
|
if result.DailyLossAdjustment != item.want {
|
|
t.Fatalf("dailyLoss=%v adjustment=%v, want %v", item.loss, result.DailyLossAdjustment, item.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAcceleratedRatioClamp(t *testing.T) {
|
|
config := DefaultConfig()
|
|
base := Input{CoinM: 226, Insurance: "3*3", DailyLossM: 10}
|
|
|
|
result := config.Calculate(withSaleRatio(base, 50))
|
|
if result.FinalRatio != 50 {
|
|
t.Fatalf("final ratio = %v, want 50", result.FinalRatio)
|
|
}
|
|
if result.MaxRatio != 56 {
|
|
t.Fatalf("max ratio = %v, want 56", result.MaxRatio)
|
|
}
|
|
|
|
result = config.Calculate(withSaleRatio(base, 100))
|
|
if result.FinalRatio != 56 {
|
|
t.Fatalf("clamped ratio = %v, want 56", result.FinalRatio)
|
|
}
|
|
|
|
result = config.Calculate(withSaleRatio(base, 30))
|
|
if result.FinalRatio != 46 {
|
|
t.Fatalf("ratio below reference = %v, want 46", result.FinalRatio)
|
|
}
|
|
}
|
|
|
|
func TestConsumablePriceParsing(t *testing.T) {
|
|
cases := []struct {
|
|
price string
|
|
want float64
|
|
}{
|
|
{"0.6元/发", 0.6},
|
|
{"6元/60发", 0.1},
|
|
{"2.5元/个", 2.5},
|
|
{"3元/张", 3},
|
|
{"2元", 2},
|
|
{"", 0},
|
|
}
|
|
for _, item := range cases {
|
|
if got := ParseUnitPrice(item.price); math.Abs(got-item.want) > 1e-9 {
|
|
t.Fatalf("ParseUnitPrice(%q)=%v, want %v", item.price, got, item.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConsumablesAndFreeItems(t *testing.T) {
|
|
config := DefaultConfig()
|
|
result := config.Calculate(Input{
|
|
CoinM: 100,
|
|
Insurance: "3*3",
|
|
DailyLossM: 10,
|
|
States: map[string]bool{
|
|
"melee": true,
|
|
"operatorRed": true,
|
|
"staminaMax": true,
|
|
"loadMax": true,
|
|
"weapon": true,
|
|
},
|
|
Quantities: map[string]float64{
|
|
"awmAmmo": 10,
|
|
"helmet6": 2,
|
|
},
|
|
FreeItems: map[string]bool{
|
|
"helmet6": true,
|
|
},
|
|
})
|
|
if result.ItemPrice != 6 {
|
|
t.Fatalf("item price = %v, want 6", result.ItemPrice)
|
|
}
|
|
if result.TotalPrice != 256 {
|
|
t.Fatalf("total price = %v, want 256", result.TotalPrice)
|
|
}
|
|
}
|
|
|
|
func TestGridCardDisabledAtThreeByThree(t *testing.T) {
|
|
config := DefaultConfig()
|
|
result := config.Calculate(Input{
|
|
CoinM: 100,
|
|
Insurance: "3*3",
|
|
DailyLossM: 10,
|
|
Quantities: map[string]float64{"gridCard9": 3},
|
|
})
|
|
if result.ItemPrice != 0 {
|
|
t.Fatalf("item price = %v, want 0", result.ItemPrice)
|
|
}
|
|
for _, item := range result.Items {
|
|
if item.Key == "gridCard9" && !item.Disabled {
|
|
t.Fatal("gridCard9 should be disabled at 3*3")
|
|
}
|
|
}
|
|
|
|
result = config.Calculate(Input{
|
|
CoinM: 100,
|
|
Insurance: "2*3",
|
|
DailyLossM: 10,
|
|
Quantities: map[string]float64{"gridCard9": 3},
|
|
})
|
|
if result.ItemPrice != 9 {
|
|
t.Fatalf("item price at 2*3 = %v, want 9", result.ItemPrice)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeRestoresEmptySections(t *testing.T) {
|
|
normalized := Normalize(Config{})
|
|
if len(normalized.InsuranceBaseRatios) == 0 {
|
|
t.Fatal("insurance ratios should fall back to defaults")
|
|
}
|
|
if len(normalized.RatioConfigItems) == 0 {
|
|
t.Fatal("ratio config items should fall back to defaults")
|
|
}
|
|
if len(normalized.QuantityItems) == 0 {
|
|
t.Fatal("quantity items should fall back to defaults")
|
|
}
|
|
if normalized.AcceleratedMaxRatio != 10 {
|
|
t.Fatalf("accelerated max = %v, want 10", normalized.AcceleratedMaxRatio)
|
|
}
|
|
}
|
|
|
|
func withSaleRatio(input Input, ratio float64) Input {
|
|
input.SaleRatio = ratio
|
|
return input
|
|
}
|