120 lines
4.2 KiB
Go
120 lines
4.2 KiB
Go
package seed
|
||
|
||
import (
|
||
"encoding/json"
|
||
"testing"
|
||
|
||
"github.com/gogf/gf/v2/container/gvar"
|
||
"github.com/gogf/gf/v2/database/gdb"
|
||
|
||
"36wisdom/biz/consts"
|
||
)
|
||
|
||
// gdb.Record = map[string]gdb.Value = map[string]*gvar.Var(gf v2.10.2),字面量一律 gvar.New
|
||
// 构造与 level 1 同构的小树:entry(1) → 决策(2) → best(3)/good(4)/fail(5)
|
||
func testTree() (nodes []gdb.Record, options []gdb.Record) {
|
||
nodes = []gdb.Record{
|
||
{"id": gvar.New(1), "character_id": gvar.New(11), "result_type": gvar.New(0)},
|
||
{"id": gvar.New(2), "character_id": gvar.New(12), "result_type": gvar.New(0)},
|
||
{"id": gvar.New(3), "character_id": gvar.New(12), "result_type": gvar.New(3)},
|
||
{"id": gvar.New(4), "character_id": gvar.New(12), "result_type": gvar.New(2)},
|
||
{"id": gvar.New(5), "character_id": gvar.New(11), "result_type": gvar.New(1)},
|
||
}
|
||
options = []gdb.Record{
|
||
{"id": gvar.New(101), "node_id": gvar.New(1), "prop_id": gvar.New(21), "next_node_id": gvar.New(2), "sort_order": gvar.New(1)},
|
||
{"id": gvar.New(102), "node_id": gvar.New(1), "prop_id": gvar.New(22), "next_node_id": gvar.New(5), "sort_order": gvar.New(2)},
|
||
{"id": gvar.New(103), "node_id": gvar.New(2), "prop_id": gvar.New(21), "next_node_id": gvar.New(3), "sort_order": gvar.New(1)},
|
||
{"id": gvar.New(104), "node_id": gvar.New(2), "prop_id": gvar.New(23), "next_node_id": gvar.New(4), "sort_order": gvar.New(2)},
|
||
{"id": gvar.New(105), "node_id": gvar.New(2), "prop_id": gvar.New(24), "next_node_id": gvar.New(5), "sort_order": gvar.New(3)},
|
||
}
|
||
return
|
||
}
|
||
|
||
func elems() map[int64]string {
|
||
return map[int64]string{11: "小明", 12: "妈妈", 21: "画", 22: "扫帚", 23: "剪刀", 24: "长杆"}
|
||
}
|
||
|
||
func TestPlanInteraction_BestPropAndFailFinal(t *testing.T) {
|
||
nodes, options := testTree()
|
||
p := planInteraction(2, 1, nodes, options, elems())
|
||
if p == nil {
|
||
t.Fatal("应生成互动计划")
|
||
}
|
||
// 正确答案 = 能到达最佳终局(3)的第一个选项(103)的道具 21
|
||
if p.answer != 21 {
|
||
t.Fatalf("正确答案应 21(选项103的道具),实际 %d", p.answer)
|
||
}
|
||
// 失败出口 = 首个失败终局 5
|
||
if p.failFinalID != 5 {
|
||
t.Fatalf("失败终局应 5,实际 %d", p.failFinalID)
|
||
}
|
||
// 道具按选项顺序去重:21,22,23,24
|
||
if len(p.items) != 4 || p.items[0].ID != 21 || p.items[3].ID != 24 {
|
||
t.Fatalf("道具顺序错误: %+v", p.items)
|
||
}
|
||
}
|
||
|
||
func TestPlanInteraction_StepSortReversed(t *testing.T) {
|
||
nodes, options := testTree()
|
||
p := planInteraction(3, 1, nodes, options, elems())
|
||
if len(p.answerOrder) != 4 {
|
||
t.Fatalf("排序应有 4 项,实际 %d", len(p.answerOrder))
|
||
}
|
||
// 正确顺序 = 道具顺序逆序
|
||
if p.answerOrder[0] != 24 || p.answerOrder[3] != 21 {
|
||
t.Fatalf("逆序错误: %v", p.answerOrder)
|
||
}
|
||
}
|
||
|
||
func TestPlanInteraction_LinkMatchPairs(t *testing.T) {
|
||
nodes, options := testTree()
|
||
p := planInteraction(8, 1, nodes, options, elems())
|
||
if p == nil {
|
||
t.Fatal("应生成连线计划")
|
||
}
|
||
// 人物:11(小明)、12(妈妈);小明(节点1)首个带道具选项→扫帚22;妈妈(节点2)→画21
|
||
found := false
|
||
for _, pair := range p.pairs {
|
||
if pair[0] == 11 && pair[1] == 22 {
|
||
found = true
|
||
}
|
||
}
|
||
if !found {
|
||
t.Fatalf("缺少 小明-扫帚 配对: %v", p.pairs)
|
||
}
|
||
}
|
||
|
||
func TestPlanInteraction_FallbackToPropPick(t *testing.T) {
|
||
// 只有 1 个道具 → step_sort 退化为 prop_pick
|
||
nodes, options := testTree()
|
||
options = options[:1]
|
||
p := planInteraction(3, 1, nodes, options, elems())
|
||
if p == nil || p.kind != "prop_pick" {
|
||
t.Fatalf("应退化为 prop_pick,实际 %+v", p)
|
||
}
|
||
}
|
||
|
||
func TestPlanInteraction_NoFailFinalSkipped(t *testing.T) {
|
||
nodes, options := testTree()
|
||
for i := range nodes {
|
||
if nodes[i]["result_type"].Int() == consts.ResultFail {
|
||
nodes[i]["result_type"] = gvar.New(2)
|
||
}
|
||
}
|
||
if p := planInteraction(2, 1, nodes, options, elems()); p != nil {
|
||
t.Fatal("无失败终局应返回 nil(跳过该关)")
|
||
}
|
||
}
|
||
|
||
func TestInteractionConfig_JSON(t *testing.T) {
|
||
p := &interactionPlan{kind: "prop_pick", items: []configItem{{ID: 21, Name: "画"}}, answer: 21, prompt: "选一选"}
|
||
s := interactionConfigJSON(p)
|
||
var m map[string]any
|
||
if err := json.Unmarshal([]byte(s), &m); err != nil {
|
||
t.Fatalf("config 非法 JSON: %v", err)
|
||
}
|
||
if m["kind"] != "prop_pick" || m["answer"] != float64(21) {
|
||
t.Fatalf("config 字段错误: %v", m)
|
||
}
|
||
}
|