直接存储Proto的Message;创建仿真时由仿真模块构建模型;发给动力学的数据从仿真模块返回的Repository构建

This commit is contained in:
joylink_zhangsai 2023-09-20 15:14:38 +08:00
parent 25a8b6e47b
commit 4a910aa08f
24 changed files with 1352 additions and 1018 deletions

View File

@ -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)
}

7
go.mod
View File

@ -2,4 +2,9 @@ module joylink.club/rtsssimulation
go 1.20 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

4
go.sum
View File

@ -1,7 +1,7 @@
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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= 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= 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.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=

View File

@ -1,6 +1,6 @@
go 1.20 go 1.20
use ( use (
./jl-ecs-go
. .
./jl-ecs-go
) )

View File

@ -1,6 +1,7 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/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/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/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/hajimehoshi/file2byteslice v1.0.0/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/jezek/xgb v1.0.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/jezek/xgb v1.0.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=

@ -1 +1 @@
Subproject commit adb9cf9a0005fc74565da8753f4f7577834d27d4 Subproject commit c3b9d965c607a2f29e0bdc586aba6851d4f29f13

View File

@ -35,11 +35,18 @@ message CheckPoint{
// //
message Turnout { message Turnout {
enum SwitchMachineType {
Unknown = 0;
ZDJ9_Single = 1;
ZDJ9_Double = 2;
}
string id = 1; string id = 1;
Kilometer km = 2; Kilometer km = 2;
DevicePort aDevicePort = 3; DevicePort aDevicePort = 3;
DevicePort bDevicePort = 4; DevicePort bDevicePort = 4;
DevicePort cDevicePort = 5; DevicePort cDevicePort = 5;
SwitchMachineType switchMachineType = 6;
repeated string relayIds = 7; //
} }
// //
@ -85,7 +92,7 @@ enum DeviceType {
DeviceType_CheckPoint = 2; DeviceType_CheckPoint = 2;
DeviceType_Turnout = 3; DeviceType_Turnout = 3;
DeviceType_Signal = 4; DeviceType_Signal = 4;
DeviceType_Responder = 5; DeviceType_Transponder = 5;
DeviceType_Slope = 6; DeviceType_Slope = 6;
DeviceType_SectionalCurvature = 7; DeviceType_SectionalCurvature = 7;
DeviceType_Link = 8; DeviceType_Link = 8;
@ -125,3 +132,12 @@ enum CheckPointType{
AxleCounter = 1; // AxleCounter = 1; //
InsulatedJoint = 2; // InsulatedJoint = 2; //
} }
message Relay {
enum Type {
Unknown = 0;
}
string id = 1;
string code = 2;
Type type = 3;
}

View File

@ -8,15 +8,20 @@ type Transponder struct {
km *proto.Kilometer km *proto.Kilometer
//section *PhysicalSection //section *PhysicalSection
//turnoutPort TurnoutPort //turnoutPort TurnoutPort
linkPosition *LinkPosition
} }
func NewTransponder(id string, km *proto.Kilometer) *Transponder { func NewTransponder(id string, km *proto.Kilometer) *Transponder {
return &Transponder{ return &Transponder{
Identity: identity{id, proto.DeviceType_DeviceType_Responder}, Identity: identity{id, proto.DeviceType_DeviceType_Transponder},
km: km, km: km,
} }
} }
func (t *Transponder) bindLinkPosition(position *LinkPosition) {
t.linkPosition = position
}
//func (r *Transponder) bindSection(section *PhysicalSection) { //func (r *Transponder) bindSection(section *PhysicalSection) {
// r.section = section // r.section = section
//} //}

View File

@ -6,9 +6,10 @@ import "joylink.club/rtsssimulation/repository/model/proto"
type CheckPoint struct { type CheckPoint struct {
Identity Identity
km *proto.Kilometer km *proto.Kilometer
pointType proto.CheckPointType //检测点类型 pointType proto.CheckPointType //检测点类型
devicePorts []DevicePort //检测点关联的设备及其端口 devicePorts []DevicePort //检测点关联的设备及其端口
linkPosition *LinkPosition
} }
func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointType) *CheckPoint { 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) { func (c *CheckPoint) bindDevicePort(devicePort DevicePort) {
c.devicePorts = append(c.devicePorts, devicePort) c.devicePorts = append(c.devicePorts, devicePort)
} }
func (c *CheckPoint) bindLinkPosition(position *LinkPosition) {
c.linkPosition = position
}

