rts-sim-module/repository/repository_builder.go

337 lines
9.7 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 {
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)
}