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