优化代码

This commit is contained in:
boyce
2025-10-01 22:26:30 +08:00
parent be0078015f
commit 6511fc4ac0
9 changed files with 411 additions and 93 deletions

View File

@@ -1,19 +1,24 @@
package blueprint
import (
"fmt"
)
type Blueprint struct {
execPool ExecPool
graphPool GraphPool
}
func (bm *Blueprint) Init(execDefFilePath string, graphFilePath string, onRegister func(execPool *ExecPool) error) error {
func (bm *Blueprint) Init(execDefFilePath string, graphFilePath string) error {
err := bm.execPool.Load(execDefFilePath)
if err != nil {
return err
}
err = onRegister(&bm.execPool)
if err != nil {
return err
for _, e := range execNodes {
if !bm.execPool.Register(e) {
return fmt.Errorf("register exec failed,exec:%s", e.GetName())
}
}
err = bm.graphPool.Load(&bm.execPool, graphFilePath)

View File

@@ -1,65 +1,36 @@
package blueprint
import (
"fmt"
"testing"
)
type Entrance_IntParam struct {
BaseExecNode
}
func (em *Entrance_IntParam) GetName() string {
return "Entrance_IntParam"
}
func (em *Entrance_IntParam) Exec() (int, error) {
return 0, nil
}
type Output struct {
BaseExecNode
}
func (em *Output) GetName() string {
return "Output"
}
func (em *Output) Exec() (int, error) {
val, ok := em.GetInPortInt(1)
if !ok {
return 0, fmt.Errorf("Output Exec inParam not found")
}
fmt.Printf("Output Exec inParam %d", val)
return 0, nil
}
func OnRegister(bm *ExecPool) error {
bm.Register(&Entrance_IntParam{})
bm.Register(&Output{})
return nil
}
const (
EntranceID_IntParam = 3
)
func TestExecMgr(t *testing.T) {
//
var bp Blueprint
err := bp.Init("./json/", "./vgf/", OnRegister)
err := bp.Init("D:\\Develop\\OriginNodeEditor\\json", "D:\\Develop\\OriginNodeEditor\\vgf")
if err != nil {
t.Fatalf("init failed,err:%v", err)
}
graphTest2 := bp.Create("test2")
err = graphTest2.Do(EntranceID_IntParam, 1, 2, 3)
graphTest1 := bp.Create("testArray")
err = graphTest1.Do(EntranceID_ArrayParam, 1, []int64{10, 11, 12})
if err != nil {
t.Fatalf("Do EntranceID_IntParam failed,err:%v", err)
}
//graphTest2 := bp.Create("testForeach")
//err = graphTest2.Do(EntranceID_IntParam, 1, 2, 3)
//if err != nil {
// t.Fatalf("Do EntranceID_IntParam failed,err:%v", err)
//}
//graphTest2 := bp.Create("test2")
//
//err = graphTest2.Do(EntranceID_IntParam, 1, 2, 3)
//if err != nil {
// t.Fatalf("Do EntranceID_IntParam failed,err:%v", err)
//}
//graph := bp.Create("test1")
//err = graph.Do(EntranceID_IntParam, 1, 2, 3)
//if err != nil {

View File

@@ -39,11 +39,12 @@ type innerExecNode struct {
Package string
Description string
InPort []IPort
OutPort []IPort
inPort []IPort
outPort []IPort
inPortParamStartIndex int // 输入参数的起始索引,用于排除执行入口
outPortParamStartIndex int // 输出参数的起始索引,用于排除执行出口
IExecNode
}
@@ -82,28 +83,28 @@ type BaseExecConfig struct {
}
func (em *innerExecNode) AppendInPort(port ...IPort) {
if len(em.InPort) == 0 {
if len(em.inPort) == 0 {
em.inPortParamStartIndex = -1
}
for i := 0; i < len(port); i++ {
if !port[i].IsPortExec() && em.inPortParamStartIndex < 0 {
em.inPortParamStartIndex = len(em.InPort)
em.inPortParamStartIndex = len(em.inPort)
}
em.InPort = append(em.InPort, port[i])
em.inPort = append(em.inPort, port[i])
}
}
func (em *innerExecNode) AppendOutPort(port ...IPort) {
if len(em.OutPort) == 0 {
if len(em.outPort) == 0 {
em.outPortParamStartIndex = -1
}
for i := 0; i < len(port); i++ {
if !port[i].IsPortExec() && em.outPortParamStartIndex < 0 {
em.outPortParamStartIndex = len(em.OutPort)
em.outPortParamStartIndex = len(em.outPort)
}
em.OutPort = append(em.OutPort, port[i])
em.outPort = append(em.outPort, port[i])
}
}
@@ -117,7 +118,7 @@ func (em *innerExecNode) SetExec(exec IExecNode) {
func (em *innerExecNode) CloneInOutPort() ([]IPort, []IPort) {
inPorts := make([]IPort, 0, 2)
for _, port := range em.InPort {
for _, port := range em.inPort {
if port.IsPortExec() {
// 执行入口, 不需要克隆,占位处理
inPorts = append(inPorts, nil)
@@ -128,7 +129,7 @@ func (em *innerExecNode) CloneInOutPort() ([]IPort, []IPort) {
}
outPorts := make([]IPort, 0, 2)
for _, port := range em.OutPort {
for _, port := range em.outPort {
if port.IsPortExec() {
outPorts = append(outPorts, nil)
continue
@@ -140,40 +141,40 @@ func (em *innerExecNode) CloneInOutPort() ([]IPort, []IPort) {
}
func (em *innerExecNode) IsInPortExec(index int) bool {
if index >= len(em.InPort) || index < 0 {
if index >= len(em.inPort) || index < 0 {
return false
}
return em.InPort[index].IsPortExec()
return em.inPort[index].IsPortExec()
}
func (em *innerExecNode) IsOutPortExec(index int) bool {
if index >= len(em.OutPort) || index < 0 {
if index >= len(em.outPort) || index < 0 {
return false
}
return em.OutPort[index].IsPortExec()
return em.outPort[index].IsPortExec()
}
func (em *innerExecNode) GetInPortCount() int {
return len(em.InPort)
return len(em.inPort)
}
func (em *innerExecNode) GetOutPortCount() int {
return len(em.OutPort)
return len(em.outPort)
}
func (em *innerExecNode) GetInPort(index int) IPort {
if index >= len(em.InPort) || index < 0 {
if index >= len(em.inPort) || index < 0 {
return nil
}
return em.InPort[index]
return em.inPort[index]
}
func (em *innerExecNode) GetOutPort(index int) IPort {
if index >= len(em.OutPort) || index < 0 {
if index >= len(em.outPort) || index < 0 {
return nil
}
return em.OutPort[index]
return em.outPort[index]
}
func (em *innerExecNode) GetInPortParamStartIndex() int {
@@ -390,7 +391,7 @@ func (en *BaseExecNode) AppendInPortArrayValStr(index int, val Port_Str) bool {
return port.AppendArrayValStr(val)
}
func (en *BaseExecNode) GetInPortArrayLen(index int) int {
func (en *BaseExecNode) GetInPortArrayLen(index int) Port_Int {
port := en.GetInPort(index)
if port == nil {
return 0
@@ -462,7 +463,7 @@ func (en *BaseExecNode) AppendOutPortArrayValStr(index int, val Port_Str) bool {
return port.AppendArrayValStr(val)
}
func (en *BaseExecNode) GetOutPortArrayLen(index int) int {
func (en *BaseExecNode) GetOutPortArrayLen(index int) Port_Int {
port := en.GetOutPort(index)
if port == nil {
return 0

View File

@@ -182,6 +182,7 @@ func (gp *GraphPool) prepareOneNode(mapNodeExec map[string]*execNode, nodeExec *
if nextExecNode == nil {
continue
}
nextExecNode.beConnect = true
nodeExec.nextNode = append(nodeExec.nextNode, nextExecNode)
}
@@ -222,13 +223,14 @@ func (gp *GraphPool) prepareOneEntrance(graphName string, entranceID int64, node
return fmt.Errorf("entrance node %s not found", nodeCfg.Id)
}
nodeExec.isEntrance = true
err = gp.prepareOneNode(mapNodes, nodeExec, graphConfig, new(int))
if err != nil {
return err
}
// 处理inPort前置结点
err = gp.prepareInPort(mapNodes, nodeExec, graphConfig)
err = gp.prepareInPort(mapNodes, graphConfig)
if err != nil {
return err
}
@@ -283,19 +285,10 @@ func (gp *GraphPool) preparePreInPortNode(mapNodes map[string]*execNode, nodeExe
return nil
}
func (gp *GraphPool) prepareInPort(mapNodeExec map[string]*execNode, nodeExec *execNode, graphConfig *graphConfig) error {
for _, nextNode := range nodeExec.nextNode {
if nextNode == nil {
continue
}
// 对nextNode结点的入口进行预处理
err := gp.preparePreInPortNode(mapNodeExec, nextNode, graphConfig)
if err != nil {
return err
}
err = gp.prepareInPort(mapNodeExec, nextNode, graphConfig)
func (gp *GraphPool) prepareInPort(mapNodeExec map[string]*execNode, graphConfig *graphConfig) error {
for _, e := range mapNodeExec {
// 对当前结点的入口进行预处理
err := gp.preparePreInPortNode(mapNodeExec, e, graphConfig)
if err != nil {
return err
}

View File

@@ -1,6 +1,8 @@
package blueprint
import "fmt"
import (
"fmt"
)
type prePortNode struct {
node *execNode // 上个结点
@@ -18,6 +20,23 @@ type execNode struct {
inPortDefaultValue map[string]any
variableName string // 如果是变量,则有变量名
beConnect bool // 是否有被连线
isEntrance bool // 是否是入口结点
}
// HasBeConnectLine 是否有被连线
func (en *execNode) HasBeConnectLine() bool {
return en.beConnect
}
// HasInPortExec 有前置执行入口
func (en *execNode) HasInPortExec() bool {
return en.execNode.IsInPortExec(0)
}
// HasOutPortExec 有前置执行入口
func (en *execNode) HasOutPortExec() bool {
return en.execNode.IsOutPortExec(0)
}
func (en *execNode) GetInPortDefaultValue(index int) any {
@@ -52,6 +71,7 @@ func (en *execNode) exec(gr *Graph) (int, error) {
return -1, err
}
//log.Debug("exec node %s", en.execNode.GetName())
return e.Exec()
}
@@ -67,9 +87,10 @@ func (en *execNode) doSetInPort(gr *Graph, index int, inPort IPort) error {
return nil
}
if _, ok := gr.context[preNode.node.Id]; !ok {
if _, ok := gr.context[preNode.node.Id]; !ok ||
(!preNode.node.HasBeConnectLine() && !preNode.node.isEntrance) {
// 如果前一个结点没有执行过,则递归执行前一个结点
err := preNode.node.Do(gr, nil)
err := preNode.node.Do(gr)
if err != nil {
return err
}

View File

@@ -80,6 +80,13 @@ func (em *Port[T]) GetBool() (Port_Bool, bool) {
return false, false
}
func (em *Port[T]) GetArray() (Port_Array, bool) {
if t, ok := any(em.PortVal).(Port_Array); ok {
return t, true
}
return nil, false
}
func (em *Port[T]) SetInt(val Port_Int) bool {
if t, ok := any(&em.PortVal).(*Port_Int); ok {
*t = val
@@ -148,9 +155,9 @@ func (em *Port[T]) AppendArrayValStr(val Port_Str) bool {
return false
}
func (em *Port[T]) GetArrayLen() int {
func (em *Port[T]) GetArrayLen() Port_Int {
if t, ok := any(&em.PortVal).(*Port_Array); ok {
return len(*t)
return Port_Int(len(*t))
}
return 0
@@ -262,6 +269,51 @@ func (em *Port[T]) setAnyVale(v any) error {
default:
return fmt.Errorf("port type is %T, but value is %v", em.PortVal, v)
}
case []int64:
arr := v.([]int64)
for _, val := range arr {
em.AppendArrayValInt(val)
}
case []int32:
arr := v.([]int32)
for _, val := range arr {
em.AppendArrayValInt(Port_Int(val))
}
case []int16:
arr := v.([]int16)
for _, val := range arr {
em.AppendArrayValInt(Port_Int(val))
}
case []int8:
arr := v.([]int8)
for _, val := range arr {
em.AppendArrayValInt(Port_Int(val))
}
case []uint64:
arr := v.([]uint64)
for _, val := range arr {
em.AppendArrayValInt(Port_Int(val))
}
case []uint32:
arr := v.([]uint32)
for _, val := range arr {
em.AppendArrayValInt(Port_Int(val))
}
case []uint16:
arr := v.([]uint16)
for _, val := range arr {
em.AppendArrayValInt(Port_Int(val))
}
case []uint8:
arr := v.([]uint8)
for _, val := range arr {
em.AppendArrayValInt(Port_Int(val))
}
case []string:
arr := v.([]string)
for _, val := range arr {
em.AppendArrayValStr(val)
}
}
return nil
@@ -283,6 +335,7 @@ type IPort interface {
GetArrayValInt(idx int) (Port_Int, bool)
GetArrayValStr(idx int) (Port_Str, bool)
GetBool() (Port_Bool, bool)
GetArray() (Port_Array, bool)
SetInt(val Port_Int) bool
SetFloat(val Port_Float) bool
@@ -292,7 +345,7 @@ type IPort interface {
SetArrayValStr(idx int, val Port_Str) bool
AppendArrayValInt(val Port_Int) bool
AppendArrayValStr(val Port_Str) bool
GetArrayLen() int
GetArrayLen() Port_Int
Clone() IPort
Reset()

View File

@@ -0,0 +1,7 @@
package blueprint
var execNodes []IExecNode
func RegExecNode(exec IExecNode) {
execNodes = append(execNodes, exec)
}

226
util/blueprint/sysnodes.go Normal file
View File

@@ -0,0 +1,226 @@
package blueprint
import (
"fmt"
"github.com/duanhf2012/origin/v2/log"
)
// 系统入口ID定义1000以内
const (
EntranceID_ArrayParam = 2
EntranceID_IntParam = 3
)
func init() {
RegExecNode(&Entrance_ArrayParam{})
RegExecNode(&Entrance_IntParam{})
RegExecNode(&Output{})
RegExecNode(&Sequence{})
RegExecNode(&Foreach{})
RegExecNode(&GetArrayInt{})
RegExecNode(&GetArrayString{})
RegExecNode(&GetArrayLen{})
}
type Entrance_ArrayParam struct {
BaseExecNode
}
func (em *Entrance_ArrayParam) GetName() string {
return "Entrance_ArrayParam"
}
func (em *Entrance_ArrayParam) Exec() (int, error) {
return 0, nil
}
type Entrance_IntParam struct {
BaseExecNode
}
func (em *Entrance_IntParam) GetName() string {
return "Entrance_IntParam"
}
func (em *Entrance_IntParam) Exec() (int, error) {
return 0, nil
}
type Output struct {
BaseExecNode
}
func (em *Output) GetName() string {
return "Output"
}
func (em *Output) Exec() (int, error) {
val, ok := em.GetInPortInt(1)
if !ok {
return 0, fmt.Errorf("Output Exec inParam not found")
}
fmt.Printf("Output Exec inParam %d", val)
return 0, nil
}
type Sequence struct {
BaseExecNode
}
func (em *Sequence) GetName() string {
return "Sequence"
}
func (em *Sequence) Exec() (int, error) {
for i := range em.outPort {
if !em.outPort[i].IsPortExec() {
break
}
err := em.DoNext(i)
if err != nil {
return -1, err
}
}
return -1, nil
}
type Foreach struct {
BaseExecNode
}
func (em *Foreach) GetName() string {
return "Foreach"
}
func (em *Foreach) Exec() (int, error) {
startIndex, ok := em.ExecContext.InputPorts[1].GetInt()
if !ok {
return 0, fmt.Errorf("foreach Exec inParam not found")
}
endIndex, ok := em.ExecContext.InputPorts[2].GetInt()
if !ok {
return 0, fmt.Errorf("foreach Exec inParam not found")
}
for i := startIndex; i < endIndex; i++ {
em.ExecContext.OutputPorts[2].SetInt(i)
err := em.DoNext(0)
if err != nil {
return -1, err
}
}
err := em.DoNext(1)
if err != nil {
return -1, err
}
return -1, nil
}
type GetArrayInt struct {
BaseExecNode
}
func (em *GetArrayInt) GetName() string {
return "GetArrayInt"
}
func (em *GetArrayInt) Exec() (int, error) {
inPort := em.GetInPort(0)
if inPort == nil {
return -1, fmt.Errorf("GetArrayInt inParam not found")
}
outPort := em.GetOutPort(0)
if outPort == nil {
return -1, fmt.Errorf("GetArrayInt outParam not found")
}
arrIndexPort := em.GetInPort(1)
if arrIndexPort == nil {
return -1, fmt.Errorf("GetArrayInt arrIndexParam not found")
}
arrIndex, ok := arrIndexPort.GetInt()
if !ok {
return -1, fmt.Errorf("GetArrayInt arrIndexParam not found")
}
if arrIndex < 0 || arrIndex >= inPort.GetArrayLen() {
return -1, fmt.Errorf("GetArrayInt arrIndexParam out of range,index %d", arrIndex)
}
val, ok := inPort.GetArrayValInt(int(arrIndex))
if !ok {
log.Errorf("GetArrayValInt failed, idx:%d", arrIndex)
return -1, fmt.Errorf("GetArrayInt inParam not found")
}
outPort.SetInt(val)
return -1, nil
}
type GetArrayString struct {
BaseExecNode
}
func (em *GetArrayString) GetName() string {
return "GetArrayString"
}
func (em *GetArrayString) Exec() (int, error) {
inPort := em.GetInPort(0)
if inPort == nil {
return -1, fmt.Errorf("GetArrayInt inParam not found")
}
outPort := em.GetOutPort(0)
if outPort == nil {
return -1, fmt.Errorf("GetArrayInt outParam not found")
}
arrIndexPort := em.GetInPort(1)
if arrIndexPort == nil {
return -1, fmt.Errorf("GetArrayInt arrIndexParam not found")
}
arrIndex, ok := arrIndexPort.GetInt()
if !ok {
return -1, fmt.Errorf("GetArrayInt arrIndexParam not found")
}
if arrIndex < 0 || arrIndex >= inPort.GetArrayLen() {
return -1, fmt.Errorf("GetArrayInt arrIndexParam out of range,index %d", arrIndex)
}
val, ok := inPort.GetArrayValStr(int(arrIndex))
if !ok {
log.Errorf("GetArrayValStr failed, idx:%d", arrIndex)
return -1, fmt.Errorf("GetArrayInt inParam not found")
}
outPort.SetStr(val)
return -1, nil
}
type GetArrayLen struct {
BaseExecNode
}
func (em *GetArrayLen) GetName() string {
return "GetArrayLen"
}
func (em *GetArrayLen) Exec() (int, error) {
inPort := em.GetInPort(0)
if inPort == nil {
return -1, fmt.Errorf("GetArrayInt inParam not found")
}
outPort := em.GetOutPort(0)
if outPort == nil {
return -1, fmt.Errorf("GetArrayInt outParam not found")
}
outPort.SetInt(inPort.GetArrayLen())
return -1, nil
}

41
util/stack/stack.go Normal file
View File

@@ -0,0 +1,41 @@
package stack
// Stack 是一个通用类型的栈结构
type Stack[T any] struct {
items []*T
}
// Push 将元素压入栈顶
func (s *Stack[T]) Push(item *T) {
s.items = append(s.items, item)
}
// Pop 弹出并返回栈顶元素,如果栈为空则返回错误
func (s *Stack[T]) Pop() *T {
if len(s.items) == 0 {
return nil
}
index := len(s.items) - 1
item := s.items[index]
s.items = s.items[:index]
return item
}
// Peek 返回栈顶元素但不移除,如果栈为空则返回错误
func (s *Stack[T]) Peek() *T {
if len(s.items) == 0 {
return nil
}
return s.items[len(s.items)-1]
}
// IsEmpty 检查栈是否为空
func (s *Stack[T]) IsEmpty() bool {
return len(s.items) == 0
}
// Size 返回栈中元素的数量
func (s *Stack[T]) Size() int {
return len(s.items)
}