View File

@ -11,14 +11,17 @@ type Link struct {
length int64 length int64
aRelation *LinkNodePort aRelation *TurnoutPort
bRelation *LinkNodePort bRelation *TurnoutPort
aKm *proto.Kilometer aKm *proto.Kilometer
bKm *proto.Kilometer bKm *proto.Kilometer
//Link关联的模型包含LinkNode //Link上的模型非区段边界检测点、应答器、信号机、区段为了位置换算方便
devicePositions []*DeviceLinkPosition devices []Identity
////Link关联的模型包含LinkNode
//devicePositions []*DeviceLinkPosition
} }
var _ Identity = &Link{} 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 { func (l *Link) PortNum() int {
return 2 return 2
} }
func (l *Link) bindDevicePort(port proto.Port, devicePort DevicePort) error { func (l *Link) bindDevicePort(port proto.Port, devicePort DevicePort) error {
linkNodePort, isLinkNodePort := devicePort.(*LinkNodePort) turnoutPort, isTurnoutPort := devicePort.(*TurnoutPort)
if !isLinkNodePort { if !isTurnoutPort {
return errors.New(fmt.Sprintf("Link不能与[%s]类型的设备关联", devicePort.Device().Type())) return errors.New(fmt.Sprintf("Link不能与[%s]类型的设备关联", devicePort.Device().Type()))
} }
switch port { switch port {
case proto.Port_A: case proto.Port_A:
l.aRelation = linkNodePort l.aRelation = turnoutPort
case proto.Port_B: case proto.Port_B:
l.bRelation = linkNodePort l.bRelation = turnoutPort
default: default:
return errors.New(fmt.Sprintf("Link没有端口[%s]", port)) return errors.New(fmt.Sprintf("Link没有端口[%s]", port))
} }
l.bindKm(turnoutPort.turnout.km, port)
return nil return nil
} }
@ -58,9 +78,9 @@ func (l *Link) bindKm(km *proto.Kilometer, port proto.Port) {
} }
} }
func (l *Link) bindDevicesLinkPositions(dlps ...*DeviceLinkPosition) { func (l *Link) bindDevices(devices ...Identity) {
for _, dlp := range dlps { for _, device := range devices {
l.devicePositions = append(l.devicePositions, dlp) l.devices = append(l.devices, device)
} }
} }
@ -91,58 +111,12 @@ type LinkPosition struct {
offset int64 offset int64
} }
// DeviceLinkPosition device在link上的位置 func (l *LinkPosition) Link() *Link {
type DeviceLinkPosition struct { return l.link
device Identity
position LinkPosition
} }
// SlopeLinkSegment Slope在Link上的区间 func (l *LinkPosition) Offset() int64 {
type SlopeLinkSegment struct { return l.offset
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
} }
// link端口 // link端口
@ -166,22 +140,88 @@ func (l *LinkPort) Device() PortedDevice {
return l.link return l.link
} }
type LinkNodePort struct { //// DeviceLinkPosition device在link上的位置
node *LinkNode //type DeviceLinkPosition struct {
port proto.Port // device Identity
} // position LinkPosition
//}
func NewLinkNodePort(node *LinkNode, port proto.Port) *LinkNodePort { //
return &LinkNodePort{ //// SlopeLinkSegment Slope在Link上的区间
node: node, //type SlopeLinkSegment struct {
port: port, // slope *Slope
} // start *LinkPosition
} // end *LinkPosition
//}
func (lp *LinkNodePort) Port() proto.Port { //
return lp.port //func (s *SlopeLinkSegment) Slope() *Slope {
} // return s.slope
//}
func (lp *LinkNodePort) Device() PortedDevice { //
return lp.node //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
//}

View File

@ -28,7 +28,7 @@ const (
DeviceType_DeviceType_CheckPoint DeviceType = 2 DeviceType_DeviceType_CheckPoint DeviceType = 2
DeviceType_DeviceType_Turnout DeviceType = 3 DeviceType_DeviceType_Turnout DeviceType = 3
DeviceType_DeviceType_Signal DeviceType = 4 DeviceType_DeviceType_Signal DeviceType = 4
DeviceType_DeviceType_Responder DeviceType = 5 DeviceType_DeviceType_Transponder DeviceType = 5
DeviceType_DeviceType_Slope DeviceType = 6 DeviceType_DeviceType_Slope DeviceType = 6
DeviceType_DeviceType_SectionalCurvature DeviceType = 7 DeviceType_DeviceType_SectionalCurvature DeviceType = 7
DeviceType_DeviceType_Link DeviceType = 8 DeviceType_DeviceType_Link DeviceType = 8
@ -43,7 +43,7 @@ var (
2: "DeviceType_CheckPoint", 2: "DeviceType_CheckPoint",
3: "DeviceType_Turnout", 3: "DeviceType_Turnout",
4: "DeviceType_Signal", 4: "DeviceType_Signal",
5: "DeviceType_Responder", 5: "DeviceType_Transponder",
6: "DeviceType_Slope", 6: "DeviceType_Slope",
7: "DeviceType_SectionalCurvature", 7: "DeviceType_SectionalCurvature",
8: "DeviceType_Link", 8: "DeviceType_Link",
@ -55,7 +55,7 @@ var (
"DeviceType_CheckPoint": 2, "DeviceType_CheckPoint": 2,
"DeviceType_Turnout": 3, "DeviceType_Turnout": 3,
"DeviceType_Signal": 4, "DeviceType_Signal": 4,
"DeviceType_Responder": 5, "DeviceType_Transponder": 5,
"DeviceType_Slope": 6, "DeviceType_Slope": 6,
"DeviceType_SectionalCurvature": 7, "DeviceType_SectionalCurvature": 7,
"DeviceType_Link": 8, "DeviceType_Link": 8,
@ -239,6 +239,98 @@ func (CheckPointType) EnumDescriptor() ([]byte, []int) {
return file_model_proto_rawDescGZIP(), []int{3} 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 { type Repository struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -508,11 +600,13 @@ type Turnout struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,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"` Km *Kilometer `protobuf:"bytes,2,opt,name=km,proto3" json:"km,omitempty"`
ADevicePort *DevicePort `protobuf:"bytes,3,opt,name=aDevicePort,proto3" json:"aDevicePort,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"` BDevicePort *DevicePort `protobuf:"bytes,4,opt,name=bDevicePort,proto3" json:"bDevicePort,omitempty"`
CDevicePort *DevicePort `protobuf:"bytes,5,opt,name=cDevicePort,proto3" json:"cDevicePort,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() { func (x *Turnout) Reset() {
@ -582,6 +676,20 @@ func (x *Turnout) GetCDevicePort() *DevicePort {
return nil 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 { type Signal struct {
state protoimpl.MessageState state protoimpl.MessageState
@ -1046,6 +1154,69 @@ func (x *KilometerConvert) GetSameTrend() bool {
return false 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 protoreflect.FileDescriptor
var file_model_proto_rawDesc = []byte{ 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x08, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x22, 0x67, 0x0a, 0x05,
0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20,
0x6e, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70,
0x65, 0x5f, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e,
0x6e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
0x65, 0x5f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x16, 0x22, 0x13, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e,
0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x75, 0x72, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x2a, 0x91, 0x02, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x6e, 0x6f, 0x75, 0x74, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79,
0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a,
0x14, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x65, 0x73, 0x70, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x68, 0x79, 0x73, 0x69,
0x6f, 0x6e, 0x64, 0x65, 0x72, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15,
0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x6c, 0x6f, 0x70, 0x65, 0x10, 0x06, 0x12, 0x21, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x68, 0x65, 0x63, 0x6b,
0x1d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63,
0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x75, 0x72, 0x76, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x07, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x75, 0x74, 0x10, 0x03, 0x12,
0x12, 0x13, 0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x15, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69,
0x69, 0x6e, 0x6b, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x67, 0x6e, 0x61, 0x6c, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x10, 0x09, 0x2a, 0x25, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72,
0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x12, 0x05, 0x0a, 0x01, 0x41, 0x10, 0x01, 0x12, 0x05, 0x0a, 0x01, 0x42, 0x10, 0x02, 0x12, 0x05, 0x5f, 0x53, 0x6c, 0x6f, 0x70, 0x65, 0x10, 0x06, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x65, 0x76, 0x69,
0x0a, 0x01, 0x43, 0x10, 0x03, 0x2a, 0x20, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x45, 0x46, 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x75, 0x72, 0x76, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x44,
0x52, 0x49, 0x47, 0x48, 0x54, 0x10, 0x01, 0x2a, 0x43, 0x0a, 0x0e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0x08,
0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x6f, 0x75, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c,
0x6e, 0x64, 0x61, 0x72, 0x79, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x78, 0x6c, 0x65, 0x43, 0x69, 0x6e, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x10, 0x09, 0x2a, 0x25, 0x0a, 0x04, 0x50, 0x6f, 0x72,
0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x75, 0x74, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x41,
0x6c, 0x61, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x42, 0x1a, 0x5a, 0x18, 0x10, 0x01, 0x12, 0x05, 0x0a, 0x01, 0x42, 0x10, 0x02, 0x12, 0x05, 0x0a, 0x01, 0x43, 0x10, 0x03,
0x2e, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x6f, 0x64, 0x2a, 0x20, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a,
0x65, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 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 ( var (
@ -1212,59 +1401,64 @@ func file_model_proto_rawDescGZIP() []byte {
return file_model_proto_rawDescData return file_model_proto_rawDescData
} }
var file_model_proto_enumTypes = make([]protoimpl.EnumInfo, 4) var file_model_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
var file_model_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_model_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_model_proto_goTypes = []interface{}{ var file_model_proto_goTypes = []interface{}{
(DeviceType)(0), // 0: model.DeviceType (DeviceType)(0), // 0: model.DeviceType
(Port)(0), // 1: model.Port (Port)(0), // 1: model.Port
(Direction)(0), // 2: model.Direction (Direction)(0), // 2: model.Direction
(CheckPointType)(0), // 3: model.CheckPointType (CheckPointType)(0), // 3: model.CheckPointType
(*Repository)(nil), // 4: model.Repository (Turnout_SwitchMachineType)(0), // 4: model.Turnout.SwitchMachineType
(*PhysicalSection)(nil), // 5: model.PhysicalSection (Relay_Type)(0), // 5: model.Relay.Type
(*CheckPoint)(nil), // 6: model.CheckPoint (*Repository)(nil), // 6: model.Repository
(*Turnout)(nil), // 7: model.Turnout (*PhysicalSection)(nil), // 7: model.PhysicalSection
(*Signal)(nil), // 8: model.Signal (*CheckPoint)(nil), // 8: model.CheckPoint
(*Transponder)(nil), // 9: model.Transponder (*Turnout)(nil), // 9: model.Turnout
(*Slope)(nil), // 10: model.Slope (*Signal)(nil), // 10: model.Signal
(*SectionalCurvature)(nil), // 11: model.SectionalCurvature (*Transponder)(nil), // 11: model.Transponder
(*DevicePort)(nil), // 12: model.DevicePort (*Slope)(nil), // 12: model.Slope
(*Kilometer)(nil), // 13: model.Kilometer (*SectionalCurvature)(nil), // 13: model.SectionalCurvature
(*KilometerConvert)(nil), // 14: model.KilometerConvert (*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{ var file_model_proto_depIdxs = []int32{
5, // 0: model.Repository.physicalSections:type_name -> model.PhysicalSection 7, // 0: model.Repository.physicalSections:type_name -> model.PhysicalSection
6, // 1: model.Repository.checkPoints:type_name -> model.CheckPoint 8, // 1: model.Repository.checkPoints:type_name -> model.CheckPoint
7, // 2: model.Repository.turnouts:type_name -> model.Turnout 9, // 2: model.Repository.turnouts:type_name -> model.Turnout
8, // 3: model.Repository.signals:type_name -> model.Signal 10, // 3: model.Repository.signals:type_name -> model.Signal
9, // 4: model.Repository.transponders:type_name -> model.Transponder 11, // 4: model.Repository.transponders:type_name -> model.Transponder
10, // 5: model.Repository.slopes:type_name -> model.Slope 12, // 5: model.Repository.slopes:type_name -> model.Slope
11, // 6: model.Repository.sectionalCurvatures:type_name -> model.SectionalCurvature 13, // 6: model.Repository.sectionalCurvatures:type_name -> model.SectionalCurvature
14, // 7: model.Repository.kilometerConverts:type_name -> model.KilometerConvert 16, // 7: model.Repository.kilometerConverts:type_name -> model.KilometerConvert
12, // 8: model.PhysicalSection.aDevicePort:type_name -> model.DevicePort 14, // 8: model.PhysicalSection.aDevicePort:type_name -> model.DevicePort
12, // 9: model.PhysicalSection.bDevicePort:type_name -> model.DevicePort 14, // 9: model.PhysicalSection.bDevicePort:type_name -> model.DevicePort
13, // 10: model.CheckPoint.km:type_name -> model.Kilometer 15, // 10: model.CheckPoint.km:type_name -> model.Kilometer
3, // 11: model.CheckPoint.type:type_name -> model.CheckPointType 3, // 11: model.CheckPoint.type:type_name -> model.CheckPointType
12, // 12: model.CheckPoint.devicePorts:type_name -> model.DevicePort 14, // 12: model.CheckPoint.devicePorts:type_name -> model.DevicePort
13, // 13: model.Turnout.km:type_name -> model.Kilometer 15, // 13: model.Turnout.km:type_name -> model.Kilometer
12, // 14: model.Turnout.aDevicePort:type_name -> model.DevicePort 14, // 14: model.Turnout.aDevicePort:type_name -> model.DevicePort
12, // 15: model.Turnout.bDevicePort:type_name -> model.DevicePort 14, // 15: model.Turnout.bDevicePort:type_name -> model.DevicePort
12, // 16: model.Turnout.cDevicePort:type_name -> model.DevicePort 14, // 16: model.Turnout.cDevicePort:type_name -> model.DevicePort
13, // 17: model.Signal.km:type_name -> model.Kilometer 4, // 17: model.Turnout.switchMachineType:type_name -> model.Turnout.SwitchMachineType
12, // 18: model.Signal.turnoutPort:type_name -> model.DevicePort 15, // 18: model.Signal.km:type_name -> model.Kilometer
13, // 19: model.Transponder.km:type_name -> model.Kilometer 14, // 19: model.Signal.turnoutPort:type_name -> model.DevicePort
12, // 20: model.Transponder.turnoutPort:type_name -> model.DevicePort 15, // 20: model.Transponder.km:type_name -> model.Kilometer
13, // 21: model.Slope.kms:type_name -> model.Kilometer 14, // 21: model.Transponder.turnoutPort:type_name -> model.DevicePort
13, // 22: model.SectionalCurvature.kms:type_name -> model.Kilometer 15, // 22: model.Slope.kms:type_name -> model.Kilometer
0, // 23: model.DevicePort.deviceType:type_name -> model.DeviceType 15, // 23: model.SectionalCurvature.kms:type_name -> model.Kilometer
1, // 24: model.DevicePort.port:type_name -> model.Port 0, // 24: model.DevicePort.deviceType:type_name -> model.DeviceType
2, // 25: model.Kilometer.direction:type_name -> model.Direction 1, // 25: model.DevicePort.port:type_name -> model.Port
13, // 26: model.KilometerConvert.kmA:type_name -> model.Kilometer 2, // 26: model.Kilometer.direction:type_name -> model.Direction
13, // 27: model.KilometerConvert.kmB:type_name -> model.Kilometer 15, // 27: model.KilometerConvert.kmA:type_name -> model.Kilometer
28, // [28:28] is the sub-list for method output_type 15, // 28: model.KilometerConvert.kmB:type_name -> model.Kilometer
28, // [28:28] is the sub-list for method input_type 5, // 29: model.Relay.type:type_name -> model.Relay.Type
28, // [28:28] is the sub-list for extension type_name 30, // [30:30] is the sub-list for method output_type
28, // [28:28] is the sub-list for extension extendee 30, // [30:30] is the sub-list for method input_type
0, // [0:28] is the sub-list for field type_name 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() } func init() { file_model_proto_init() }
@ -1405,14 +1599,26 @@ func file_model_proto_init() {
return nil 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{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_model_proto_rawDesc, RawDescriptor: file_model_proto_rawDesc,
NumEnums: 4, NumEnums: 6,
NumMessages: 11, NumMessages: 12,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@ -17,7 +17,7 @@ type PhysicalSection struct {
aRelation DevicePort aRelation DevicePort
bRelation DevicePort bRelation DevicePort
// 非道岔物理区段A/B端区段边界的公里标 // 非道岔物理区段A/B端的公里标
aKm *proto.Kilometer aKm *proto.Kilometer
bKm *proto.Kilometer bKm *proto.Kilometer
@ -25,6 +25,10 @@ type PhysicalSection struct {
// 关联的设备(目前有信号机、应答器、(非区段边界)检测点) // 关联的设备(目前有信号机、应答器、(非区段边界)检测点)
devices []Identity devices []Identity
//在Link上的区间根据aKm和bKm计算出的
startLinkPosition *LinkPosition
endLinkPosition *LinkPosition
} }
func NewPhysicalSection(id string) *PhysicalSection { 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 { func (s *PhysicalSection) ARelation() DevicePort {
return s.aRelation return s.aRelation
} }
@ -125,6 +137,14 @@ func (s *PhysicalSection) findBoundaryKmByPort(port proto.Port) *proto.Kilometer
return nil return nil
} }
func (s *PhysicalSection) StartLinkPosition() *LinkPosition {
return s.startLinkPosition
}
func (s *PhysicalSection) EndLinkPosition() *LinkPosition {
return s.endLinkPosition
}
type PhysicalSectionPort struct { type PhysicalSectionPort struct {
section *PhysicalSection section *PhysicalSection
port proto.Port port proto.Port

View File

@ -17,10 +17,16 @@ type Repository struct {
slopeMap map[string]*Slope slopeMap map[string]*Slope
sectionalCurvatureMap map[string]*SectionalCurvature 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 kilometerConvertMap map[string]*proto.KilometerConvert
} }
func NewRepository(id string, version string) *Repository { func newRepository(id string, version string) *Repository {
return &Repository{ return &Repository{
id: id, id: id,
version: version, version: version,
@ -32,10 +38,79 @@ func NewRepository(id string, version string) *Repository {
responderMap: make(map[string]*Transponder), responderMap: make(map[string]*Transponder),
slopeMap: make(map[string]*Slope), slopeMap: make(map[string]*Slope),
sectionalCurvatureMap: make(map[string]*SectionalCurvature), 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) { func (repo *Repository) getModel(deviceId string, deviceType proto.DeviceType) (Identity, error) {
switch deviceType { switch deviceType {
case proto.DeviceType_DeviceType_PhysicalSection: case proto.DeviceType_DeviceType_PhysicalSection:
@ -46,73 +121,25 @@ func (repo *Repository) getModel(deviceId string, deviceType proto.DeviceType) (
return repo.turnoutMap[deviceId], nil return repo.turnoutMap[deviceId], nil
case proto.DeviceType_DeviceType_Signal: case proto.DeviceType_DeviceType_Signal:
return repo.signalMap[deviceId], nil return repo.signalMap[deviceId], nil
case proto.DeviceType_DeviceType_Responder: case proto.DeviceType_DeviceType_Transponder:
return repo.responderMap[deviceId], nil return repo.responderMap[deviceId], nil
case proto.DeviceType_DeviceType_Slope: case proto.DeviceType_DeviceType_Slope:
return repo.slopeMap[deviceId], nil return repo.slopeMap[deviceId], nil
case proto.DeviceType_DeviceType_SectionalCurvature: case proto.DeviceType_DeviceType_SectionalCurvature:
return repo.sectionalCurvatureMap[deviceId], nil return repo.sectionalCurvatureMap[deviceId], nil
case proto.DeviceType_DeviceType_Link:
return repo.linkMap[deviceId], nil
default: default:
return nil, errors.New(fmt.Sprintf("仓库中不存在[%s]类型的模型", deviceType)) return nil, errors.New(fmt.Sprintf("仓库中不存在[%s]类型的模型", deviceType))
} }
} }
func (repo *Repository) PhysicalSectionList() []*PhysicalSection { func (repo *Repository) FindLink(id string) *Link {
list := make([]*PhysicalSection, len(repo.physicalSectionMap)) return repo.linkMap[id]
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) AddPhysicalSection(section *PhysicalSection) { func (repo *Repository) AddPhysicalSection(section *PhysicalSection) {
repo.physicalSectionMap[section.Id()] = section 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) { 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 return convert, nil
} }
func buildKilometerConvertKey(cs1 string, cs2 string, dir1 proto.Direction, dir2 proto.Direction) string {
return cs1 + dir1.String() + cs2 + dir2.String()
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -4,8 +4,10 @@ import "joylink.club/rtsssimulation/repository/model/proto"
type SectionalCurvature struct { type SectionalCurvature struct {
Identity Identity
kms []*proto.Kilometer kms []*proto.Kilometer
radius int32 //半径 mm radius int32 //半径 mm
startLinkPosition *LinkPosition
endLinkPosition *LinkPosition
} }
func NewSectionalCurvature(id string, kms []*proto.Kilometer, radius int32) *SectionalCurvature { 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, 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
}

View File

@ -8,6 +8,7 @@ type Signal struct {
km *proto.Kilometer km *proto.Kilometer
//section *PhysicalSection //section *PhysicalSection
//turnoutPort TurnoutPort //turnoutPort TurnoutPort
linkPosition *LinkPosition
} }
func NewSignal(id string, km *proto.Kilometer) *Signal { 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) { //func (s *Signal) bindSection(section *PhysicalSection) {
// s.section = section // s.section = section
//} //}

View File

@ -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
}

View File

@ -5,8 +5,10 @@ import "joylink.club/rtsssimulation/repository/model/proto"
type Slope struct { type Slope struct {
Identity Identity
kms []*proto.Kilometer kms []*proto.Kilometer
degree int32 degree int32
startLinkPosition *LinkPosition
endLinkPosition *LinkPosition
} }
func NewSlope(id string, kms []*proto.Kilometer, degree int32) *Slope { 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, 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
}

View File

@ -15,11 +15,16 @@ type Turnout struct {
// 道岔关联的道岔物理区段 // 道岔关联的道岔物理区段
section *PhysicalSection section *PhysicalSection
// A/B/C端口关联的设备端口 // A/B/C端口关联的设备端口(区段/道岔)
aDevicePort DevicePort aDevicePort DevicePort
bDevicePort DevicePort bDevicePort DevicePort
cDevicePort DevicePort cDevicePort DevicePort
// A/B/C端口关联的Link端口
aLinkPort *LinkPort
bLinkPort *LinkPort
cLinkPort *LinkPort
// A/B/C端口的区段边界的公里标 // A/B/C端口的区段边界的公里标
aKm *proto.Kilometer aKm *proto.Kilometer
bKm *proto.Kilometer bKm *proto.Kilometer
@ -65,6 +70,17 @@ func (t *Turnout) bindDevicePort(port proto.Port, devicePort DevicePort) error {
return nil 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 { func (t *Turnout) bindBoundaryKm(km *proto.Kilometer, port proto.Port) error {
switch port { switch port {
case proto.Port_A: case proto.Port_A:

41
simulation/simulation.go Normal file
View File

@ -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]
}

View File

@ -1,4 +1,4 @@
package util package number
type Number interface { type Number interface {
~int | ~int8 | ~int16 | ~int32 | int64 | ~int | ~int8 | ~int16 | ~int32 | int64 |
@ -13,3 +13,17 @@ func IsBetween[T Number](n T, a T, b T) bool {
} }
return true 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
}