From 4a910aa08fb3cf5a584aa6b91d72042eceef900a Mon Sep 17 00:00:00 2001 From: joylink_zhangsai <1021828630@qq.com> Date: Wed, 20 Sep 2023 15:14:38 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E5=AD=98=E5=82=A8Proto?= =?UTF-8?q?=E7=9A=84Message=EF=BC=9B=E5=88=9B=E5=BB=BA=E4=BB=BF=E7=9C=9F?= =?UTF-8?q?=E6=97=B6=E7=94=B1=E4=BB=BF=E7=9C=9F=E6=A8=A1=E5=9D=97=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E6=A8=A1=E5=9E=8B=EF=BC=9B=E5=8F=91=E7=BB=99=E5=8A=A8?= =?UTF-8?q?=E5=8A=9B=E5=AD=A6=E7=9A=84=E6=95=B0=E6=8D=AE=E4=BB=8E=E4=BB=BF?= =?UTF-8?q?=E7=9C=9F=E6=A8=A1=E5=9D=97=E8=BF=94=E5=9B=9E=E7=9A=84Repositor?= =?UTF-8?q?y=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/basic/main.go | 27 - go.mod | 7 +- go.sum | 4 +- go.work | 2 +- go.work.sum | 1 + jl-ecs-go | 2 +- proto/src/model.proto | 18 +- repository/Transponder.go | 7 +- repository/check_point.go | 11 +- repository/link.go | 200 +++--- repository/model/proto/model.pb.go | 386 +++++++--- repository/physical_section.go | 22 +- repository/repository.go | 141 ++-- repository/repository_builder.go | 336 --------- repository/repository_manager.go | 661 ++++++++++++++++++ ...der_test.go => repository_manager_test.go} | 0 repository/responder.go | 26 - repository/sectional_curvature.go | 26 +- repository/signal.go | 5 + repository/simulation.go | 387 ---------- repository/slope.go | 26 +- repository/turnout.go | 18 +- simulation/simulation.go | 41 ++ util/{ => number}/number.go | 16 +- 24 files changed, 1352 insertions(+), 1018 deletions(-) delete mode 100644 examples/basic/main.go delete mode 100644 repository/repository_builder.go create mode 100644 repository/repository_manager.go rename repository/{repository_builder_test.go => repository_manager_test.go} (100%) delete mode 100644 repository/responder.go delete mode 100644 repository/simulation.go create mode 100644 simulation/simulation.go rename util/{ => number}/number.go (67%) diff --git a/examples/basic/main.go b/examples/basic/main.go deleted file mode 100644 index b3deabe..0000000 --- a/examples/basic/main.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "joylink.club/rtsssimulation/repository" - "joylink.club/rtsssimulation/repository/model/proto" -) - -var Repo *repository.Repository - -func main() { - link := repository.NewLink("1") - fmt.Println(link) - - lp := repository.NewLinkPort(link, proto.Port_A) - fmt.Println(lp) - - Repo = repository.NewRepository("1" /* id */, "0.1" /* version */) - section := repository.NewPhysicalSection("s1") - fmt.Println(section) - Repo.AddPhysicalSection(section) - fmt.Println(Repo) - - time.Sleep(5 * time.Second) -} diff --git a/go.mod b/go.mod index 5ac4ba1..f826feb 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,9 @@ module joylink.club/rtsssimulation go 1.20 -require google.golang.org/protobuf v1.31.0 +require ( + github.com/yohamta/donburi v1.3.8 + google.golang.org/protobuf v1.31.0 +) + +require github.com/google/go-cmp v0.5.9 // indirect diff --git a/go.sum b/go.sum index 9ea5597..86078e1 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/yohamta/donburi v1.3.8 h1:ca4NuhzJ8Jeb6GAEf6ecksa+l8JWaAnr0WLqG20TimU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= diff --git a/go.work b/go.work index e224206..6673469 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,6 @@ go 1.20 use ( - ./jl-ecs-go . + ./jl-ecs-go ) diff --git a/go.work.sum b/go.work.sum index 0b43fb7..98d8516 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,6 +1,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/ebitengine/purego v0.1.0/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hajimehoshi/ebiten/v2 v2.4.13/go.mod h1:BZcqCU4XHmScUi+lsKexocWcf4offMFwfp8dVGIB/G4= github.com/hajimehoshi/file2byteslice v1.0.0/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE= github.com/jezek/xgb v1.0.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= diff --git a/jl-ecs-go b/jl-ecs-go index adb9cf9..c3b9d96 160000 --- a/jl-ecs-go +++ b/jl-ecs-go @@ -1 +1 @@ -Subproject commit adb9cf9a0005fc74565da8753f4f7577834d27d4 +Subproject commit c3b9d965c607a2f29e0bdc586aba6851d4f29f13 diff --git a/proto/src/model.proto b/proto/src/model.proto index c1c4523..647ea63 100644 --- a/proto/src/model.proto +++ b/proto/src/model.proto @@ -35,11 +35,18 @@ message CheckPoint{ //道岔 message Turnout { + enum SwitchMachineType { + Unknown = 0; + ZDJ9_Single = 1; + ZDJ9_Double = 2; + } string id = 1; Kilometer km = 2; DevicePort aDevicePort = 3; DevicePort bDevicePort = 4; DevicePort cDevicePort = 5; + SwitchMachineType switchMachineType = 6; + repeated string relayIds = 7; //道岔关联的继电器 } //信号机 @@ -85,7 +92,7 @@ enum DeviceType { DeviceType_CheckPoint = 2; DeviceType_Turnout = 3; DeviceType_Signal = 4; - DeviceType_Responder = 5; + DeviceType_Transponder = 5; DeviceType_Slope = 6; DeviceType_SectionalCurvature = 7; DeviceType_Link = 8; @@ -124,4 +131,13 @@ enum CheckPointType{ Boundary = 0; //区段边界 AxleCounter = 1; //计轴器 InsulatedJoint = 2; //绝缘节 +} + +message Relay { + enum Type { + Unknown = 0; + } + string id = 1; + string code = 2; + Type type = 3; } \ No newline at end of file diff --git a/repository/Transponder.go b/repository/Transponder.go index 5c37a46..b292d30 100644 --- a/repository/Transponder.go +++ b/repository/Transponder.go @@ -8,15 +8,20 @@ type Transponder struct { km *proto.Kilometer //section *PhysicalSection //turnoutPort TurnoutPort + linkPosition *LinkPosition } func NewTransponder(id string, km *proto.Kilometer) *Transponder { return &Transponder{ - Identity: identity{id, proto.DeviceType_DeviceType_Responder}, + Identity: identity{id, proto.DeviceType_DeviceType_Transponder}, km: km, } } +func (t *Transponder) bindLinkPosition(position *LinkPosition) { + t.linkPosition = position +} + //func (r *Transponder) bindSection(section *PhysicalSection) { // r.section = section //} diff --git a/repository/check_point.go b/repository/check_point.go index a4575fa..40a2aa0 100644 --- a/repository/check_point.go +++ b/repository/check_point.go @@ -6,9 +6,10 @@ import "joylink.club/rtsssimulation/repository/model/proto" type CheckPoint struct { Identity - km *proto.Kilometer - pointType proto.CheckPointType //检测点类型 - devicePorts []DevicePort //检测点关联的设备及其端口 + km *proto.Kilometer + pointType proto.CheckPointType //检测点类型 + devicePorts []DevicePort //检测点关联的设备及其端口 + linkPosition *LinkPosition } func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointType) *CheckPoint { @@ -22,3 +23,7 @@ func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointTyp func (c *CheckPoint) bindDevicePort(devicePort DevicePort) { c.devicePorts = append(c.devicePorts, devicePort) } + +func (c *CheckPoint) bindLinkPosition(position *LinkPosition) { + c.linkPosition = position +} diff --git a/repository/link.go b/repository/link.go index 910891e..c44863b 100644 --- a/repository/link.go +++ b/repository/link.go @@ -11,14 +11,17 @@ type Link struct { length int64 - aRelation *LinkNodePort - bRelation *LinkNodePort + aRelation *TurnoutPort + bRelation *TurnoutPort aKm *proto.Kilometer bKm *proto.Kilometer - //Link关联的模型,包含LinkNode - devicePositions []*DeviceLinkPosition + //Link上的模型((非区段边界)检测点、应答器、信号机、区段(为了位置换算方便)) + devices []Identity + + ////Link关联的模型,包含LinkNode + //devicePositions []*DeviceLinkPosition } var _ Identity = &Link{} @@ -29,23 +32,40 @@ func NewLink(id string) *Link { } } +func (l *Link) Length() int64 { + return l.length +} + +func (l *Link) ARelation() *TurnoutPort { + return l.aRelation +} + +func (l *Link) BRelation() *TurnoutPort { + return l.bRelation +} + +func (l *Link) Devices() []Identity { + return l.devices +} + func (l *Link) PortNum() int { return 2 } func (l *Link) bindDevicePort(port proto.Port, devicePort DevicePort) error { - linkNodePort, isLinkNodePort := devicePort.(*LinkNodePort) - if !isLinkNodePort { + turnoutPort, isTurnoutPort := devicePort.(*TurnoutPort) + if !isTurnoutPort { return errors.New(fmt.Sprintf("Link不能与[%s]类型的设备关联", devicePort.Device().Type())) } switch port { case proto.Port_A: - l.aRelation = linkNodePort + l.aRelation = turnoutPort case proto.Port_B: - l.bRelation = linkNodePort + l.bRelation = turnoutPort default: return errors.New(fmt.Sprintf("Link没有端口[%s]", port)) } + l.bindKm(turnoutPort.turnout.km, port) return nil } @@ -58,9 +78,9 @@ func (l *Link) bindKm(km *proto.Kilometer, port proto.Port) { } } -func (l *Link) bindDevicesLinkPositions(dlps ...*DeviceLinkPosition) { - for _, dlp := range dlps { - l.devicePositions = append(l.devicePositions, dlp) +func (l *Link) bindDevices(devices ...Identity) { + for _, device := range devices { + l.devices = append(l.devices, device) } } @@ -91,58 +111,12 @@ type LinkPosition struct { offset int64 } -// DeviceLinkPosition device在link上的位置 -type DeviceLinkPosition struct { - device Identity - position LinkPosition +func (l *LinkPosition) Link() *Link { + return l.link } -// SlopeLinkSegment Slope在Link上的区间 -type SlopeLinkSegment struct { - slope *Slope - start *LinkPosition - end *LinkPosition -} - -type SectionalCurvatureLinkSegment struct { - sectionalCurvature *SectionalCurvature - start *LinkPosition - end *LinkPosition -} - -// LinkNode link节点 -type LinkNode struct { - Identity - turnout *Turnout - aRelation LinkPort - bRelation LinkPort - cRelation LinkPort -} - -func (ln LinkNode) Id() string { - return ln.turnout.Id() -} - -func (ln LinkNode) PortNum() int { - return 3 -} - -func (ln LinkNode) bindDevicePort(port proto.Port, devicePort DevicePort) error { - linkPort, isLinkPort := devicePort.(*LinkPort) - if !isLinkPort { - return errors.New(fmt.Sprintf("Link节点不能与[%s]类型的设备关联", devicePort.Device().Type())) - } - switch port { - case proto.Port_A: - ln.aRelation = *linkPort - case proto.Port_B: - ln.bRelation = *linkPort - case proto.Port_C: - ln.cRelation = *linkPort - default: - return errors.New(fmt.Sprintf("Link节点没有端口[%s]", port)) - } - return nil +func (l *LinkPosition) Offset() int64 { + return l.offset } // link端口 @@ -166,22 +140,88 @@ func (l *LinkPort) Device() PortedDevice { return l.link } -type LinkNodePort struct { - node *LinkNode - port proto.Port -} - -func NewLinkNodePort(node *LinkNode, port proto.Port) *LinkNodePort { - return &LinkNodePort{ - node: node, - port: port, - } -} - -func (lp *LinkNodePort) Port() proto.Port { - return lp.port -} - -func (lp *LinkNodePort) Device() PortedDevice { - return lp.node -} +//// DeviceLinkPosition device在link上的位置 +//type DeviceLinkPosition struct { +// device Identity +// position LinkPosition +//} +// +//// SlopeLinkSegment Slope在Link上的区间 +//type SlopeLinkSegment struct { +// slope *Slope +// start *LinkPosition +// end *LinkPosition +//} +// +//func (s *SlopeLinkSegment) Slope() *Slope { +// return s.slope +//} +// +//func (s *SlopeLinkSegment) Start() *LinkPosition { +// return s.start +//} +// +//func (s *SlopeLinkSegment) End() *LinkPosition { +// return s.end +//} +// +//type SectionalCurvatureLinkSegment struct { +// sectionalCurvature *SectionalCurvature +// start *LinkPosition +// end *LinkPosition +//} +// +//// LinkNode link节点 +//type LinkNode struct { +// Identity +// turnout *Turnout +// aRelation LinkPort +// bRelation LinkPort +// cRelation LinkPort +//} +// +//func (ln LinkNode) Id() string { +// return ln.turnout.Id() +//} +// +//func (ln LinkNode) PortNum() int { +// return 3 +//} +// +//func (ln LinkNode) bindDevicePort(port proto.Port, devicePort DevicePort) error { +// linkPort, isLinkPort := devicePort.(*LinkPort) +// if !isLinkPort { +// return errors.New(fmt.Sprintf("Link节点不能与[%s]类型的设备关联", devicePort.Device().Type())) +// } +// switch port { +// case proto.Port_A: +// ln.aRelation = *linkPort +// case proto.Port_B: +// ln.bRelation = *linkPort +// case proto.Port_C: +// ln.cRelation = *linkPort +// default: +// return errors.New(fmt.Sprintf("Link节点没有端口[%s]", port)) +// } +// return nil +//} +// +//type LinkNodePort struct { +// node *LinkNode +// port proto.Port +//} +// +//func NewLinkNodePort(node *LinkNode, port proto.Port) *LinkNodePort { +// return &LinkNodePort{ +// node: node, +// port: port, +// } +//} +// +//func (lp *LinkNodePort) Port() proto.Port { +// return lp.port +//} +// +//func (lp *LinkNodePort) Device() PortedDevice { +// return lp.node +//} diff --git a/repository/model/proto/model.pb.go b/repository/model/proto/model.pb.go index 19de8bd..ebfbbe7 100644 --- a/repository/model/proto/model.pb.go +++ b/repository/model/proto/model.pb.go @@ -28,7 +28,7 @@ const ( DeviceType_DeviceType_CheckPoint DeviceType = 2 DeviceType_DeviceType_Turnout DeviceType = 3 DeviceType_DeviceType_Signal DeviceType = 4 - DeviceType_DeviceType_Responder DeviceType = 5 + DeviceType_DeviceType_Transponder DeviceType = 5 DeviceType_DeviceType_Slope DeviceType = 6 DeviceType_DeviceType_SectionalCurvature DeviceType = 7 DeviceType_DeviceType_Link DeviceType = 8 @@ -43,7 +43,7 @@ var ( 2: "DeviceType_CheckPoint", 3: "DeviceType_Turnout", 4: "DeviceType_Signal", - 5: "DeviceType_Responder", + 5: "DeviceType_Transponder", 6: "DeviceType_Slope", 7: "DeviceType_SectionalCurvature", 8: "DeviceType_Link", @@ -55,7 +55,7 @@ var ( "DeviceType_CheckPoint": 2, "DeviceType_Turnout": 3, "DeviceType_Signal": 4, - "DeviceType_Responder": 5, + "DeviceType_Transponder": 5, "DeviceType_Slope": 6, "DeviceType_SectionalCurvature": 7, "DeviceType_Link": 8, @@ -239,6 +239,98 @@ func (CheckPointType) EnumDescriptor() ([]byte, []int) { return file_model_proto_rawDescGZIP(), []int{3} } +type Turnout_SwitchMachineType int32 + +const ( + Turnout_Unknown Turnout_SwitchMachineType = 0 + Turnout_ZDJ9_Single Turnout_SwitchMachineType = 1 + Turnout_ZDJ9_Double Turnout_SwitchMachineType = 2 +) + +// Enum value maps for Turnout_SwitchMachineType. +var ( + Turnout_SwitchMachineType_name = map[int32]string{ + 0: "Unknown", + 1: "ZDJ9_Single", + 2: "ZDJ9_Double", + } + Turnout_SwitchMachineType_value = map[string]int32{ + "Unknown": 0, + "ZDJ9_Single": 1, + "ZDJ9_Double": 2, + } +) + +func (x Turnout_SwitchMachineType) Enum() *Turnout_SwitchMachineType { + p := new(Turnout_SwitchMachineType) + *p = x + return p +} + +func (x Turnout_SwitchMachineType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Turnout_SwitchMachineType) Descriptor() protoreflect.EnumDescriptor { + return file_model_proto_enumTypes[4].Descriptor() +} + +func (Turnout_SwitchMachineType) Type() protoreflect.EnumType { + return &file_model_proto_enumTypes[4] +} + +func (x Turnout_SwitchMachineType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Turnout_SwitchMachineType.Descriptor instead. +func (Turnout_SwitchMachineType) EnumDescriptor() ([]byte, []int) { + return file_model_proto_rawDescGZIP(), []int{3, 0} +} + +type Relay_Type int32 + +const ( + Relay_Unknown Relay_Type = 0 +) + +// Enum value maps for Relay_Type. +var ( + Relay_Type_name = map[int32]string{ + 0: "Unknown", + } + Relay_Type_value = map[string]int32{ + "Unknown": 0, + } +) + +func (x Relay_Type) Enum() *Relay_Type { + p := new(Relay_Type) + *p = x + return p +} + +func (x Relay_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Relay_Type) Descriptor() protoreflect.EnumDescriptor { + return file_model_proto_enumTypes[5].Descriptor() +} + +func (Relay_Type) Type() protoreflect.EnumType { + return &file_model_proto_enumTypes[5] +} + +func (x Relay_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Relay_Type.Descriptor instead. +func (Relay_Type) EnumDescriptor() ([]byte, []int) { + return file_model_proto_rawDescGZIP(), []int{11, 0} +} + type Repository struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -508,11 +600,13 @@ type Turnout struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Km *Kilometer `protobuf:"bytes,2,opt,name=km,proto3" json:"km,omitempty"` - ADevicePort *DevicePort `protobuf:"bytes,3,opt,name=aDevicePort,proto3" json:"aDevicePort,omitempty"` - BDevicePort *DevicePort `protobuf:"bytes,4,opt,name=bDevicePort,proto3" json:"bDevicePort,omitempty"` - CDevicePort *DevicePort `protobuf:"bytes,5,opt,name=cDevicePort,proto3" json:"cDevicePort,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Km *Kilometer `protobuf:"bytes,2,opt,name=km,proto3" json:"km,omitempty"` + ADevicePort *DevicePort `protobuf:"bytes,3,opt,name=aDevicePort,proto3" json:"aDevicePort,omitempty"` + BDevicePort *DevicePort `protobuf:"bytes,4,opt,name=bDevicePort,proto3" json:"bDevicePort,omitempty"` + CDevicePort *DevicePort `protobuf:"bytes,5,opt,name=cDevicePort,proto3" json:"cDevicePort,omitempty"` + SwitchMachineType Turnout_SwitchMachineType `protobuf:"varint,6,opt,name=switchMachineType,proto3,enum=model.Turnout_SwitchMachineType" json:"switchMachineType,omitempty"` + RelayIds []string `protobuf:"bytes,7,rep,name=relayIds,proto3" json:"relayIds,omitempty"` //道岔关联的继电器 } func (x *Turnout) Reset() { @@ -582,6 +676,20 @@ func (x *Turnout) GetCDevicePort() *DevicePort { return nil } +func (x *Turnout) GetSwitchMachineType() Turnout_SwitchMachineType { + if x != nil { + return x.SwitchMachineType + } + return Turnout_Unknown +} + +func (x *Turnout) GetRelayIds() []string { + if x != nil { + return x.RelayIds + } + return nil +} + // 信号机 type Signal struct { state protoimpl.MessageState @@ -1046,6 +1154,69 @@ func (x *KilometerConvert) GetSameTrend() bool { return false } +type Relay struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` + Type Relay_Type `protobuf:"varint,3,opt,name=type,proto3,enum=model.Relay_Type" json:"type,omitempty"` +} + +func (x *Relay) Reset() { + *x = Relay{} + if protoimpl.UnsafeEnabled { + mi := &file_model_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Relay) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Relay) ProtoMessage() {} + +func (x *Relay) ProtoReflect() protoreflect.Message { + mi := &file_model_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Relay.ProtoReflect.Descriptor instead. +func (*Relay) Descriptor() ([]byte, []int) { + return file_model_proto_rawDescGZIP(), []int{11} +} + +func (x *Relay) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Relay) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *Relay) GetType() Relay_Type { + if x != nil { + return x.Type + } + return Relay_Unknown +} + var File_model_proto protoreflect.FileDescriptor var file_model_proto_rawDesc = []byte{ @@ -1102,7 +1273,7 @@ var file_model_proto_rawDesc = []byte{ 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x52, - 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x22, 0xda, 0x01, 0x0a, + 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x22, 0x8a, 0x03, 0x0a, 0x07, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x75, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x02, 0x6b, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69, 0x6c, @@ -1116,7 +1287,18 @@ var file_model_proto_rawDesc = []byte{ 0x50, 0x6f, 0x72, 0x74, 0x12, 0x33, 0x0a, 0x0b, 0x63, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0b, 0x63, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x8d, 0x01, 0x0a, 0x06, 0x53, 0x69, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x77, 0x69, + 0x74, 0x63, 0x68, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x54, 0x75, 0x72, + 0x6e, 0x6f, 0x75, 0x74, 0x2e, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x4d, 0x61, 0x63, 0x68, 0x69, + 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x11, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x4d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, + 0x61, 0x79, 0x49, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, + 0x61, 0x79, 0x49, 0x64, 0x73, 0x22, 0x42, 0x0a, 0x11, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x4d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, + 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x5a, 0x44, 0x4a, 0x39, 0x5f, + 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x5a, 0x44, 0x4a, 0x39, + 0x5f, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x22, 0x8d, 0x01, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x02, 0x6b, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, @@ -1169,35 +1351,42 @@ var file_model_proto_rawDesc = []byte{ 0x42, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x6d, 0x42, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x2a, 0x8f, 0x02, 0x0a, - 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, - 0x6e, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x5f, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x5f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x16, - 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x75, 0x72, - 0x6e, 0x6f, 0x75, 0x74, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x10, 0x04, 0x12, 0x18, 0x0a, - 0x14, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x6c, 0x6f, 0x70, 0x65, 0x10, 0x06, 0x12, 0x21, 0x0a, - 0x1d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x75, 0x72, 0x76, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x07, - 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, - 0x69, 0x6e, 0x6b, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x10, 0x09, 0x2a, 0x25, - 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, - 0x12, 0x05, 0x0a, 0x01, 0x41, 0x10, 0x01, 0x12, 0x05, 0x0a, 0x01, 0x42, 0x10, 0x02, 0x12, 0x05, - 0x0a, 0x01, 0x43, 0x10, 0x03, 0x2a, 0x20, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x45, 0x46, 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, - 0x52, 0x49, 0x47, 0x48, 0x54, 0x10, 0x01, 0x2a, 0x43, 0x0a, 0x0e, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x6f, 0x75, - 0x6e, 0x64, 0x61, 0x72, 0x79, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x78, 0x6c, 0x65, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x75, - 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x42, 0x1a, 0x5a, 0x18, - 0x2e, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x6f, 0x64, - 0x65, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x08, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x22, 0x67, 0x0a, 0x05, + 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, + 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x22, 0x13, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x2a, 0x91, 0x02, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x68, 0x79, 0x73, 0x69, + 0x63, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x75, 0x74, 0x10, 0x03, 0x12, + 0x15, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x6c, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, + 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x5f, 0x53, 0x6c, 0x6f, 0x70, 0x65, 0x10, 0x06, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x43, 0x75, 0x72, 0x76, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0x08, + 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, + 0x69, 0x6e, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x10, 0x09, 0x2a, 0x25, 0x0a, 0x04, 0x50, 0x6f, 0x72, + 0x74, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x41, + 0x10, 0x01, 0x12, 0x05, 0x0a, 0x01, 0x42, 0x10, 0x02, 0x12, 0x05, 0x0a, 0x01, 0x43, 0x10, 0x03, + 0x2a, 0x20, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, + 0x04, 0x4c, 0x45, 0x46, 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x49, 0x47, 0x48, 0x54, + 0x10, 0x01, 0x2a, 0x43, 0x0a, 0x0e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, + 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x78, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, + 0x72, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, + 0x4a, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x42, 0x1a, 0x5a, 0x18, 0x2e, 0x2f, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1212,59 +1401,64 @@ func file_model_proto_rawDescGZIP() []byte { return file_model_proto_rawDescData } -var file_model_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_model_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_model_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +var file_model_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_model_proto_goTypes = []interface{}{ - (DeviceType)(0), // 0: model.DeviceType - (Port)(0), // 1: model.Port - (Direction)(0), // 2: model.Direction - (CheckPointType)(0), // 3: model.CheckPointType - (*Repository)(nil), // 4: model.Repository - (*PhysicalSection)(nil), // 5: model.PhysicalSection - (*CheckPoint)(nil), // 6: model.CheckPoint - (*Turnout)(nil), // 7: model.Turnout - (*Signal)(nil), // 8: model.Signal - (*Transponder)(nil), // 9: model.Transponder - (*Slope)(nil), // 10: model.Slope - (*SectionalCurvature)(nil), // 11: model.SectionalCurvature - (*DevicePort)(nil), // 12: model.DevicePort - (*Kilometer)(nil), // 13: model.Kilometer - (*KilometerConvert)(nil), // 14: model.KilometerConvert + (DeviceType)(0), // 0: model.DeviceType + (Port)(0), // 1: model.Port + (Direction)(0), // 2: model.Direction + (CheckPointType)(0), // 3: model.CheckPointType + (Turnout_SwitchMachineType)(0), // 4: model.Turnout.SwitchMachineType + (Relay_Type)(0), // 5: model.Relay.Type + (*Repository)(nil), // 6: model.Repository + (*PhysicalSection)(nil), // 7: model.PhysicalSection + (*CheckPoint)(nil), // 8: model.CheckPoint + (*Turnout)(nil), // 9: model.Turnout + (*Signal)(nil), // 10: model.Signal + (*Transponder)(nil), // 11: model.Transponder + (*Slope)(nil), // 12: model.Slope + (*SectionalCurvature)(nil), // 13: model.SectionalCurvature + (*DevicePort)(nil), // 14: model.DevicePort + (*Kilometer)(nil), // 15: model.Kilometer + (*KilometerConvert)(nil), // 16: model.KilometerConvert + (*Relay)(nil), // 17: model.Relay } var file_model_proto_depIdxs = []int32{ - 5, // 0: model.Repository.physicalSections:type_name -> model.PhysicalSection - 6, // 1: model.Repository.checkPoints:type_name -> model.CheckPoint - 7, // 2: model.Repository.turnouts:type_name -> model.Turnout - 8, // 3: model.Repository.signals:type_name -> model.Signal - 9, // 4: model.Repository.transponders:type_name -> model.Transponder - 10, // 5: model.Repository.slopes:type_name -> model.Slope - 11, // 6: model.Repository.sectionalCurvatures:type_name -> model.SectionalCurvature - 14, // 7: model.Repository.kilometerConverts:type_name -> model.KilometerConvert - 12, // 8: model.PhysicalSection.aDevicePort:type_name -> model.DevicePort - 12, // 9: model.PhysicalSection.bDevicePort:type_name -> model.DevicePort - 13, // 10: model.CheckPoint.km:type_name -> model.Kilometer + 7, // 0: model.Repository.physicalSections:type_name -> model.PhysicalSection + 8, // 1: model.Repository.checkPoints:type_name -> model.CheckPoint + 9, // 2: model.Repository.turnouts:type_name -> model.Turnout + 10, // 3: model.Repository.signals:type_name -> model.Signal + 11, // 4: model.Repository.transponders:type_name -> model.Transponder + 12, // 5: model.Repository.slopes:type_name -> model.Slope + 13, // 6: model.Repository.sectionalCurvatures:type_name -> model.SectionalCurvature + 16, // 7: model.Repository.kilometerConverts:type_name -> model.KilometerConvert + 14, // 8: model.PhysicalSection.aDevicePort:type_name -> model.DevicePort + 14, // 9: model.PhysicalSection.bDevicePort:type_name -> model.DevicePort + 15, // 10: model.CheckPoint.km:type_name -> model.Kilometer 3, // 11: model.CheckPoint.type:type_name -> model.CheckPointType - 12, // 12: model.CheckPoint.devicePorts:type_name -> model.DevicePort - 13, // 13: model.Turnout.km:type_name -> model.Kilometer - 12, // 14: model.Turnout.aDevicePort:type_name -> model.DevicePort - 12, // 15: model.Turnout.bDevicePort:type_name -> model.DevicePort - 12, // 16: model.Turnout.cDevicePort:type_name -> model.DevicePort - 13, // 17: model.Signal.km:type_name -> model.Kilometer - 12, // 18: model.Signal.turnoutPort:type_name -> model.DevicePort - 13, // 19: model.Transponder.km:type_name -> model.Kilometer - 12, // 20: model.Transponder.turnoutPort:type_name -> model.DevicePort - 13, // 21: model.Slope.kms:type_name -> model.Kilometer - 13, // 22: model.SectionalCurvature.kms:type_name -> model.Kilometer - 0, // 23: model.DevicePort.deviceType:type_name -> model.DeviceType - 1, // 24: model.DevicePort.port:type_name -> model.Port - 2, // 25: model.Kilometer.direction:type_name -> model.Direction - 13, // 26: model.KilometerConvert.kmA:type_name -> model.Kilometer - 13, // 27: model.KilometerConvert.kmB:type_name -> model.Kilometer - 28, // [28:28] is the sub-list for method output_type - 28, // [28:28] is the sub-list for method input_type - 28, // [28:28] is the sub-list for extension type_name - 28, // [28:28] is the sub-list for extension extendee - 0, // [0:28] is the sub-list for field type_name + 14, // 12: model.CheckPoint.devicePorts:type_name -> model.DevicePort + 15, // 13: model.Turnout.km:type_name -> model.Kilometer + 14, // 14: model.Turnout.aDevicePort:type_name -> model.DevicePort + 14, // 15: model.Turnout.bDevicePort:type_name -> model.DevicePort + 14, // 16: model.Turnout.cDevicePort:type_name -> model.DevicePort + 4, // 17: model.Turnout.switchMachineType:type_name -> model.Turnout.SwitchMachineType + 15, // 18: model.Signal.km:type_name -> model.Kilometer + 14, // 19: model.Signal.turnoutPort:type_name -> model.DevicePort + 15, // 20: model.Transponder.km:type_name -> model.Kilometer + 14, // 21: model.Transponder.turnoutPort:type_name -> model.DevicePort + 15, // 22: model.Slope.kms:type_name -> model.Kilometer + 15, // 23: model.SectionalCurvature.kms:type_name -> model.Kilometer + 0, // 24: model.DevicePort.deviceType:type_name -> model.DeviceType + 1, // 25: model.DevicePort.port:type_name -> model.Port + 2, // 26: model.Kilometer.direction:type_name -> model.Direction + 15, // 27: model.KilometerConvert.kmA:type_name -> model.Kilometer + 15, // 28: model.KilometerConvert.kmB:type_name -> model.Kilometer + 5, // 29: model.Relay.type:type_name -> model.Relay.Type + 30, // [30:30] is the sub-list for method output_type + 30, // [30:30] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_model_proto_init() } @@ -1405,14 +1599,26 @@ func file_model_proto_init() { return nil } } + file_model_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Relay); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_model_proto_rawDesc, - NumEnums: 4, - NumMessages: 11, + NumEnums: 6, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, diff --git a/repository/physical_section.go b/repository/physical_section.go index 4c607d7..caa2a74 100644 --- a/repository/physical_section.go +++ b/repository/physical_section.go @@ -17,7 +17,7 @@ type PhysicalSection struct { aRelation DevicePort bRelation DevicePort - // 非道岔物理区段A/B端区段边界的公里标 + // 非道岔物理区段A/B端的公里标 aKm *proto.Kilometer bKm *proto.Kilometer @@ -25,6 +25,10 @@ type PhysicalSection struct { // 关联的设备(目前有信号机、应答器、(非区段边界)检测点) devices []Identity + + //在Link上的区间(根据aKm和bKm计算出的) + startLinkPosition *LinkPosition + endLinkPosition *LinkPosition } func NewPhysicalSection(id string) *PhysicalSection { @@ -87,6 +91,14 @@ func (s *PhysicalSection) bindDevices(devices ...Identity) { } } +func (s *PhysicalSection) bindStartLinkPosition(position *LinkPosition) { + s.startLinkPosition = position +} + +func (s *PhysicalSection) bindEndLinkPosition(position *LinkPosition) { + s.endLinkPosition = position +} + func (s *PhysicalSection) ARelation() DevicePort { return s.aRelation } @@ -125,6 +137,14 @@ func (s *PhysicalSection) findBoundaryKmByPort(port proto.Port) *proto.Kilometer return nil } +func (s *PhysicalSection) StartLinkPosition() *LinkPosition { + return s.startLinkPosition +} + +func (s *PhysicalSection) EndLinkPosition() *LinkPosition { + return s.endLinkPosition +} + type PhysicalSectionPort struct { section *PhysicalSection port proto.Port diff --git a/repository/repository.go b/repository/repository.go index a9f00e7..88d68de 100644 --- a/repository/repository.go +++ b/repository/repository.go @@ -17,10 +17,16 @@ type Repository struct { slopeMap map[string]*Slope sectionalCurvatureMap map[string]*SectionalCurvature + linkMap map[string]*Link + //devicePositionMap map[string]*DeviceLinkPosition //key为device的id + //linkNodeMap map[string]*LinkNode //LinkNode的id应该没什么意义,所以此处key用LinkNode中Turnout的id + //slopeLinkSegmentMap map[string]*SlopeLinkSegment + //sectionalCurvatureLinkSegmentMap map[string]*SectionalCurvatureLinkSegment + kilometerConvertMap map[string]*proto.KilometerConvert } -func NewRepository(id string, version string) *Repository { +func newRepository(id string, version string) *Repository { return &Repository{ id: id, version: version, @@ -32,10 +38,79 @@ func NewRepository(id string, version string) *Repository { responderMap: make(map[string]*Transponder), slopeMap: make(map[string]*Slope), sectionalCurvatureMap: make(map[string]*SectionalCurvature), - kilometerConvertMap: make(map[string]*proto.KilometerConvert), + linkMap: make(map[string]*Link), + //devicePositionMap: make(map[string]*DeviceLinkPosition), + //linkNodeMap: make(map[string]*LinkNode), + //slopeLinkSegmentMap: make(map[string]*SlopeLinkSegment), + //sectionalCurvatureLinkSegmentMap: make(map[string]*SectionalCurvatureLinkSegment), + kilometerConvertMap: make(map[string]*proto.KilometerConvert), } } +func (repo *Repository) PhysicalSectionList() []*PhysicalSection { + var list []*PhysicalSection + for _, model := range repo.physicalSectionMap { + list = append(list, model) + } + return list +} +func (repo *Repository) CheckPointList() []*CheckPoint { + var list []*CheckPoint + for _, model := range repo.checkPointMap { + list = append(list, model) + } + return list +} +func (repo *Repository) TurnoutList() []*Turnout { + var list []*Turnout + for _, model := range repo.turnoutMap { + list = append(list, model) + } + return list +} +func (repo *Repository) SignalList() []*Signal { + var list []*Signal + for _, model := range repo.signalMap { + list = append(list, model) + } + return list +} +func (repo *Repository) ResponderList() []*Transponder { + var list []*Transponder + for _, model := range repo.responderMap { + list = append(list, model) + } + return list +} +func (repo *Repository) SlopeList() []*Slope { + var list []*Slope + for _, model := range repo.slopeMap { + list = append(list, model) + } + return list +} +func (repo *Repository) SectionalCurvatureList() []*SectionalCurvature { + var list []*SectionalCurvature + for _, model := range repo.sectionalCurvatureMap { + list = append(list, model) + } + return list +} +func (repo *Repository) LinkList() []*Link { + var list []*Link + for _, model := range repo.linkMap { + list = append(list, model) + } + return list +} +func (repo *Repository) KilometerConvertList() []*proto.KilometerConvert { + var list []*proto.KilometerConvert + for _, model := range repo.kilometerConvertMap { + list = append(list, model) + } + return list +} + func (repo *Repository) getModel(deviceId string, deviceType proto.DeviceType) (Identity, error) { switch deviceType { case proto.DeviceType_DeviceType_PhysicalSection: @@ -46,73 +121,25 @@ func (repo *Repository) getModel(deviceId string, deviceType proto.DeviceType) ( return repo.turnoutMap[deviceId], nil case proto.DeviceType_DeviceType_Signal: return repo.signalMap[deviceId], nil - case proto.DeviceType_DeviceType_Responder: + case proto.DeviceType_DeviceType_Transponder: return repo.responderMap[deviceId], nil case proto.DeviceType_DeviceType_Slope: return repo.slopeMap[deviceId], nil case proto.DeviceType_DeviceType_SectionalCurvature: return repo.sectionalCurvatureMap[deviceId], nil + case proto.DeviceType_DeviceType_Link: + return repo.linkMap[deviceId], nil default: return nil, errors.New(fmt.Sprintf("仓库中不存在[%s]类型的模型", deviceType)) } } -func (repo *Repository) PhysicalSectionList() []*PhysicalSection { - list := make([]*PhysicalSection, len(repo.physicalSectionMap)) - for _, m := range repo.physicalSectionMap { - list = append(list, m) - } - return list -} - -func (repo *Repository) TurnoutList() []*Turnout { - list := make([]*Turnout, 0) - for _, m := range repo.turnoutMap { - list = append(list, m) - } - return list -} - -func (repo *Repository) SignalList() []*Signal { - list := make([]*Signal, len(repo.signalMap)) - for _, m := range repo.signalMap { - list = append(list, m) - } - return list -} - -func (repo *Repository) ResponderList() []*Transponder { - list := make([]*Transponder, len(repo.responderMap)) - for _, m := range repo.responderMap { - list = append(list, m) - } - return list -} - -func (repo *Repository) SlopeList() []*Slope { - list := make([]*Slope, len(repo.slopeMap)) - for _, m := range repo.slopeMap { - list = append(list, m) - } - return list -} - -func (repo *Repository) SectionalCurvatureList() []*SectionalCurvature { - list := make([]*SectionalCurvature, len(repo.sectionalCurvatureMap)) - for _, m := range repo.sectionalCurvatureMap { - list = append(list, m) - } - return list +func (repo *Repository) FindLink(id string) *Link { + return repo.linkMap[id] } func (repo *Repository) AddPhysicalSection(section *PhysicalSection) { repo.physicalSectionMap[section.Id()] = section - //repo.modelMap[section.Id()] = section - -} - -func buildKilometerConvertKey(cs1 string, cs2 string, dir1 proto.Direction, dir2 proto.Direction) string { - return cs1 + dir1.String() + cs2 + dir2.String() } func (repo *Repository) addKilometerConvert(kc *proto.KilometerConvert) { @@ -127,3 +154,7 @@ func (repo *Repository) getKilometerConvert(cs1, cs2 string, dir1, dir2 proto.Di } return convert, nil } + +func buildKilometerConvertKey(cs1 string, cs2 string, dir1 proto.Direction, dir2 proto.Direction) string { + return cs1 + dir1.String() + cs2 + dir2.String() +} diff --git a/repository/repository_builder.go b/repository/repository_builder.go deleted file mode 100644 index 72f8b79..0000000 --- a/repository/repository_builder.go +++ /dev/null @@ -1,336 +0,0 @@ -package repository - -import ( - "errors" - "fmt" - "joylink.club/rtsssimulation/repository/model/proto" -) - -var repositoryMap = make(map[string]*Repository) - -func BuildRepository(source *proto.Repository) (*Repository, error) { - repository := NewRepository(source.Id, source.Version) - buildModels(source, repository) - err := buildModelRelationship(source, repository) - if err == nil { - repositoryMap[buildRepositoryKey(source.Id, source.Version)] = repository - } - return repository, err -} - -func buildRepositoryKey(id string, version string) string { - return id + "_" + version -} - -func getRepository(id string, version string) (*Repository, error) { - repository := repositoryMap[buildRepositoryKey(id, version)] - if repository == nil { - return repository, errors.New(fmt.Sprintf("%s-%s的仓库未找到", id, version)) - } - return repository, nil -} - -func buildModels(source *proto.Repository, repository *Repository) { - for _, protoData := range source.KilometerConverts { - repository.addKilometerConvert(protoData) - } - for _, protoData := range source.PhysicalSections { - m := NewPhysicalSection(protoData.Id) - repository.physicalSectionMap[m.Id()] = m - } - for _, protoData := range source.CheckPoints { - m := NewCheckPoint(protoData.Id, protoData.Km, protoData.Type) - repository.checkPointMap[m.Id()] = m - } - for _, protoData := range source.Turnouts { - m := NewTurnout(protoData.Id, protoData.Km) - repository.turnoutMap[m.Id()] = m - } - for _, protoData := range source.Signals { - m := NewSignal(protoData.Id, protoData.Km) - repository.signalMap[m.Id()] = m - } - for _, protoData := range source.Transponders { - m := NewTransponder(protoData.Id, protoData.Km) - repository.responderMap[m.Id()] = m - } - for _, protoData := range source.Slopes { - m := NewSlope(protoData.Id, protoData.Kms, protoData.Degree) - repository.slopeMap[m.Id()] = m - } - for _, protoData := range source.SectionalCurvatures { - m := NewSectionalCurvature(protoData.Id, protoData.Kms, protoData.Radius) - repository.sectionalCurvatureMap[m.Id()] = m - } -} - -func buildModelRelationship(source *proto.Repository, repository *Repository) error { - err := buildCheckPointRelationShip(source, repository) - if err != nil { - return err - } - err = buildPhysicalSectionRelationShip(source, repository) - if err != nil { - return err - } - err = buildTurnoutRelationShip(source, repository) - if err != nil { - return err - } - err = buildSignalRelationShip(source, repository) - if err != nil { - return err - } - err = buildResponderRelationShip(source, repository) - if err != nil { - return err - } - return err -} - -func buildCheckPointRelationShip(source *proto.Repository, repo *Repository) error { - for _, protoData := range source.CheckPoints { - cp := repo.checkPointMap[protoData.Id] - isBoundary := protoData.Type == proto.CheckPointType_Boundary - for _, protoDp := range protoData.DevicePorts { - switch protoDp.DeviceType { - case proto.DeviceType_DeviceType_PhysicalSection: - section := repo.physicalSectionMap[protoDp.DeviceId] - if isBoundary { //是区段边界 - err := section.bindBoundaryKm(cp.km, protoDp.Port) - if err != nil { - return err - } - } else { - //检测点关联区段端口 - cp.bindDevicePort(&PhysicalSectionPort{ - section: section, - port: protoDp.Port, - }) - //区段关联检测点 - section.bindDevices(cp) - //如果区段边界未设置 - if section.findBoundaryKmByPort(protoDp.Port) == nil { - if err := section.bindBoundaryKm(cp.km, protoDp.Port); err != nil { - return err - } - } - } - case proto.DeviceType_DeviceType_Turnout: - turnout := repo.turnoutMap[protoDp.DeviceId] - if isBoundary { //是区段边界 - err := turnout.bindBoundaryKm(cp.km, protoDp.Port) - if err != nil { - return err - } - } else { - //检测点关联道岔端口 - cp.bindDevicePort(&TurnoutPort{ - turnout: turnout, - port: protoDp.Port, - }) - //道岔关联检测点 - turnout.bindDevice(cp, protoDp.Port) - //如果区段边界未设置 - if turnout.findBoundaryKmByPort(protoDp.Port) == nil { - if err := turnout.bindBoundaryKm(cp.km, protoDp.Port); err != nil { - return err - } - } - } - } - } - } - return nil -} - -func buildResponderRelationShip(source *proto.Repository, repository *Repository) error { - for _, protoData := range source.Transponders { - responder := repository.responderMap[protoData.Id] - //应答器和区段相互关联 - if protoData.SectionId != "" { - interrelateResponderAndPhysicalSection(responder, repository.physicalSectionMap[protoData.SectionId]) - } - //应答器和道岔相互关联 - tp := protoData.TurnoutPort - if tp != nil { - if tp.DeviceType != proto.DeviceType_DeviceType_Turnout { - return errors.New(fmt.Sprintf("应答器[%s]关联的[%s-%s-%s]并非道岔端口", - responder.Id(), tp.DeviceId, tp.DeviceType, tp.Port)) - } - interrelateResponderAndTurnout(responder, repository.turnoutMap[tp.DeviceId], tp.Port) - } - } - return nil -} - -func buildSignalRelationShip(source *proto.Repository, repository *Repository) error { - for _, protoData := range source.Signals { - signal := repository.signalMap[protoData.Id] - //信号机和区段相互关联 - if protoData.SectionId != "" { - interrelateSignalAndPhysicalSection(signal, repository.physicalSectionMap[protoData.SectionId]) - } - //信号机和道岔相互关联 - tp := protoData.TurnoutPort - if tp != nil { - if tp.DeviceType != proto.DeviceType_DeviceType_Turnout { - return errors.New(fmt.Sprintf("信号机[%s]关联的[%s-%s-%s]并非道岔端口", - signal.Id(), tp.DeviceId, tp.DeviceType, tp.Port)) - } - interrelateSignalAndTurnout(signal, repository.turnoutMap[tp.DeviceId], tp.Port) - } - } - return nil -} - -func buildTurnoutRelationShip(source *proto.Repository, repo *Repository) error { - for _, protoData := range source.Turnouts { - turnout := repo.turnoutMap[protoData.Id] - err := buildTurnoutPortRelation(repo, turnout, proto.Port_A, protoData.ADevicePort) - if err != nil { - return err - } - err = buildTurnoutPortRelation(repo, turnout, proto.Port_B, protoData.BDevicePort) - if err != nil { - return err - } - err = buildTurnoutPortRelation(repo, turnout, proto.Port_C, protoData.CDevicePort) - if err != nil { - return err - } - } - return nil -} - -func buildTurnoutPortRelation(repo *Repository, turnout *Turnout, port proto.Port, protoDp *proto.DevicePort) error { - model, err := repo.getModel(protoDp.DeviceId, protoDp.DeviceType) - if err != nil { - return err - } - dp, err := buildDevicePort(model, protoDp.Port) - if err != nil { - return err - } - err = turnout.bindDevicePort(port, dp) - return err -} - -func buildPhysicalSectionRelationShip(source *proto.Repository, repository *Repository) error { - for _, protoData := range source.PhysicalSections { - section := repository.physicalSectionMap[protoData.Id] - //A端关联 - if protoData.ADevicePort != nil { - err := buildSectionPortRelation(repository, section, proto.Port_A, protoData.ADevicePort) - if err != nil { - return err - } - } - //B端关联 - if protoData.BDevicePort != nil { - err := buildSectionPortRelation(repository, section, proto.Port_B, protoData.BDevicePort) - if err != nil { - return err - } - } - //道岔关联 - for _, turnoutId := range protoData.TurnoutIds { - turnout := repository.turnoutMap[turnoutId] - if turnout == nil { - return errors.New(fmt.Sprintf("id[%s]的道岔不存在", turnoutId)) - } - section.bindTurnouts(turnout) - turnout.section = section - } - } - return nil -} - -// 构建物理区段指定端口的关联关系。区段{section}的{port}端口关联{protoDp} -func buildSectionPortRelation(repo *Repository, section *PhysicalSection, port proto.Port, protoDp *proto.DevicePort) error { - model, err := repo.getModel(protoDp.DeviceId, protoDp.DeviceType) - if err != nil { - return err - } - dp, err := buildDevicePort(model, protoDp.Port) - if err != nil { - return err - } - err = section.bindDevicePort(port, dp) - if err != nil { - return err - } - return nil -} - -func buildDevicePort(device Identity, port proto.Port) (DevicePort, error) { - var dp DevicePort - switch device.Type() { - case proto.DeviceType_DeviceType_PhysicalSection: - section := device.(*PhysicalSection) - dp = &PhysicalSectionPort{ - section: section, - port: port, - } - case proto.DeviceType_DeviceType_Turnout: - turnout := device.(*Turnout) - dp = &TurnoutPort{ - turnout: turnout, - port: port, - } - case proto.DeviceType_DeviceType_Link: - link := device.(*Link) - dp = &LinkPort{ - link: link, - port: port, - } - case proto.DeviceType_DeviceType_LinkNode: - linkNode := device.(*LinkNode) - dp = &LinkNodePort{ - node: linkNode, - port: port, - } - default: - return nil, errors.New(fmt.Sprintf("[%s]类型设备没有端口", device.Type())) - } - return dp, nil -} - -// 相互关联道岔和检测点 -func interrelateTurnoutAndCheckPoints(turnout *Turnout, point *CheckPoint, port proto.Port) { - turnout.bindDevice(point, port) - point.bindDevicePort(&TurnoutPort{ - turnout: turnout, - port: port, - }) -} - -// 相互关联物理区段和信号机 -func interrelateSignalAndPhysicalSection(signal *Signal, section *PhysicalSection) { - section.bindDevices(signal) - //signal.bindSection(section) -} - -// 相互关联信号机和道岔 -func interrelateSignalAndTurnout(signal *Signal, turnout *Turnout, port proto.Port) { - //signal.bindTurnoutPort(TurnoutPort{ - // turnout: turnout, - // port: port, - //}) - turnout.bindDevice(signal, port) -} - -// 相互关联应答器和物理区段 -func interrelateResponderAndPhysicalSection(responder *Transponder, section *PhysicalSection) { - //responder.bindSection(section) - section.bindDevices(responder) -} - -// 相互关联应答器和道岔 -func interrelateResponderAndTurnout(responder *Transponder, turnout *Turnout, port proto.Port) { - //responder.bindTurnoutPort(TurnoutPort{ - // turnout: turnout, - // port: port, - //}) - turnout.bindDevice(responder, port) -} diff --git a/repository/repository_manager.go b/repository/repository_manager.go new file mode 100644 index 0000000..bc02b7e --- /dev/null +++ b/repository/repository_manager.go @@ -0,0 +1,661 @@ +package repository + +import ( + "errors" + "fmt" + "joylink.club/rtsssimulation/repository/model/proto" + "joylink.club/rtsssimulation/util/number" + "math" + "strconv" +) + +var repositoryMap = make(map[string]*Repository) + +func BuildRepository(source *proto.Repository) (*Repository, error) { + repository := newRepository(source.Id, source.Version) + buildModels(source, repository) + err := buildModelRelationship(source, repository) + if err != nil { + return nil, err + } + err = buildLinksAndRelate(repository) + if err != nil { + return nil, err + } + repositoryMap[buildRepositoryKey(source.Id, source.Version)] = repository + return repository, err +} + +func FindRepository(id string, version string) *Repository { + return repositoryMap[buildRepositoryKey(id, version)] +} + +func buildRepositoryKey(id string, version string) string { + return id + "_" + version +} + +func buildModels(source *proto.Repository, repository *Repository) { + for _, protoData := range source.KilometerConverts { + repository.addKilometerConvert(protoData) + } + for _, protoData := range source.PhysicalSections { + m := NewPhysicalSection(protoData.Id) + repository.physicalSectionMap[m.Id()] = m + } + for _, protoData := range source.CheckPoints { + m := NewCheckPoint(protoData.Id, protoData.Km, protoData.Type) + repository.checkPointMap[m.Id()] = m + } + for _, protoData := range source.Turnouts { + m := NewTurnout(protoData.Id, protoData.Km) + repository.turnoutMap[m.Id()] = m + } + for _, protoData := range source.Signals { + m := NewSignal(protoData.Id, protoData.Km) + repository.signalMap[m.Id()] = m + } + for _, protoData := range source.Transponders { + m := NewTransponder(protoData.Id, protoData.Km) + repository.responderMap[m.Id()] = m + } + for _, protoData := range source.Slopes { + m := NewSlope(protoData.Id, protoData.Kms, protoData.Degree) + repository.slopeMap[m.Id()] = m + } + for _, protoData := range source.SectionalCurvatures { + m := NewSectionalCurvature(protoData.Id, protoData.Kms, protoData.Radius) + repository.sectionalCurvatureMap[m.Id()] = m + } +} + +func buildModelRelationship(source *proto.Repository, repository *Repository) error { + err := buildCheckPointRelationShip(source, repository) + if err != nil { + return err + } + err = buildPhysicalSectionRelationShip(source, repository) + if err != nil { + return err + } + err = buildTurnoutRelationShip(source, repository) + if err != nil { + return err + } + err = buildSignalRelationShip(source, repository) + if err != nil { + return err + } + err = buildResponderRelationShip(source, repository) + if err != nil { + return err + } + return err +} + +func buildCheckPointRelationShip(source *proto.Repository, repo *Repository) error { + for _, protoData := range source.CheckPoints { + cp := repo.checkPointMap[protoData.Id] + isBoundary := protoData.Type == proto.CheckPointType_Boundary + for _, protoDp := range protoData.DevicePorts { + switch protoDp.DeviceType { + case proto.DeviceType_DeviceType_PhysicalSection: + section := repo.physicalSectionMap[protoDp.DeviceId] + if isBoundary { //是区段边界 + err := section.bindBoundaryKm(cp.km, protoDp.Port) + if err != nil { + return err + } + } else { + //检测点关联区段端口 + cp.bindDevicePort(&PhysicalSectionPort{ + section: section, + port: protoDp.Port, + }) + //区段关联检测点 + section.bindDevices(cp) + //如果区段边界未设置 + if section.findBoundaryKmByPort(protoDp.Port) == nil { + if err := section.bindBoundaryKm(cp.km, protoDp.Port); err != nil { + return err + } + } + } + case proto.DeviceType_DeviceType_Turnout: + turnout := repo.turnoutMap[protoDp.DeviceId] + if isBoundary { //是区段边界 + err := turnout.bindBoundaryKm(cp.km, protoDp.Port) + if err != nil { + return err + } + } else { + //检测点关联道岔端口 + cp.bindDevicePort(&TurnoutPort{ + turnout: turnout, + port: protoDp.Port, + }) + //道岔关联检测点 + turnout.bindDevice(cp, protoDp.Port) + //如果区段边界未设置 + if turnout.findBoundaryKmByPort(protoDp.Port) == nil { + if err := turnout.bindBoundaryKm(cp.km, protoDp.Port); err != nil { + return err + } + } + } + } + } + } + return nil +} + +func buildResponderRelationShip(source *proto.Repository, repository *Repository) error { + for _, protoData := range source.Transponders { + responder := repository.responderMap[protoData.Id] + //应答器和区段相互关联 + if protoData.SectionId != "" { + interrelateResponderAndPhysicalSection(responder, repository.physicalSectionMap[protoData.SectionId]) + } + //应答器和道岔相互关联 + tp := protoData.TurnoutPort + if tp != nil { + if tp.DeviceType != proto.DeviceType_DeviceType_Turnout { + return errors.New(fmt.Sprintf("应答器[%s]关联的[%s-%s-%s]并非道岔端口", + responder.Id(), tp.DeviceId, tp.DeviceType, tp.Port)) + } + interrelateResponderAndTurnout(responder, repository.turnoutMap[tp.DeviceId], tp.Port) + } + } + return nil +} + +func buildSignalRelationShip(source *proto.Repository, repository *Repository) error { + for _, protoData := range source.Signals { + signal := repository.signalMap[protoData.Id] + //信号机和区段相互关联 + if protoData.SectionId != "" { + interrelateSignalAndPhysicalSection(signal, repository.physicalSectionMap[protoData.SectionId]) + } + //信号机和道岔相互关联 + tp := protoData.TurnoutPort + if tp != nil { + if tp.DeviceType != proto.DeviceType_DeviceType_Turnout { + return errors.New(fmt.Sprintf("信号机[%s]关联的[%s-%s-%s]并非道岔端口", + signal.Id(), tp.DeviceId, tp.DeviceType, tp.Port)) + } + interrelateSignalAndTurnout(signal, repository.turnoutMap[tp.DeviceId], tp.Port) + } + } + return nil +} + +func buildTurnoutRelationShip(source *proto.Repository, repo *Repository) error { + for _, protoData := range source.Turnouts { + turnout := repo.turnoutMap[protoData.Id] + err := buildTurnoutPortRelation(repo, turnout, proto.Port_A, protoData.ADevicePort) + if err != nil { + return err + } + err = buildTurnoutPortRelation(repo, turnout, proto.Port_B, protoData.BDevicePort) + if err != nil { + return err + } + err = buildTurnoutPortRelation(repo, turnout, proto.Port_C, protoData.CDevicePort) + if err != nil { + return err + } + } + return nil +} + +func buildTurnoutPortRelation(repo *Repository, turnout *Turnout, port proto.Port, protoDp *proto.DevicePort) error { + model, err := repo.getModel(protoDp.DeviceId, protoDp.DeviceType) + if err != nil { + return err + } + dp, err := buildDevicePort(model, protoDp.Port) + if err != nil { + return err + } + err = turnout.bindDevicePort(port, dp) + return err +} + +func buildPhysicalSectionRelationShip(source *proto.Repository, repository *Repository) error { + for _, protoData := range source.PhysicalSections { + section := repository.physicalSectionMap[protoData.Id] + //A端关联 + if protoData.ADevicePort != nil { + err := buildSectionPortRelation(repository, section, proto.Port_A, protoData.ADevicePort) + if err != nil { + return err + } + } + //B端关联 + if protoData.BDevicePort != nil { + err := buildSectionPortRelation(repository, section, proto.Port_B, protoData.BDevicePort) + if err != nil { + return err + } + } + //道岔关联 + for _, turnoutId := range protoData.TurnoutIds { + turnout := repository.turnoutMap[turnoutId] + if turnout == nil { + return errors.New(fmt.Sprintf("id[%s]的道岔不存在", turnoutId)) + } + section.bindTurnouts(turnout) + turnout.section = section + } + } + return nil +} + +// 构建物理区段指定端口的关联关系。区段{section}的{port}端口关联{protoDp} +func buildSectionPortRelation(repo *Repository, section *PhysicalSection, port proto.Port, protoDp *proto.DevicePort) error { + model, err := repo.getModel(protoDp.DeviceId, protoDp.DeviceType) + if err != nil { + return err + } + dp, err := buildDevicePort(model, protoDp.Port) + if err != nil { + return err + } + err = section.bindDevicePort(port, dp) + if err != nil { + return err + } + return nil +} + +func buildDevicePort(device Identity, port proto.Port) (DevicePort, error) { + var dp DevicePort + switch device.Type() { + case proto.DeviceType_DeviceType_PhysicalSection: + section := device.(*PhysicalSection) + dp = &PhysicalSectionPort{ + section: section, + port: port, + } + case proto.DeviceType_DeviceType_Turnout: + turnout := device.(*Turnout) + dp = &TurnoutPort{ + turnout: turnout, + port: port, + } + case proto.DeviceType_DeviceType_Link: + link := device.(*Link) + dp = &LinkPort{ + link: link, + port: port, + } + default: + return nil, errors.New(fmt.Sprintf("[%s]类型设备没有端口", device.Type())) + } + return dp, nil +} + +// 相互关联道岔和检测点 +func interrelateTurnoutAndCheckPoints(turnout *Turnout, point *CheckPoint, port proto.Port) { + turnout.bindDevice(point, port) + point.bindDevicePort(&TurnoutPort{ + turnout: turnout, + port: port, + }) +} + +// 相互关联物理区段和信号机 +func interrelateSignalAndPhysicalSection(signal *Signal, section *PhysicalSection) { + section.bindDevices(signal) + //signal.bindSection(section) +} + +// 相互关联信号机和道岔 +func interrelateSignalAndTurnout(signal *Signal, turnout *Turnout, port proto.Port) { + //signal.bindTurnoutPort(TurnoutPort{ + // turnout: turnout, + // port: port, + //}) + turnout.bindDevice(signal, port) +} + +// 相互关联应答器和物理区段 +func interrelateResponderAndPhysicalSection(responder *Transponder, section *PhysicalSection) { + //responder.bindSection(section) + section.bindDevices(responder) +} + +// 相互关联应答器和道岔 +func interrelateResponderAndTurnout(responder *Transponder, turnout *Turnout, port proto.Port) { + //responder.bindTurnoutPort(TurnoutPort{ + // turnout: turnout, + // port: port, + //}) + turnout.bindDevice(responder, port) +} + +func buildLinksAndRelate(repo *Repository) error { + //构建link + err := buildLinks(repo) + if err != nil { + return err + } + //Slope关联Link + err = slopeRelateLink(repo) + if err != nil { + return err + } + //SectionalCurvature关联Link + err = sectionalCurvatureRelateLink(repo) + if err != nil { + return err + } + //PhysicalSection关联Link + err = physicalSectionRelateLink(repo) + return nil +} + +func buildLinks(repo *Repository) error { + visitedTurnoutPortMap := make(map[string]bool) + allTurnouts := repo.TurnoutList() + linkIdGenerator := 10000 + for { + //找一个未遍历过的道岔端口 + startTp := getATurnoutPort(allTurnouts, visitedTurnoutPortMap) + if startTp == nil { + break + } + //以始端道岔的公里标作为公里标换算的基准 + baseKm := startTp.turnout.km + //创建基础Link + link := &Link{ + Identity: identity{ + id: strconv.Itoa(linkIdGenerator), //由于发给动力学的link的id是数字,所以这里也用数字 + deviceType: proto.DeviceType_DeviceType_Link, + }} + linkIdGenerator++ + //以此道岔端口作为Link的A端节点 + err := interrelateLinkAndTurnout(startTp, &LinkPort{link, proto.Port_A}) + if err != nil { + return err + } + //沿着道岔端口方向,一直寻找到轨道尽头或者下一个道岔端口。构建并关联中间的设备在link上的位置 + endTp, endKm, err := findEndTurnoutPortOrEndKm(repo, link, startTp, baseKm) + if err != nil { + return err + } + //以下一个道岔端口作为Link的B端节点 + if endTp != nil { + visitedTurnoutPortMap[buildTurnoutPortKey(endTp)] = true + endKm = endTp.turnout.km + err = interrelateLinkAndTurnout(endTp, &LinkPort{link, proto.Port_B}) + if err != nil { + return err + } + } else { + link.bindKm(endKm, proto.Port_B) + } + //计算Link长度 + convertedKm, err := convertKilometer(repo, endKm, baseKm.CoordinateSystem, baseKm.Direction) + if err != nil { + return err + } + link.length = int64(math.Abs(float64(convertedKm.Value - baseKm.Value))) + + repo.linkMap[link.Id()] = link + } + return nil +} + +func findEndTurnoutPortOrEndKm(repo *Repository, link *Link, startTp *TurnoutPort, + baseKm *proto.Kilometer) (*TurnoutPort, *proto.Kilometer, error) { + + var endTp *TurnoutPort + var endKm *proto.Kilometer + var err error + + visitedModelMap := make(map[string]bool) + var currentDp DevicePort = startTp + devices := startTp.turnout.getDevicesByPort(startTp.port) + for { + //遍历设备并构建、关联其在Link上的位置 + err = buildAndRelateDeviceLinkPositions(repo, link, baseKm, visitedModelMap, devices...) + if err != nil { + return nil, nil, err + } + //顺着端口寻找下一个设备端口 + var nextDp DevicePort + switch currentDp.Device().Type() { + case proto.DeviceType_DeviceType_PhysicalSection: + section := currentDp.Device().(*PhysicalSection) + nextDp = section.findOtherDevicePort(currentDp.Port()) + if nextDp == nil { + endKm = section.findOtherBoundaryKmByPort(currentDp.Port()) + } + case proto.DeviceType_DeviceType_Turnout: + turnout := currentDp.Device().(*Turnout) + nextDp = turnout.getDevicePortByPort(currentDp.Port()) + if nextDp == nil { + endKm = turnout.findBoundaryKmByPort(currentDp.Port()) + } + } + //根据下一个端口设备的信息决定是否结束循环 + if nextDp == nil { + break + } + currentDp = nextDp + var nextIsTp bool + switch nextDp.Device().Type() { + case proto.DeviceType_DeviceType_PhysicalSection: + devices = nextDp.Device().(*PhysicalSection).devices + case proto.DeviceType_DeviceType_Turnout: + nextIsTp = true + endTp = nextDp.(*TurnoutPort) + devices = nextDp.Device().(*Turnout).getDevicesByPort(nextDp.Port()) + err = buildAndRelateDeviceLinkPositions(repo, link, baseKm, visitedModelMap, devices...) + if err != nil { + return nil, nil, err + } + } + if nextIsTp { + break + } + } + + return endTp, endKm, err +} + +func getATurnoutPort(turnouts []*Turnout, visitedTurnoutMap map[string]bool) *TurnoutPort { + portSlice := []proto.Port{proto.Port_A, proto.Port_B, proto.Port_C} + for _, turnout := range turnouts { + for _, port := range portSlice { + tp := &TurnoutPort{ + turnout: turnout, + port: port, + } + key := buildTurnoutPortKey(tp) + if !visitedTurnoutMap[key] { + visitedTurnoutMap[key] = true + return tp + } + } + } + return nil +} + +func buildTurnoutPortKey(tp *TurnoutPort) string { + return fmt.Sprintf("%v-%s", tp.turnout, tp.port) +} + +func buildAndRelateDeviceLinkPositions(repo *Repository, link *Link, startKm *proto.Kilometer, visitedModelMap map[string]bool, devices ...Identity) error { + for _, device := range devices { + if visitedModelMap[device.Id()] { + continue + } + km := findModelKm(device) + if km == nil { + continue + } + link.bindDevices(device) + convertedKm, err := convertKilometer(repo, km, startKm.CoordinateSystem, startKm.Direction) + if err != nil { + return err + } + offset := int64(math.Abs(float64(convertedKm.Value - startKm.Value))) + linkPosition := &LinkPosition{ + link: link, + offset: offset, + } + switch device.Type() { + case proto.DeviceType_DeviceType_CheckPoint: + device.(*CheckPoint).bindLinkPosition(linkPosition) + case proto.DeviceType_DeviceType_Signal: + device.(*Signal).bindLinkPosition(linkPosition) + case proto.DeviceType_DeviceType_Transponder: + device.(*Transponder).bindLinkPosition(linkPosition) + } + } + return nil +} + +func interrelateLinkAndTurnout(tp *TurnoutPort, linkPort *LinkPort) error { + tp.turnout.bindLinkPort(tp.port, linkPort) + return linkPort.link.bindDevicePort(linkPort.port, tp) +} + +func findModelKm(model Identity) *proto.Kilometer { + switch model.Type() { + case proto.DeviceType_DeviceType_Signal: + return model.(*Signal).km + case proto.DeviceType_DeviceType_Transponder: + return model.(*Transponder).km + case proto.DeviceType_DeviceType_CheckPoint: + return model.(*CheckPoint).km + case proto.DeviceType_DeviceType_Turnout: + return model.(*Turnout).km + } + return nil +} + +func slopeRelateLink(repo *Repository) error { + slopeMap := repo.slopeMap + for _, slope := range slopeMap { + start, end, err := calculateLinkSegment(repo, slope.kms[0], slope.kms[1]) + if err != nil { + return err + } + slope.bindStartLinkPosition(start) + slope.bindEndLinkPosition(end) + } + return nil +} + +func calculateLinkSegment(repo *Repository, startKm *proto.Kilometer, + endKm *proto.Kilometer) (*LinkPosition, *LinkPosition, error) { + + endKm, err := convertKilometer(repo, endKm, startKm.CoordinateSystem, startKm.Direction) + if err != nil { + return nil, nil, err + } + var start *LinkPosition + var end *LinkPosition + var minKmValue float64 + var minKmLink *Link + var maxKmValue float64 + var maxKmLink *Link + for _, link := range repo.linkMap { + //将link两端的公里标转为aKm同坐标系的公里标 + linkAKm, err := convertKilometer(repo, link.aKm, startKm.CoordinateSystem, startKm.Direction) + if err != nil || linkAKm.Direction != startKm.Direction { + continue + } + linkBKm, err := convertKilometer(repo, link.bKm, startKm.CoordinateSystem, startKm.Direction) + if err != nil || linkBKm.Direction != startKm.Direction { + continue + } + //记录公里标最小/最大的Link + newMinKmValue := math.Min(float64(linkAKm.Value), float64(linkBKm.Value)) + newMaxKmValue := math.Max(float64(linkAKm.Value), float64(linkBKm.Value)) + if minKmLink == nil || newMinKmValue < minKmValue { + minKmValue = newMinKmValue + minKmLink = link + } + if maxKmLink == nil || newMaxKmValue > maxKmValue { + maxKmValue = newMaxKmValue + maxKmLink = link + } + //若start/end公里标落在link上,构建LinkPosition + if number.IsBetween(startKm.Value, linkAKm.Value, linkBKm.Value) { + start = &LinkPosition{ + link: link, + offset: int64(math.Abs(float64(startKm.Value - linkAKm.Value))), + } + } + if number.IsBetween(endKm.Value, linkAKm.Value, linkBKm.Value) { + end = &LinkPosition{ + link: link, + offset: int64(math.Abs(float64(endKm.Value - linkAKm.Value))), + } + } + if start != nil && end != nil { + break + } + } + //处理start/end公里标没落在Link上的情况 + if start == nil { + if startKm.Value < endKm.Value { + offset, _ := minKmLink.findEndOffset() + start = &LinkPosition{ + link: minKmLink, + offset: offset, + } + } else { + offset, _ := maxKmLink.findEndOffset() + start = &LinkPosition{ + link: maxKmLink, + offset: offset, + } + } + } + if end == nil { + if endKm.Value < startKm.Value { + offset, _ := minKmLink.findEndOffset() + end = &LinkPosition{ + link: minKmLink, + offset: offset, + } + } else { + offset, _ := maxKmLink.findEndOffset() + end = &LinkPosition{ + link: maxKmLink, + offset: offset, + } + } + } + + return start, end, nil +} + +func sectionalCurvatureRelateLink(repo *Repository) error { + for _, curvature := range repo.sectionalCurvatureMap { + start, end, err := calculateLinkSegment(repo, curvature.kms[0], curvature.kms[1]) + if err != nil { + return err + } + curvature.bindStartLinkPosition(start) + curvature.bindEndLinkPosition(end) + } + return nil +} + +func physicalSectionRelateLink(repo *Repository) error { + for _, section := range repo.physicalSectionMap { + start, end, err := calculateLinkSegment(repo, section.aKm, section.bKm) + if err != nil { + return err + } + section.bindStartLinkPosition(start) + section.bindEndLinkPosition(end) + section.startLinkPosition.link.bindDevices(section) + } + return nil +} diff --git a/repository/repository_builder_test.go b/repository/repository_manager_test.go similarity index 100% rename from repository/repository_builder_test.go rename to repository/repository_manager_test.go diff --git a/repository/responder.go b/repository/responder.go deleted file mode 100644 index 9052bbe..0000000 --- a/repository/responder.go +++ /dev/null @@ -1,26 +0,0 @@ -package repository - -import "joylink.club/rtsssimulation/repository/model/proto" - -type Responder struct { - Identity - - km *proto.Kilometer - section *PhysicalSection - turnoutPort TurnoutPort -} - -func NewResponder(id string, km *proto.Kilometer) *Responder { - return &Responder{ - Identity: identity{id, proto.DeviceType_DeviceType_Responder}, - km: km, - } -} - -func (r *Responder) bindSection(section *PhysicalSection) { - r.section = section -} - -func (r *Responder) bindTurnoutPort(turnoutPort TurnoutPort) { - r.turnoutPort = turnoutPort -} diff --git a/repository/sectional_curvature.go b/repository/sectional_curvature.go index 9a747ff..79d190f 100644 --- a/repository/sectional_curvature.go +++ b/repository/sectional_curvature.go @@ -4,8 +4,10 @@ import "joylink.club/rtsssimulation/repository/model/proto" type SectionalCurvature struct { Identity - kms []*proto.Kilometer - radius int32 //半径 mm + kms []*proto.Kilometer + radius int32 //半径 mm + startLinkPosition *LinkPosition + endLinkPosition *LinkPosition } func NewSectionalCurvature(id string, kms []*proto.Kilometer, radius int32) *SectionalCurvature { @@ -15,3 +17,23 @@ func NewSectionalCurvature(id string, kms []*proto.Kilometer, radius int32) *Sec radius: radius, } } + +func (s *SectionalCurvature) bindStartLinkPosition(position *LinkPosition) { + s.startLinkPosition = position +} + +func (s *SectionalCurvature) bindEndLinkPosition(position *LinkPosition) { + s.endLinkPosition = position +} + +func (s *SectionalCurvature) StartLinkPosition() *LinkPosition { + return s.startLinkPosition +} + +func (s *SectionalCurvature) EndLinkPosition() *LinkPosition { + return s.endLinkPosition +} + +func (s *SectionalCurvature) Radius() int32 { + return s.radius +} diff --git a/repository/signal.go b/repository/signal.go index 6cde02e..9dbb215 100644 --- a/repository/signal.go +++ b/repository/signal.go @@ -8,6 +8,7 @@ type Signal struct { km *proto.Kilometer //section *PhysicalSection //turnoutPort TurnoutPort + linkPosition *LinkPosition } func NewSignal(id string, km *proto.Kilometer) *Signal { @@ -17,6 +18,10 @@ func NewSignal(id string, km *proto.Kilometer) *Signal { } } +func (s *Signal) bindLinkPosition(position *LinkPosition) { + s.linkPosition = position +} + //func (s *Signal) bindSection(section *PhysicalSection) { // s.section = section //} diff --git a/repository/simulation.go b/repository/simulation.go deleted file mode 100644 index 96bb485..0000000 --- a/repository/simulation.go +++ /dev/null @@ -1,387 +0,0 @@ -package repository - -import ( - "fmt" - "joylink.club/rtsssimulation/repository/model/proto" - "joylink.club/rtsssimulation/util" - "math" - "strconv" -) - -var simId = 1 - -func BuildSimulation(id string, version string) (*Simulation, error) { - repository, err := getRepository(id, version) - if err != nil { - return nil, err - } - simulation := newSimulation(repository) - //构建link - err = buildLinks(simulation) - if err != nil { - return nil, err - } - //构建Slope的Link区间 - err = buildSlopeLinkSegments(simulation) - if err != nil { - return nil, err - } - //构建SectionalCurvature的Link区间 - err = buildSectionalCurvatureLinkSegments(simulation) - if err != nil { - return nil, err - } - return simulation, nil -} - -func getASimulationId() string { - id := strconv.Itoa(simId) - simId++ - return id -} - -type Simulation struct { - id string - idGenerator int - repository *Repository - linkMap map[string]*Link - devicePositionMap map[string]*DeviceLinkPosition //key为device的id - linkNodeMap map[string]*LinkNode //LinkNode的id应该没什么意义,所以此处key用LinkNode中Turnout的id - slopeLinkSegmentMap map[string]SlopeLinkSegment - sectionalCurvatureLinkSegmentMap map[string]SectionalCurvatureLinkSegment -} - -func newSimulation(repository *Repository) *Simulation { - return &Simulation{ - id: getASimulationId(), - idGenerator: 1, - repository: repository, - linkMap: make(map[string]*Link), - devicePositionMap: make(map[string]*DeviceLinkPosition), - linkNodeMap: make(map[string]*LinkNode), - slopeLinkSegmentMap: make(map[string]SlopeLinkSegment), - sectionalCurvatureLinkSegmentMap: make(map[string]SectionalCurvatureLinkSegment), - } -} - -func (s *Simulation) getAId() string { - id := strconv.Itoa(s.idGenerator) - s.idGenerator++ - return id -} - -func buildLinks(sim *Simulation) error { - visitedTurnoutPortMap := make(map[string]bool) - allTurnouts := sim.repository.TurnoutList() - for { - //找一个未遍历过的道岔端口 - startTp := getATurnoutPort(allTurnouts, visitedTurnoutPortMap) - if startTp == nil { - break - } - //以始端道岔的公里标作为公里标换算的基准 - baseKm := startTp.turnout.km - //创建基础Link - link := &Link{Identity: identity{sim.getAId(), proto.DeviceType_DeviceType_Link}} - //以此道岔端口作为Link的A端节点 - err := buildAndRelateLinkNode(sim, startTp, link, proto.Port_A) - if err != nil { - return err - } - //沿着道岔端口方向,一直寻找到轨道尽头或者下一个道岔端口。构建并关联中间的设备在link上的位置 - endTp, endKm, err := findEndTurnoutPortOrEndKm(sim, link, startTp, baseKm) - if err != nil { - return err - } - //以下一个道岔端口作为Link的B端节点 - if endTp != nil { - visitedTurnoutPortMap[buildTurnoutPortKey(endTp)] = true - endKm = endTp.turnout.km - err = buildAndRelateLinkNode(sim, endTp, link, proto.Port_B) - if err != nil { - return err - } - } - //计算Link长度 - convertedKm, err := convertKilometer(sim.repository, endKm, baseKm.CoordinateSystem, baseKm.Direction) - if err != nil { - return err - } - link.length = int64(math.Abs(float64(convertedKm.Value - baseKm.Value))) - - sim.linkMap[link.Id()] = link - } - return nil -} - -func findEndTurnoutPortOrEndKm(sim *Simulation, link *Link, startTp *TurnoutPort, - baseKm *proto.Kilometer) (*TurnoutPort, *proto.Kilometer, error) { - - var endTp *TurnoutPort - var endKm *proto.Kilometer - var err error - - visitedModelMap := make(map[string]bool) - var currentDp DevicePort = startTp - devices := startTp.turnout.getDevicesByPort(startTp.port) - for { - //遍历设备并构建、关联其在Link上的位置 - err = buildAndRelateDeviceLinkPositions(sim, link, baseKm, visitedModelMap, devices...) - if err != nil { - return nil, nil, err - } - //顺着端口寻找下一个设备端口 - var nextDp DevicePort - switch currentDp.Device().Type() { - case proto.DeviceType_DeviceType_PhysicalSection: - section := currentDp.Device().(*PhysicalSection) - nextDp = section.findOtherDevicePort(currentDp.Port()) - if nextDp == nil { - endKm = section.findOtherBoundaryKmByPort(currentDp.Port()) - } - case proto.DeviceType_DeviceType_Turnout: - turnout := currentDp.Device().(*Turnout) - nextDp = turnout.getDevicePortByPort(currentDp.Port()) - if nextDp == nil { - endKm = turnout.findBoundaryKmByPort(currentDp.Port()) - } - } - //根据下一个端口设备的信息决定是否结束循环 - if nextDp == nil { - break - } - currentDp = nextDp - var nextIsTp bool - switch nextDp.Device().Type() { - case proto.DeviceType_DeviceType_PhysicalSection: - devices = nextDp.Device().(*PhysicalSection).devices - case proto.DeviceType_DeviceType_Turnout: - nextIsTp = true - endTp = nextDp.(*TurnoutPort) - devices = nextDp.Device().(*Turnout).getDevicesByPort(nextDp.Port()) - err = buildAndRelateDeviceLinkPositions(sim, link, baseKm, visitedModelMap, devices...) - if err != nil { - return nil, nil, err - } - } - if nextIsTp { - break - } - } - - return endTp, endKm, err -} - -func getATurnoutPort(turnouts []*Turnout, visitedTurnoutMap map[string]bool) *TurnoutPort { - portSlice := []proto.Port{proto.Port_A, proto.Port_B, proto.Port_C} - for _, turnout := range turnouts { - for _, port := range portSlice { - tp := &TurnoutPort{ - turnout: turnout, - port: port, - } - key := buildTurnoutPortKey(tp) - if !visitedTurnoutMap[key] { - visitedTurnoutMap[key] = true - return tp - } - } - } - return nil -} - -func buildTurnoutPortKey(tp *TurnoutPort) string { - return fmt.Sprintf("%v-%s", tp.turnout, tp.port) -} - -func buildAndRelateDeviceLinkPositions(sim *Simulation, link *Link, startKm *proto.Kilometer, visitedModelMap map[string]bool, devices ...Identity) error { - - for _, device := range devices { - if visitedModelMap[device.Id()] { - continue - } - km := findModelKm(device) - if km == nil { - continue - } - convertedKm, err := convertKilometer(sim.repository, km, startKm.CoordinateSystem, startKm.Direction) - if err != nil { - return err - } - offset := int64(math.Abs(float64(convertedKm.Value - startKm.Value))) - dlps := &DeviceLinkPosition{ - device: device, - position: LinkPosition{ - link: link, - offset: offset, - }, - } - sim.devicePositionMap[dlps.device.Id()] = dlps - link.bindDevicesLinkPositions(dlps) - } - return nil -} - -func buildAndRelateLinkNode(sim *Simulation, tp *TurnoutPort, link *Link, port proto.Port) error { - ln := sim.linkNodeMap[tp.turnout.Id()] - if ln == nil { - ln = &LinkNode{ - Identity: identity{sim.getAId(), proto.DeviceType_DeviceType_LinkNode}, - turnout: tp.turnout, - } - } - //LinkNode关联Link - err := ln.bindDevicePort(port, &LinkPort{ - link: link, - port: port, - }) - if err != nil { - return err - } - //Link关联LinkNode - err = link.bindDevicePort(port, &LinkNodePort{ - node: ln, - port: tp.port, - }) - return err -} - -func findModelKm(model Identity) *proto.Kilometer { - signal, ok := model.(*Signal) - if ok { - return signal.km - } - responder, ok := model.(*Responder) - if ok { - return responder.km - } - cp, ok := model.(*CheckPoint) - if ok { - return cp.km - } - turnout, ok := model.(*Turnout) - if ok { - return turnout.km - } - return nil -} - -func buildSlopeLinkSegments(simulation *Simulation) error { - repo := simulation.repository - slopeMap := repo.slopeMap - for _, slope := range slopeMap { - start, end, err := calculateLinkSegment(simulation, slope.kms[0], slope.kms[1]) - if err != nil { - return err - } - simulation.slopeLinkSegmentMap[slope.Id()] = SlopeLinkSegment{ - slope: slope, - start: start, - end: end, - } - } - return nil -} - -func calculateLinkSegment(simulation *Simulation, startKm *proto.Kilometer, - endKm *proto.Kilometer) (*LinkPosition, *LinkPosition, error) { - - repo := simulation.repository - endKm, err := convertKilometer(repo, endKm, startKm.CoordinateSystem, startKm.Direction) - if err != nil { - return nil, nil, err - } - var start *LinkPosition - var end *LinkPosition - var minKmValue float64 - var minKmLink *Link - var maxKmValue float64 - var maxKmLink *Link - for _, link := range simulation.linkMap { - //将link两端的公里标转为aKm同坐标系的公里标 - linkAKm, err := convertKilometer(repo, link.aKm, startKm.CoordinateSystem, startKm.Direction) - if err != nil || linkAKm.Direction != startKm.Direction { - continue - } - linkBKm, err := convertKilometer(repo, link.bKm, startKm.CoordinateSystem, startKm.Direction) - if err != nil || linkBKm.Direction != startKm.Direction { - continue - } - //记录公里标最小/最大的Link - newMinKmValue := math.Min(float64(linkAKm.Value), float64(linkBKm.Value)) - newMaxKmValue := math.Max(float64(linkAKm.Value), float64(linkBKm.Value)) - if minKmLink == nil || newMinKmValue < minKmValue { - minKmValue = newMinKmValue - minKmLink = link - } - if maxKmLink == nil || newMaxKmValue > maxKmValue { - maxKmValue = newMaxKmValue - maxKmLink = link - } - //若start/end公里标落在link上,构建LinkPosition - if util.IsBetween(startKm.Value, linkAKm.Value, linkBKm.Value) { - start = &LinkPosition{ - link: link, - offset: int64(math.Abs(float64(startKm.Value - linkAKm.Value))), - } - } - if util.IsBetween(endKm.Value, linkAKm.Value, linkBKm.Value) { - end = &LinkPosition{ - link: link, - offset: int64(math.Abs(float64(endKm.Value - linkAKm.Value))), - } - } - if start != nil && end != nil { - break - } - } - //处理start/end公里标没落在Link上的情况 - if start == nil { - if startKm.Value < endKm.Value { - offset, _ := minKmLink.findEndOffset() - start = &LinkPosition{ - link: minKmLink, - offset: offset, - } - } else { - offset, _ := maxKmLink.findEndOffset() - start = &LinkPosition{ - link: maxKmLink, - offset: offset, - } - } - } - if end == nil { - if endKm.Value < startKm.Value { - offset, _ := minKmLink.findEndOffset() - end = &LinkPosition{ - link: minKmLink, - offset: offset, - } - } else { - offset, _ := maxKmLink.findEndOffset() - end = &LinkPosition{ - link: maxKmLink, - offset: offset, - } - } - } - - return start, end, nil -} - -func buildSectionalCurvatureLinkSegments(sim *Simulation) error { - repo := sim.repository - for _, curvature := range repo.sectionalCurvatureMap { - start, end, err := calculateLinkSegment(sim, curvature.kms[0], curvature.kms[1]) - if err != nil { - return err - } - sim.sectionalCurvatureLinkSegmentMap[curvature.Id()] = SectionalCurvatureLinkSegment{ - sectionalCurvature: curvature, - start: start, - end: end, - } - } - return nil -} diff --git a/repository/slope.go b/repository/slope.go index 3138e7b..c0468ec 100644 --- a/repository/slope.go +++ b/repository/slope.go @@ -5,8 +5,10 @@ import "joylink.club/rtsssimulation/repository/model/proto" type Slope struct { Identity - kms []*proto.Kilometer - degree int32 + kms []*proto.Kilometer + degree int32 + startLinkPosition *LinkPosition + endLinkPosition *LinkPosition } func NewSlope(id string, kms []*proto.Kilometer, degree int32) *Slope { @@ -16,3 +18,23 @@ func NewSlope(id string, kms []*proto.Kilometer, degree int32) *Slope { degree: degree, } } + +func (s *Slope) bindStartLinkPosition(position *LinkPosition) { + s.startLinkPosition = position +} + +func (s *Slope) bindEndLinkPosition(position *LinkPosition) { + s.endLinkPosition = position +} + +func (s *Slope) StartLinkPosition() *LinkPosition { + return s.startLinkPosition +} + +func (s *Slope) EndLinkPosition() *LinkPosition { + return s.endLinkPosition +} + +func (s *Slope) Degree() int32 { + return s.degree +} diff --git a/repository/turnout.go b/repository/turnout.go index 1456a7c..6852a36 100644 --- a/repository/turnout.go +++ b/repository/turnout.go @@ -15,11 +15,16 @@ type Turnout struct { // 道岔关联的道岔物理区段 section *PhysicalSection - // A/B/C端口关联的设备端口 + // A/B/C端口关联的设备端口(区段/道岔) aDevicePort DevicePort bDevicePort DevicePort cDevicePort DevicePort + // A/B/C端口关联的Link端口 + aLinkPort *LinkPort + bLinkPort *LinkPort + cLinkPort *LinkPort + // A/B/C端口的区段边界的公里标 aKm *proto.Kilometer bKm *proto.Kilometer @@ -65,6 +70,17 @@ func (t *Turnout) bindDevicePort(port proto.Port, devicePort DevicePort) error { return nil } +func (t *Turnout) bindLinkPort(port proto.Port, linkPort *LinkPort) { + switch port { + case proto.Port_A: + t.aLinkPort = linkPort + case proto.Port_B: + t.aLinkPort = linkPort + case proto.Port_C: + t.aLinkPort = linkPort + } +} + func (t *Turnout) bindBoundaryKm(km *proto.Kilometer, port proto.Port) error { switch port { case proto.Port_A: diff --git a/simulation/simulation.go b/simulation/simulation.go new file mode 100644 index 0000000..f7d1d8a --- /dev/null +++ b/simulation/simulation.go @@ -0,0 +1,41 @@ +package simulation + +import ( + "joylink.club/ecs" + "joylink.club/rtsssimulation/repository" +) + +var ( + simulationManager = make(map[ecs.WorldId]*Simulation) +) + +type Simulation struct { + world ecs.World + repo *repository.Repository +} + +func (s *Simulation) getWorld() ecs.World { + return s.world +} + +func (s *Simulation) getRepo() *repository.Repository { + return s.repo +} + +func CreateSimulation(repo *repository.Repository, config *WorldConfig) int { + world := InitializeWorld(config) + sim := &Simulation{ + world: world, + repo: repo, + } + simulationManager[world.Id()] = sim + return int(world.Id()) +} + +func DestroySimulation(id ecs.WorldId) { + delete(simulationManager, id) +} + +func FindSimulation(id ecs.WorldId) *Simulation { + return simulationManager[id] +} diff --git a/util/number.go b/util/number/number.go similarity index 67% rename from util/number.go rename to util/number/number.go index af26f68..e289d68 100644 --- a/util/number.go +++ b/util/number/number.go @@ -1,4 +1,4 @@ -package util +package number type Number interface { ~int | ~int8 | ~int16 | ~int32 | int64 | @@ -13,3 +13,17 @@ func IsBetween[T Number](n T, a T, b T) bool { } return true } + +func Min[T Number](a T, b T) T { + if a <= b { + return a + } + return b +} + +func Max[T Number](a T, b T) T { + if a >= b { + return a + } + return b +}