312 lines
9.0 KiB
Go
312 lines
9.0 KiB
Go
|
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 {
|
||
|
if protoData.Type != proto.CheckPointType_Boundary {
|
||
|
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.Responders {
|
||
|
m := NewResponder(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 := cp.pointType == 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)
|
||
|
}
|
||
|
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)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func buildResponderRelationShip(source *proto.Repository, repository *Repository) error {
|
||
|
for _, protoData := range source.Responders {
|
||
|
responder := repository.responderMap[protoData.Id]
|
||
|
//应答器和区段相互关联
|
||
|
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]
|
||
|
//信号机和区段相互关联
|
||
|
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)
|
||
|
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
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
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 *Responder, section *PhysicalSection) {
|
||
|
responder.bindSection(section)
|
||
|
section.bindDevices(responder)
|
||
|
}
|
||
|
|
||
|
// 相互关联应答器和道岔
|
||
|
func interrelateResponderAndTurnout(responder *Responder, turnout *Turnout, port proto.Port) {
|
||
|
responder.bindTurnoutPort(TurnoutPort{
|
||
|
turnout: turnout,
|
||
|
port: port,
|
||
|
})
|
||
|
turnout.bindDevice(responder, port)
|
||
|
}
|