This commit is contained in:
weizhihong 2023-11-02 13:08:38 +08:00
commit d3c2cfd003
30 changed files with 1233 additions and 1040 deletions

114
component/axle_device.go Normal file
View File

@ -0,0 +1,114 @@
package component
import (
"fmt"
"joylink.club/ecs"
)
//计轴设备,管理联锁集中站内的所有计轴区段
//计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态
//计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
//
//当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。
//当RACRJORJT任意一个不为0时终止发送复零/预复零命令。
// AxleSection 计轴物理区段状态
type AxleSection struct {
//true-占用false-出清
Occ bool
}
// AxleSectionFault 计轴区段故障
type AxleSectionFault struct {
//true-设置区段故障占用false-取消区段故障占用
SectionFault bool
}
// AxleCounter 计轴区段计轴器
type AxleCounter struct {
//计轴区段内车轴数
Count int
//记录Count变化波形
countPulse uint8
}
func NewAxleCounter() *AxleCounter {
return &AxleCounter{Count: 0, countPulse: 0}
}
func (c *AxleCounter) UpdateCount(count int) {
cp := to1(c.Count)
np := to1(count)
//
if cp != np {
c.countPulse <<= 1
if np > 0 {
c.countPulse |= np
}
}
c.Count = count
}
func (c *AxleCounter) ResetCountPulse() {
c.countPulse = 0x00
}
func (c *AxleCounter) ShowCountWave() string {
return fmt.Sprintf("%08b", c.countPulse)
}
// IsCount010Pulse true-车进入计轴区段后出清计轴区段
func (c *AxleCounter) IsCount010Pulse() bool {
return c.countPulse&0x01 == 0 && c.countPulse&0x02 > 0 && c.countPulse&0x04 == 0
}
type AxleCounterRuntime struct {
//true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。
Rac bool
//true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
Rjo bool
//true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等
Rjt bool
//true-计轴直接复位
//计轴的轮对计数清零,区段转换为空闲状态
Drst bool
//true-计轴预复位
//将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
Pdrst bool
//true-计轴系统正在执行直接预复位操作
DoingPdrst bool
}
// FaDcAxleDevice 车站计轴管理设备
type FaDcAxleDevice struct {
//区段计轴器列表,实体(AxleCounterType,AxleCounterRuntimeType,AxleSectionFlag)
Counters []*ecs.Entry
//计轴区段实体列表,实体(AxleSectionType,AxleSectionFaultType)
Sections []*ecs.Entry
//key-section id ,value-counter
CounterMap map[string]*ecs.Entry
}
func (f *FaDcAxleDevice) AddAxleSection(counter *ecs.Entry, section *ecs.Entry) {
f.Counters = append(f.Counters, counter)
f.Sections = append(f.Sections, section)
f.CounterMap[AxleSectionFlag.Get(counter).Id] = counter
}
func (f *FaDcAxleDevice) GetAxleCounterEntry(sectionId string) *ecs.Entry {
return f.CounterMap[sectionId]
}
var (
FaDcAxleDeviceType = ecs.NewComponentType[FaDcAxleDevice]()
AxleSectionFaultType = ecs.NewComponentType[AxleSectionFault]()
AxleSectionType = ecs.NewComponentType[AxleSection]()
AxleCounterType = ecs.NewComponentType[AxleCounter]()
AxleCounterRuntimeType = ecs.NewComponentType[AxleCounterRuntime]()
AxleSectionFlag = ecs.NewComponentType[Uid]() //计轴区段id
)
// 归1
func to1(c int) uint8 {
if c > 0 {
return 0x01
} else {
return 0x00
}
}

View File

@ -1,79 +0,0 @@
package component
import "joylink.club/ecs"
// AxleSectionState 计轴区段状态
type AxleSectionState struct {
//true-计轴占用
Occ bool
//true-计轴出清
Clr bool
}
func NewAxleSectionState() *AxleSectionState {
return &AxleSectionState{Clr: true, Occ: false}
}
//计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态
//计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
//
//当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。
//当RACRJORJT任意一个不为0时终止发送复零/预复零命令。
// AxleSectionDevice 计轴区段设备(由几个计轴检测点、一个或多个轨道区段、计轴器运算电路组成)
type AxleSectionDevice struct {
//true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。
Rac bool
//true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
Rjo bool
//true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等
Rjt bool
//true-计轴直接复位
//计轴的轮对计数清零,区段转换为空闲状态
Drst bool
//true-计轴预复位
//将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
Pdrst bool
}
func NewAxleSectionDevice() *AxleSectionDevice {
return &AxleSectionDevice{Rac: false, Rjo: false, Rjt: false, Drst: false, Pdrst: false}
}
// AxleSectionRuntime 计轴区段相关运算中间数据
type AxleSectionRuntime struct {
//true-计轴系统正在执行直接预复位操作
DoingPdrst bool
//true-压道车离开计轴区段
CountTrainOutPulse bool
//true-压道车进入计轴区段
CountTrainInPulse bool
//计轴区段内车轴数
count int16
}
func (s *AxleSectionRuntime) UpdateCountAndPulse(count int16) {
if !s.CountTrainInPulse {
s.CountTrainInPulse = s.count <= 0 && count > 0
}
if !s.CountTrainOutPulse {
s.CountTrainOutPulse = s.count > 0 && count <= 0
}
s.count = count
}
func (s *AxleSectionRuntime) Count() int16 {
return s.count
}
func (s *AxleSectionRuntime) SetCount(count int16) {
s.count = count
}
func NewAxleSectionRuntime() *AxleSectionRuntime {
return &AxleSectionRuntime{DoingPdrst: false, CountTrainInPulse: false, CountTrainOutPulse: false, count: 0}
}
var (
AxleSectionStateType = ecs.NewComponentType[AxleSectionState]()
AxleSectionDeviceType = ecs.NewComponentType[AxleSectionDevice]()
AxleSectionRuntimeType = ecs.NewComponentType[AxleSectionRuntime]()
AxleSectionTag = ecs.NewTag()
)

View File

@ -25,8 +25,7 @@ type PsdState struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Km4 bool `protobuf:"varint,1,opt,name=km4,proto3" json:"km4,omitempty"`
Km8 bool `protobuf:"varint,2,opt,name=km8,proto3" json:"km8,omitempty"`
Close bool `protobuf:"varint,1,opt,name=close,proto3" json:"close,omitempty"`
}
func (x *PsdState) Reset() {
@ -61,16 +60,9 @@ func (*PsdState) Descriptor() ([]byte, []int) {
return file_component_psd_proto_rawDescGZIP(), []int{0}
}
func (x *PsdState) GetKm4() bool {
func (x *PsdState) GetClose() bool {
if x != nil {
return x.Km4
}
return false
}
func (x *PsdState) GetKm8() bool {
if x != nil {
return x.Km8
return x.Close
}
return false
}
@ -80,12 +72,11 @@ var File_component_psd_proto protoreflect.FileDescriptor
var file_component_psd_proto_rawDesc = []byte{
0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x73, 0x64, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74,
0x22, 0x2e, 0x0a, 0x08, 0x50, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03,
0x6b, 0x6d, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6b, 0x6d, 0x34, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x6d, 0x38, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6b, 0x6d, 0x38,
0x42, 0x1d, 0x5a, 0x1b, 0x2e, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2f,
0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x22, 0x20, 0x0a, 0x08, 0x50, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x63, 0x6c, 0x6f, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x63, 0x6c, 0x6f,
0x73, 0x65, 0x42, 0x1d, 0x5a, 0x1b, 0x2e, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e,
0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -1,34 +0,0 @@
package component
import "joylink.club/ecs"
var MkxTag = ecs.NewTag()
var MkxInfoType = ecs.NewComponentType[MkxInfo]()
type MkxInfo struct {
PsdId string
}
var MkxCircuitType = ecs.NewComponentType[MkxCircuit]()
type MkxCircuit struct {
MkxplBtn *ecs.Entry //门控箱旁路按钮
PcbList []*ecs.Entry
Pcbj *ecs.Entry
PobList []*ecs.Entry
Pobj *ecs.Entry
PabList []*ecs.Entry
Pabj *ecs.Entry
}
var MkxCollectionCircuitType = ecs.NewComponentType[MkxCollectionCircuit]()
type MkxCollectionCircuit struct {
PcbXh bool
PobXh bool
PabXh bool
PcbLx bool
PobLx bool
PabLx bool
}

View File

@ -1,11 +0,0 @@
package component
import "joylink.club/ecs"
// PscType 中央控制盘
var PscType = ecs.NewComponentType[Psc]()
type Psc struct {
Mkx *ecs.Entry
Psd *ecs.Entry
}

View File

@ -18,32 +18,21 @@ type PsdCircuit struct {
//屏蔽门表示继电器
MGJ *ecs.Entry
MPLJ *ecs.Entry
//IBP盘上的操作允许/禁止按钮
IbpCz *ecs.Entry
}
var PsdDriveCircuitType = ecs.NewComponentType[PsdDriveCircuit]()
var PsdInterlockDriveCircuitType = ecs.NewComponentType[PsdInterlockDriveCircuit]()
// PsdDriveCircuit 屏蔽门驱动电路
type PsdDriveCircuit struct {
// PsdInterlockDriveCircuit 屏蔽门联锁驱动电路
type PsdInterlockDriveCircuit struct {
//屏蔽门驱动继电器接通状态
GMJ bool
KMJ4 bool
KMJ8 bool
}
var PsdCollectionCircuitType = ecs.NewComponentType[PsdCollectionCircuit]()
type PsdCollectionCircuit struct {
GMJ bool
KMJ4 bool
KMJ8 bool
//MGJ吸起
MGJ_X bool
//MGJ落下
MGJ_L bool
MPLJ_X bool
MPLJ_L bool
}
var AsdTag = ecs.NewTag()
var AsdListType = ecs.NewComponentType[AsdList]()
// AsdList 滑动门列表
@ -55,8 +44,38 @@ var AsdMotorStateType = ecs.NewComponentType[AsdMotorState]()
// AsdMotorState 滑动门电机状态
type AsdMotorState struct {
GM bool //向关门方向转动
TD bool //电机通电
KM bool //向开门方向转动
MG bool //门关闭状态
MK bool //门开启状态
MG bool //门是否关闭(继电器状态)
}
var PlatformMkxCircuitType = ecs.NewComponentType[PlatformMkxCircuit]()
// PlatformMkxCircuit 站台门控箱电路
type PlatformMkxCircuit struct {
MkxList []*ecs.Entry
PCBJ *ecs.Entry
POBJ *ecs.Entry
PABJ *ecs.Entry
}
var MkxType = ecs.NewComponentType[Mkx]()
type Mkx struct {
PCB *ecs.Entry
POB *ecs.Entry
PAB *ecs.Entry
MPL *ecs.Entry
}
var PscType = ecs.NewComponentType[Psc]()
type Psc struct {
InterlockKM4 bool
InterlockKM8 bool
InterlockGM bool
InterlockMPL bool
MkxKM bool
MkxGM bool
}

79
entity/fadc_axle.go Normal file
View File

@ -0,0 +1,79 @@
package entity
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"strings"
)
// LoadAxlePhysicalSections 加载计轴区段
func LoadAxlePhysicalSections(w ecs.World) error {
data := GetWorldData(w)
sections := data.Repo.PhysicalSectionList()
for _, section := range sections {
if is, se := section.IsAxleSection(); se == nil && is {
if len(strings.TrimSpace(section.CentralizedStation())) == 0 {
return fmt.Errorf("区段[%s]未设置所属集中站", section.Id())
}
//fmt.Println("=====>>>>>计轴区段:", section.Id())
fadcDeviceId := CreateFaDcAxleDeviceId(section.CentralizedStation())
fadcDeviceEntry, find := data.EntityMap[fadcDeviceId]
if !find {
fadcDeviceEntry = createFadcDeviceEntity(w, section, data)
data.EntityMap[fadcDeviceId] = fadcDeviceEntry
}
fadcDevice := component.FaDcAxleDeviceType.Get(fadcDeviceEntry)
counter := createAxleCounterEntity(w, section, data)
axleSec := createAxleSectionEntity(w, section, data)
fadcDevice.AddAxleSection(counter, axleSec)
}
}
return nil
}
// 联锁集中站计轴管理设备实体
func createFadcDeviceEntity(w ecs.World, axleSection *repository.PhysicalSection, worldData *component.WorldData) *ecs.Entry {
uid := CreateFaDcAxleDeviceId(axleSection.CentralizedStation())
entry, ok := worldData.EntityMap[uid]
if !ok {
entry = w.Entry(w.Create(component.UidType, component.FaDcAxleDeviceType))
//
component.UidType.SetValue(entry, component.Uid{Id: uid})
component.FaDcAxleDeviceType.Set(entry, &component.FaDcAxleDevice{CounterMap: make(map[string]*ecs.Entry)})
//
worldData.EntityMap[uid] = entry
}
return entry
}
// 计轴区段实体
func createAxleSectionEntity(w ecs.World, axleSection *repository.PhysicalSection, worldData *component.WorldData) *ecs.Entry {
uid := axleSection.Id()
entry, ok := worldData.EntityMap[uid]
if !ok {
entry = w.Entry(w.Create(component.UidType, component.AxleSectionType, component.AxleSectionFaultType))
//
component.UidType.SetValue(entry, component.Uid{Id: uid})
component.AxleSectionType.Set(entry, &component.AxleSection{Occ: false})
component.AxleSectionFaultType.Set(entry, &component.AxleSectionFault{SectionFault: false})
//
worldData.EntityMap[uid] = entry
}
return entry
}
// 计轴器实体
func createAxleCounterEntity(w ecs.World, axleSection *repository.PhysicalSection, worldData *component.WorldData) *ecs.Entry {
entry := w.Entry(w.Create(component.AxleCounterType, component.AxleCounterRuntimeType, component.AxleSectionFlag))
component.AxleCounterType.Set(entry, component.NewAxleCounter())
component.AxleCounterRuntimeType.Set(entry, &component.AxleCounterRuntime{Rac: false, Rjo: false, Rjt: false, Drst: false, Pdrst: false, DoingPdrst: false})
component.AxleSectionFlag.SetValue(entry, component.Uid{Id: axleSection.Id()})
return entry
}
// CreateFaDcAxleDeviceId 设备集中站计轴管理设备id通过联锁集中站centralizedStation来构建
func CreateFaDcAxleDeviceId(centralizedStation string) string {
return fmt.Sprintf("fadc-axle-device-%s", centralizedStation)
}

View File

@ -29,13 +29,8 @@ func Load(w ecs.World, repo *repository.Repository) error {
if err != nil {
return err
}
// 加载门控箱相关试题
err = LoadMkx(w)
if err != nil {
return err
}
// 加载计轴区段相关实体
err = LoadAxleSections(w)
err = LoadAxlePhysicalSections(w)
if err != nil {
return err
}

View File

@ -1,78 +0,0 @@
package entity
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"strings"
)
func LoadMkx(w ecs.World) error {
data := GetWorldData(w)
mkxs := data.Repo.MkxList()
for _, mkx := range mkxs {
entry := NewMkxEntry(w, mkx, data)
loadMkxCircuit(w, entry, mkx, data.EntityMap)
}
return nil
}
func loadMkxCircuit(world ecs.World, entry *ecs.Entry, mkx *repository.Mkx, entryMap map[string]*ecs.Entry) {
if len(mkx.ComponentGroups()) == 0 {
return
}
circuit := &component.MkxCircuit{}
for _, group := range mkx.ComponentGroups() {
for _, ec := range group.Components() {
relay := ec.(*repository.Relay)
if strings.Contains(ec.Code(), "PCBJ") {
circuit.Pcbj = NewRelayEntity(world, relay, entryMap)
} else if strings.Contains(ec.Code(), "POBJ") {
circuit.Pobj = NewRelayEntity(world, relay, entryMap)
} else if strings.Contains(ec.Code(), "PABJ") {
circuit.Pabj = NewRelayEntity(world, relay, entryMap)
} else {
println(fmt.Sprintf("未知的门控箱继电器[%s]", ec.Id()))
}
}
}
for _, button := range mkx.PcbButtons() {
box := NewMkxBox(world, button, entryMap)
circuit.PcbList = append(circuit.PcbList, box)
}
for _, button := range mkx.PobButtons() {
box := NewMkxBox(world, button, entryMap)
circuit.PobList = append(circuit.PobList, box)
}
for _, button := range mkx.PabButtons() {
box := NewMkxBox(world, button, entryMap)
circuit.PabList = append(circuit.PabList, box)
}
component.MkxCircuitType.Set(entry, circuit)
}
func NewMkxEntry(world ecs.World, mkx *repository.Mkx, worldData *component.WorldData) *ecs.Entry {
entry, ok := worldData.EntityMap[mkx.Id()]
if !ok {
entry = world.Entry(world.Create(component.MkxTag, component.UidType, component.MkxInfoType, component.MkxCircuitType,
component.MkxCollectionCircuitType))
component.UidType.SetValue(entry, component.Uid{Id: mkx.Id()})
component.MkxInfoType.SetValue(entry, component.MkxInfo{PsdId: mkx.PsdId()})
worldData.EntityMap[mkx.Id()] = entry
}
return entry
}
func NewMkxBox(world ecs.World, btn *repository.Button, entryMap map[string]*ecs.Entry) *ecs.Entry {
//mplButton := repository.NewButton(btn.Id()+"mpl", "mpl", proto.Button_NO_Reset_Press)
//box := &component.MkxBox{
// Btn: NewButtonEntity(world, btn, entryMap),
// MkxplBtn: NewButtonEntity(world, mplButton, entryMap),
//}
//entry := world.Entry(world.Create(component.MkxBoxType))
//component.MkxBoxType.Set(entry, box)
//component.BitStateType.SetValue(box.MkxplBtn, component.BitState{Val: true})
//return entry
return nil
}

View File

@ -4,8 +4,12 @@ import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"strconv"
)
var PsdBaseComponentTypeArr = []ecs.IComponentType{component.PsdTag, component.UidType,
component.PsdStateType, component.AsdListType, component.PscType}
func LoadPsd(w ecs.World) error {
data := GetWorldData(w)
psds := data.Repo.PsdList()
@ -13,9 +17,27 @@ func LoadPsd(w ecs.World) error {
entry := NewPsdEntry(w, psd, data)
loadPsdCircuit(w, entry, psd, data.EntityMap)
}
pmcMap := make(map[string]*ecs.Entry)
for _, mkx := range data.Repo.MkxList() {
entry := NewMkxEntry(w, data, mkx)
loadPlatformMkxCircuit(w, data.EntityMap, pmcMap, mkx, entry, data.EntityMap[mkx.Psd().Id()])
}
return nil
}
func loadPlatformMkxCircuit(world ecs.World, entryMap map[string]*ecs.Entry, pmcMap map[string]*ecs.Entry,
mkx *repository.Mkx, mkxEntry *ecs.Entry, psdEntry *ecs.Entry) {
platformMkx, ok := pmcMap[mkx.Psd().Id()]
if !ok {
platformMkx = NewPlatformMkxEntry(world, entryMap, mkx)
pmcMap[mkx.Psd().Id()] = platformMkx
}
platformMkxCircuit := component.PlatformMkxCircuitType.Get(platformMkx)
platformMkxCircuit.MkxList = append(platformMkxCircuit.MkxList, mkxEntry)
psdEntry.AddComponent(component.PlatformMkxCircuitType)
component.PlatformMkxCircuitType.Set(psdEntry, platformMkxCircuit)
}
func loadPsdCircuit(world ecs.World, entry *ecs.Entry, psd *repository.Psd, entryMap map[string]*ecs.Entry) {
if len(psd.ComponentGroups()) == 0 {
return
@ -38,16 +60,68 @@ func loadPsdCircuit(world ecs.World, entry *ecs.Entry, psd *repository.Psd, entr
}
}
}
entry.AddComponent(component.PsdCircuitType)
component.PsdCircuitType.Set(entry, circuit)
entry.AddComponent(component.PsdInterlockDriveCircuitType)
}
func NewPsdEntry(world ecs.World, psd *repository.Psd, worldData *component.WorldData) *ecs.Entry {
entry, ok := worldData.EntityMap[psd.Id()]
if !ok {
entry = world.Entry(world.Create(component.PsdTag, component.UidType, component.PsdStateType,
component.PsdDriveCircuitType, component.PsdCollectionCircuitType, component.AsdListType))
entry = world.Entry(world.Create(PsdBaseComponentTypeArr...))
component.UidType.SetValue(entry, component.Uid{Id: psd.Id()})
worldData.EntityMap[psd.Id()] = entry
asdList := &component.AsdList{}
for i := int32(0); i <= psd.AsdAmount(); i++ {
asdList.List = append(asdList.List, NewAsdEntry(world, worldData, psd.Id(), int(i)))
}
component.AsdListType.Set(entry, asdList)
}
return entry
}
func NewAsdEntry(world ecs.World, worldData *component.WorldData, psdId string, asdIndex int) *ecs.Entry {
entry := world.Entry(world.Create(component.AsdTag, component.UidType,
component.AsdMotorStateType, component.TwoPositionTransformType))
uid := psdId + "_" + strconv.Itoa(asdIndex)
worldData.EntityMap[uid] = entry
component.UidType.SetValue(entry, component.Uid{Id: uid})
return entry
}
func NewMkxEntry(world ecs.World, worldData *component.WorldData, mkx *repository.Mkx) *ecs.Entry {
entry := world.Entry(world.Create(component.UidType, component.MkxType))
worldData.EntityMap[mkx.Id()] = entry
component.UidType.SetValue(entry, component.Uid{Id: mkx.Id()})
mkxComponent := &component.Mkx{}
component.MkxType.Set(entry, mkxComponent)
if pcb := mkx.Pcb(); pcb != nil {
mkxComponent.PCB = NewButtonEntity(world, pcb, worldData.EntityMap)
}
if pob := mkx.Pob(); pob != nil {
mkxComponent.POB = NewButtonEntity(world, pob, worldData.EntityMap)
}
if pab := mkx.Pab(); pab != nil {
mkxComponent.PAB = NewButtonEntity(world, pab, worldData.EntityMap)
}
if mpl := mkx.Mpl(); mpl != nil {
mkxComponent.MPL = NewButtonEntity(world, mpl, worldData.EntityMap)
}
return entry
}
func NewPlatformMkxEntry(world ecs.World, entryMap map[string]*ecs.Entry, mkx *repository.Mkx) *ecs.Entry {
entry := world.Entry(world.Create(component.PlatformMkxCircuitType))
circuit := &component.PlatformMkxCircuit{}
if pcbj := mkx.Pcbj(); pcbj != nil {
circuit.PCBJ = NewRelayEntity(world, pcbj, entryMap)
}
if pobj := mkx.Pobj(); pobj != nil {
circuit.POBJ = NewRelayEntity(world, pobj, entryMap)
}
if pabj := mkx.Pabj(); pabj != nil {
circuit.PABJ = NewRelayEntity(world, pabj, entryMap)
}
component.PlatformMkxCircuitType.Set(entry, circuit)
return entry
}

View File

@ -1,32 +0,0 @@
package entity
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
)
// LoadAxleSections 加载计轴区段
func LoadAxleSections(w ecs.World) error {
data := GetWorldData(w)
sections := data.Repo.PhysicalSectionList()
for _, section := range sections {
if is, se := section.IsAxleSection(); se == nil && is {
newAxleSectionEntity(w, section, data)
}
}
return nil
}
func newAxleSectionEntity(w ecs.World, axleSection *repository.PhysicalSection, worldData *component.WorldData) *ecs.Entry {
uid := axleSection.Id()
entry, ok := worldData.EntityMap[uid]
if !ok {
entry = w.Entry(w.Create(component.UidType, component.AxleSectionTag, component.AxleSectionStateType, component.AxleSectionDeviceType, component.AxleSectionRuntimeType))
component.UidType.SetValue(entry, component.Uid{Id: uid})
component.AxleSectionStateType.Set(entry, component.NewAxleSectionState())
component.AxleSectionDeviceType.Set(entry, component.NewAxleSectionDevice())
component.AxleSectionRuntimeType.Set(entry, component.NewAxleSectionRuntime())
worldData.EntityMap[uid] = entry
}
return entry
}

View File

@ -1,53 +0,0 @@
package fi
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
func ClosePsd(world ecs.World, id string) {
worldData := entity.GetWorldData(world)
world.Execute(func() {
entry, ok := worldData.EntityMap[id]
if ok {
psdDriveCircuit := component.PsdDriveCircuitType.Get(entry)
psdDriveCircuit.GMJ = true
psdDriveCircuit.KMJ4 = false
psdDriveCircuit.KMJ8 = false
} else {
fmt.Printf("未找到id=%s的屏蔽门\n", id)
}
})
}
func Km4Psd(world ecs.World, id string) {
worldData := entity.GetWorldData(world)
world.Execute(func() {
entry, ok := worldData.EntityMap[id]
if ok {
psdDriveCircuit := component.PsdDriveCircuitType.Get(entry)
psdDriveCircuit.GMJ = false
psdDriveCircuit.KMJ4 = true
psdDriveCircuit.KMJ8 = false
} else {
fmt.Printf("未找到id=%s的屏蔽门\n", id)
}
})
}
func Km8Psd(world ecs.World, id string) {
worldData := entity.GetWorldData(world)
world.Execute(func() {
entry, ok := worldData.EntityMap[id]
if ok {
psdDriveCircuit := component.PsdDriveCircuitType.Get(entry)
psdDriveCircuit.GMJ = false
psdDriveCircuit.KMJ4 = false
psdDriveCircuit.KMJ8 = true
} else {
fmt.Printf("未找到id=%s的屏蔽门\n", id)
}
})
}

View File

@ -1,55 +1,137 @@
package fi
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// DriveAxleSectionTrainIn 测试:计轴区段中车轴进入
func DriveAxleSectionTrainIn(w ecs.World, axleSectionId string) {
w.Execute(func() {
// AxleSectionDrstDrive 计轴直接复位操作
//
// set : true-设置false-取消
func AxleSectionDrstDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionEntry, ok := wd.EntityMap[axleSectionId]
if ok {
rt := component.AxleSectionRuntimeType.Get(sectionEntry)
rt.UpdateCountAndPulse(1)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
faDcAxleDeviceId := entity.CreateFaDcAxleDeviceId(sectionModel.CentralizedStation())
faDcAxleDeviceEntry, ok := wd.EntityMap[faDcAxleDeviceId]
if !ok {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]不存实体", faDcAxleDeviceId))
}
//
axleCounterEntry := component.FaDcAxleDeviceType.Get(faDcAxleDeviceEntry).GetAxleCounterEntry(sectionId)
if axleCounterEntry == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴器实体", faDcAxleDeviceId, sectionId))
}
axleRuntime := component.AxleCounterRuntimeType.Get(axleCounterEntry)
axleRuntime.Drst = set
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// DriveAxleSectionTrainOut 测试:计轴区段中车轴离开
func DriveAxleSectionTrainOut(w ecs.World, axleSectionId string) {
w.Execute(func() {
// AxleSectionPdrstDrive 计轴预复位操作
//
// set : true-设置false-取消
func AxleSectionPdrstDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionEntry, ok := wd.EntityMap[axleSectionId]
if ok {
rt := component.AxleSectionRuntimeType.Get(sectionEntry)
rt.UpdateCountAndPulse(0)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
faDcAxleDeviceId := entity.CreateFaDcAxleDeviceId(sectionModel.CentralizedStation())
faDcAxleDeviceEntry, ok := wd.EntityMap[faDcAxleDeviceId]
if !ok {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]不存实体", faDcAxleDeviceId))
}
//
axleCounterEntry := component.FaDcAxleDeviceType.Get(faDcAxleDeviceEntry).GetAxleCounterEntry(sectionId)
if axleCounterEntry == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴器实体", faDcAxleDeviceId, sectionId))
}
axleRuntime := component.AxleCounterRuntimeType.Get(axleCounterEntry)
axleRuntime.Pdrst = set
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// DriveAxleSectionDrst 测试:设置计轴区段直接复位
func DriveAxleSectionDrst(w ecs.World, axleSectionId string, drst bool) {
w.Execute(func() {
// AxleSectionFaultOccDrive 区段故障占用设置
//
// set : true - 设置故障占用false - 取消故障占用
func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionEntry, ok := wd.EntityMap[axleSectionId]
if ok {
device := component.AxleSectionDeviceType.Get(sectionEntry)
device.Drst = drst
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
faDcAxleDeviceId := entity.CreateFaDcAxleDeviceId(sectionModel.CentralizedStation())
faDcAxleDeviceEntry, ok := wd.EntityMap[faDcAxleDeviceId]
if !ok {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]不存实体", faDcAxleDeviceId))
}
//
axleCounterEntry := component.FaDcAxleDeviceType.Get(faDcAxleDeviceEntry).GetAxleCounterEntry(sectionId)
axleCounter := component.AxleCounterType.Get(axleCounterEntry)
//
sectionEntry, ok := wd.EntityMap[sectionId]
if !ok {
return ecs.NewErrResult(fmt.Errorf("计轴区段[%s]不存实体", sectionId))
}
sectionFault := component.AxleSectionFaultType.Get(sectionEntry)
//计轴故障设置
sectionFault.SectionFault = set
if set {
axleCounter.UpdateCount(1)
} else {
axleCounter.UpdateCount(0)
}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// DriveAxleSectionPdrst 测试:设置计轴区段预复位
func DriveAxleSectionPdrst(w ecs.World, axleSectionId string, pdrst bool) {
w.Execute(func() {
// AxleSectionTrainDrive 计轴区段内车进入出清设置
//
// trainIn : true - 计轴区段内有车false-计轴区段出清
func AxleSectionTrainDrive(w ecs.World, sectionId string, trainIn bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionEntry, ok := wd.EntityMap[axleSectionId]
if ok {
device := component.AxleSectionDeviceType.Get(sectionEntry)
device.Pdrst = pdrst
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
faDcAxleDeviceId := entity.CreateFaDcAxleDeviceId(sectionModel.CentralizedStation())
faDcAxleDeviceEntry, ok := wd.EntityMap[faDcAxleDeviceId]
if !ok {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]不存实体", faDcAxleDeviceId))
}
//
axleCounterEntry := component.FaDcAxleDeviceType.Get(faDcAxleDeviceEntry).GetAxleCounterEntry(sectionId)
if axleCounterEntry == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴器实体", faDcAxleDeviceId, sectionId))
}
axleCounter := component.AxleCounterType.Get(axleCounterEntry)
if trainIn {
axleCounter.UpdateCount(1)
} else {
axleCounter.UpdateCount(0)
}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}

View File

@ -5,6 +5,5 @@ package component;
option go_package = "./component/component_proto";
message PsdState {
bool km4 = 1;
bool km8 = 2;
bool close = 1;
}

View File

@ -35,6 +35,8 @@ message PhysicalSection {
repeated string turnoutIds = 2; //
DevicePort aDevicePort = 3; //A端关联的设备端口
DevicePort bDevicePort = 4;
//
string centralizedStation = 5;
}
//
@ -85,7 +87,9 @@ message Signal {
message Psd {
string id = 1;
string platformId = 2;
repeated ElectronicComponentGroup electronicComponentGroups = 3; //
int32 asdAmount = 3;
repeated AsdGroup asdGroups = 4;
repeated ElectronicComponentGroup electronicComponentGroups = 5; //
}
//
@ -137,6 +141,7 @@ enum DeviceType {
DeviceType_Station = 16;
DeviceType_Mkx = 17;
DeviceType_Key = 18;
DeviceType_Platform = 19;
}
enum Port {
@ -262,10 +267,12 @@ message ElectronicComponent {
message Mkx {
string id = 1;
string psdId = 2;
repeated string pcbButtonIds = 3;
repeated string pobButtonIds = 4;
repeated string pabButtonIds = 5;
repeated ElectronicComponentGroup electronicComponentGroups = 6; //
string pcbButtonId = 3;
string pobButtonId = 4;
string pabButtonId = 5;
string pcbjId = 6;
string pobjId = 7;
string pabjId = 8;
}
//
message Platform {
@ -275,7 +282,6 @@ message Platform {
string physicalSectionId = 4;
}
//
message Key {
string id = 1;
@ -315,3 +321,10 @@ message QdData {
int32 col = 2; //
repeated string refRelays = 3;//Id
}
//
message AsdGroup {
int32 group = 1; //
int32 start = 2; //
int32 end = 3; //
}

View File

@ -4,39 +4,53 @@ import "joylink.club/rtsssimulation/repository/model/proto"
type Mkx struct {
Identity
psdId string
pcbButtons []*Button
pobButtons []*Button
pabButtons []*Button
componentGroups []*ElectronicComponentGroup
psd *Psd
pcb *Button
pob *Button
pab *Button
mpl *Button
pcbj *Relay
pobj *Relay
pabj *Relay
}
func NewMkx(id string, psdId string) *Mkx {
func NewMkx(id string) *Mkx {
return &Mkx{
Identity: identity{
id: id,
deviceType: proto.DeviceType_DeviceType_Mkx,
},
psdId: psdId,
}
}
func (m *Mkx) PsdId() string {
return m.psdId
func (m *Mkx) Psd() *Psd {
return m.psd
}
func (m *Mkx) PcbButtons() []*Button {
return m.pcbButtons
func (m *Mkx) Pcb() *Button {
return m.pcb
}
func (m *Mkx) PobButtons() []*Button {
return m.pobButtons
func (m *Mkx) Pob() *Button {
return m.pob
}
func (m *Mkx) PabButtons() []*Button {
return m.pabButtons
func (m *Mkx) Pab() *Button {
return m.pab
}
func (m *Mkx) ComponentGroups() []*ElectronicComponentGroup {
return m.componentGroups
func (m *Mkx) Mpl() *Button {
return m.mpl
}
func (m *Mkx) Pcbj() *Relay {
return m.pcbj
}
func (m *Mkx) Pobj() *Relay {
return m.pobj
}
func (m *Mkx) Pabj() *Relay {
return m.pabj
}

View File

@ -42,6 +42,7 @@ const (
DeviceType_DeviceType_Station DeviceType = 16
DeviceType_DeviceType_Mkx DeviceType = 17
DeviceType_DeviceType_Key DeviceType = 18
DeviceType_DeviceType_Platform DeviceType = 19
)
// Enum value maps for DeviceType.
@ -66,6 +67,7 @@ var (
16: "DeviceType_Station",
17: "DeviceType_Mkx",
18: "DeviceType_Key",
19: "DeviceType_Platform",
}
DeviceType_value = map[string]int32{
"DeviceType_Unknown": 0,
@ -87,6 +89,7 @@ var (
"DeviceType_Station": 16,
"DeviceType_Mkx": 17,
"DeviceType_Key": 18,
"DeviceType_Platform": 19,
}
)
@ -829,6 +832,8 @@ type PhysicalSection struct {
TurnoutIds []string `protobuf:"bytes,2,rep,name=turnoutIds,proto3" json:"turnoutIds,omitempty"` //道岔物理区段关联的道岔
ADevicePort *DevicePort `protobuf:"bytes,3,opt,name=aDevicePort,proto3" json:"aDevicePort,omitempty"` //非道岔物理区段A端关联的设备端口
BDevicePort *DevicePort `protobuf:"bytes,4,opt,name=bDevicePort,proto3" json:"bDevicePort,omitempty"`
// 物理区段所属集中站
CentralizedStation string `protobuf:"bytes,5,opt,name=centralizedStation,proto3" json:"centralizedStation,omitempty"`
}
func (x *PhysicalSection) Reset() {
@ -891,6 +896,13 @@ func (x *PhysicalSection) GetBDevicePort() *DevicePort {
return nil
}
func (x *PhysicalSection) GetCentralizedStation() string {
if x != nil {
return x.CentralizedStation
}
return ""
}
// 区段检测点
type CheckPoint struct {
state protoimpl.MessageState
@ -1162,7 +1174,9 @@ type Psd struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
PlatformId string `protobuf:"bytes,2,opt,name=platformId,proto3" json:"platformId,omitempty"`
ElectronicComponentGroups []*ElectronicComponentGroup `protobuf:"bytes,3,rep,name=electronicComponentGroups,proto3" json:"electronicComponentGroups,omitempty"` //关联的电子元件组合
AsdAmount int32 `protobuf:"varint,3,opt,name=asdAmount,proto3" json:"asdAmount,omitempty"`
AsdGroups []*AsdGroup `protobuf:"bytes,4,rep,name=asdGroups,proto3" json:"asdGroups,omitempty"`
ElectronicComponentGroups []*ElectronicComponentGroup `protobuf:"bytes,5,rep,name=electronicComponentGroups,proto3" json:"electronicComponentGroups,omitempty"` //关联的电子元件组合
}
func (x *Psd) Reset() {
@ -1211,6 +1225,20 @@ func (x *Psd) GetPlatformId() string {
return ""
}
func (x *Psd) GetAsdAmount() int32 {
if x != nil {
return x.AsdAmount
}
return 0
}
func (x *Psd) GetAsdGroups() []*AsdGroup {
if x != nil {
return x.AsdGroups
}
return nil
}
func (x *Psd) GetElectronicComponentGroups() []*ElectronicComponentGroup {
if x != nil {
return x.ElectronicComponentGroups
@ -2162,10 +2190,12 @@ type Mkx struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
PsdId string `protobuf:"bytes,2,opt,name=psdId,proto3" json:"psdId,omitempty"`
PcbButtonIds []string `protobuf:"bytes,3,rep,name=pcbButtonIds,proto3" json:"pcbButtonIds,omitempty"`
PobButtonIds []string `protobuf:"bytes,4,rep,name=pobButtonIds,proto3" json:"pobButtonIds,omitempty"`
PabButtonIds []string `protobuf:"bytes,5,rep,name=pabButtonIds,proto3" json:"pabButtonIds,omitempty"`
ElectronicComponentGroups []*ElectronicComponentGroup `protobuf:"bytes,6,rep,name=electronicComponentGroups,proto3" json:"electronicComponentGroups,omitempty"` // 关联的电子元件组合
PcbButtonId string `protobuf:"bytes,3,opt,name=pcbButtonId,proto3" json:"pcbButtonId,omitempty"`
PobButtonId string `protobuf:"bytes,4,opt,name=pobButtonId,proto3" json:"pobButtonId,omitempty"`
PabButtonId string `protobuf:"bytes,5,opt,name=pabButtonId,proto3" json:"pabButtonId,omitempty"`
PcbjId string `protobuf:"bytes,6,opt,name=pcbjId,proto3" json:"pcbjId,omitempty"`
PobjId string `protobuf:"bytes,7,opt,name=pobjId,proto3" json:"pobjId,omitempty"`
PabjId string `protobuf:"bytes,8,opt,name=pabjId,proto3" json:"pabjId,omitempty"`
}
func (x *Mkx) Reset() {
@ -2214,32 +2244,46 @@ func (x *Mkx) GetPsdId() string {
return ""
}
func (x *Mkx) GetPcbButtonIds() []string {
func (x *Mkx) GetPcbButtonId() string {
if x != nil {
return x.PcbButtonIds
return x.PcbButtonId
}
return nil
return ""
}
func (x *Mkx) GetPobButtonIds() []string {
func (x *Mkx) GetPobButtonId() string {
if x != nil {
return x.PobButtonIds
return x.PobButtonId
}
return nil
return ""
}
func (x *Mkx) GetPabButtonIds() []string {
func (x *Mkx) GetPabButtonId() string {
if x != nil {
return x.PabButtonIds
return x.PabButtonId
}
return nil
return ""
}
func (x *Mkx) GetElectronicComponentGroups() []*ElectronicComponentGroup {
func (x *Mkx) GetPcbjId() string {
if x != nil {
return x.ElectronicComponentGroups
return x.PcbjId
}
return nil
return ""
}
func (x *Mkx) GetPobjId() string {
if x != nil {
return x.PobjId
}
return ""
}
func (x *Mkx) GetPabjId() string {
if x != nil {
return x.PabjId
}
return ""
}
// 站台
@ -2631,6 +2675,70 @@ func (x *QdData) GetRefRelays() []string {
return nil
}
// 滑动门编组
type AsdGroup struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Group int32 `protobuf:"varint,1,opt,name=group,proto3" json:"group,omitempty"` //编组
Start int32 `protobuf:"varint,2,opt,name=start,proto3" json:"start,omitempty"` //起始子门索引
End int32 `protobuf:"varint,3,opt,name=end,proto3" json:"end,omitempty"` //终止子门索引
}
func (x *AsdGroup) Reset() {
*x = AsdGroup{}
if protoimpl.UnsafeEnabled {
mi := &file_model_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AsdGroup) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AsdGroup) ProtoMessage() {}
func (x *AsdGroup) ProtoReflect() protoreflect.Message {
mi := &file_model_proto_msgTypes[28]
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 AsdGroup.ProtoReflect.Descriptor instead.
func (*AsdGroup) Descriptor() ([]byte, []int) {
return file_model_proto_rawDescGZIP(), []int{28}
}
func (x *AsdGroup) GetGroup() int32 {
if x != nil {
return x.Group
}
return 0
}
func (x *AsdGroup) GetStart() int32 {
if x != nil {
return x.Start
}
return 0
}
func (x *AsdGroup) GetEnd() int32 {
if x != nil {
return x.End
}
return 0
}
var File_model_proto protoreflect.FileDescriptor
var file_model_proto_rawDesc = []byte{
@ -2702,7 +2810,7 @@ var file_model_proto_rawDesc = []byte{
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x7a, 0x65,
0x64, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x52, 0x16, 0x43, 0x65, 0x6e,
0x74, 0x72, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x66, 0x73, 0x22, 0xab, 0x01, 0x0a, 0x0f, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c,
0x65, 0x66, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x0f, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c,
0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x75, 0x72, 0x6e, 0x6f,
0x75, 0x74, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x75, 0x72,
@ -2713,7 +2821,10 @@ var file_model_proto_rawDesc = []byte{
0x62, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 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, 0x62, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72,
0x74, 0x22, 0x9e, 0x01, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74,
0x74, 0x12, 0x2e, 0x0a, 0x12, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64,
0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63,
0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x22, 0x9e, 0x01, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x20, 0x0a, 0x02, 0x6b, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d,
0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x02,
@ -2775,146 +2886,149 @@ var file_model_proto_rawDesc = []byte{
0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x48, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x48, 0x4c,
0x55, 0x5f, 0x46, 0x55, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x48, 0x4c, 0x55, 0x5f, 0x46, 0x4c,
0x10, 0x03, 0x12, 0x06, 0x0a, 0x02, 0x41, 0x42, 0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x48, 0x42,
0x55, 0x10, 0x05, 0x22, 0x94, 0x01, 0x0a, 0x03, 0x50, 0x73, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x55, 0x10, 0x05, 0x22, 0xe1, 0x01, 0x0a, 0x03, 0x50, 0x73, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0a, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64, 0x12, 0x5d, 0x0a, 0x19, 0x65,
0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65,
0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f,
0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69,
0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52,
0x19, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
0x6e, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0b, 0x54,
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x02, 0x6b, 0x6d,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b,
0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x02, 0x6b, 0x6d, 0x12, 0x1c, 0x0a, 0x09,
0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x0b, 0x74, 0x75,
0x72, 0x6e, 0x6f, 0x75, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 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, 0x74, 0x75, 0x72, 0x6e, 0x6f, 0x75, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x22,
0x53, 0x0a, 0x05, 0x53, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x03, 0x6b, 0x6d, 0x73, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69,
0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06,
0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x65,
0x67, 0x72, 0x65, 0x65, 0x22, 0x60, 0x0a, 0x12, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61,
0x6c, 0x43, 0x75, 0x72, 0x76, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x03, 0x6b, 0x6d,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e,
0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x6d, 0x73, 0x12, 0x16,
0x0a, 0x06, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06,
0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x22, 0x7c, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64,
0x12, 0x31, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x0b, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x04,
0x70, 0x6f, 0x72, 0x74, 0x22, 0x7d, 0x0a, 0x09, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65,
0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6f, 0x72, 0x64,
0x69, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x10, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x79, 0x73,
0x74, 0x65, 0x6d, 0x12, 0x2e, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44,
0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x22, 0x78, 0x0a, 0x10, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72,
0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x03, 0x6b, 0x6d, 0x41, 0x18, 0x01,
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, 0x41, 0x12, 0x22, 0x0a, 0x03, 0x6b,
0x6d, 0x42, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
0x2e, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x6d, 0x42, 0x12,
0x1c, 0x0a, 0x09, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01,
0x28, 0x08, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x22, 0xeb, 0x01,
0x0a, 0x05, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d,
0x6f, 0x64, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x6d, 0x6f, 0x64,
0x65, 0x6c, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x05,
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x93, 0x01, 0x0a, 0x05, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12,
0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09,
0x4a, 0x50, 0x58, 0x43, 0x5f, 0x31, 0x30, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
0x50, 0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57,
0x4a, 0x58, 0x43, 0x5f, 0x34, 0x38, 0x30, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x57, 0x4a,
0x58, 0x43, 0x5f, 0x48, 0x31, 0x32, 0x35, 0x5f, 0x38, 0x30, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09,
0x4a, 0x57, 0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
0x57, 0x58, 0x43, 0x5f, 0x48, 0x33, 0x34, 0x30, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x59,
0x4a, 0x58, 0x43, 0x5f, 0x31, 0x36, 0x30, 0x5f, 0x32, 0x36, 0x30, 0x10, 0x07, 0x12, 0x0c, 0x0a,
0x08, 0x4a, 0x5a, 0x58, 0x43, 0x5f, 0x48, 0x31, 0x38, 0x10, 0x08, 0x22, 0x3b, 0x0a, 0x15, 0x50,
0x68, 0x61, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65,
0x63, 0x74, 0x6f, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x52, 0x0a, 0x18, 0x45, 0x6c, 0x65, 0x63,
0x0a, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61,
0x73, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
0x61, 0x73, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x09, 0x61, 0x73, 0x64,
0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d,
0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x41, 0x73, 0x64, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x09, 0x61,
0x73, 0x64, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x5d, 0x0a, 0x19, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x47,
0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x70,
0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c,
0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x73, 0x22, 0xef, 0x01, 0x0a,
0x06, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x38, 0x0a, 0x0a, 0x62,
0x75, 0x74, 0x74, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x18, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2e, 0x42,
0x75, 0x74, 0x74, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x62, 0x75, 0x74, 0x74, 0x6f,
0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x4c, 0x69, 0x67, 0x68,
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x68, 0x61, 0x73, 0x4c, 0x69, 0x67, 0x68,
0x74, 0x22, 0x6b, 0x0a, 0x0a, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12,
0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e,
0x4e, 0x4f, 0x5f, 0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x50, 0x72, 0x65, 0x73, 0x73, 0x10, 0x01,
0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x5f, 0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x55, 0x70, 0x10,
0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x50, 0x72, 0x65, 0x73, 0x73,
0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x55, 0x70, 0x10, 0x04,
0x12, 0x0c, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x5f, 0x4b, 0x6e, 0x6f, 0x62, 0x10, 0x05, 0x22, 0x97,
0x01, 0x0a, 0x05, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x30, 0x0a, 0x06,
0x61, 0x73, 0x70, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d,
0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74,
0x41, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x06, 0x61, 0x73, 0x70, 0x65, 0x63, 0x74, 0x22, 0x38,
0x0a, 0x0b, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x41, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x05, 0x0a,
0x01, 0x4c, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x48, 0x10, 0x01, 0x12, 0x05, 0x0a, 0x01, 0x55,
0x10, 0x02, 0x12, 0x06, 0x0a, 0x02, 0x48, 0x55, 0x10, 0x03, 0x12, 0x05, 0x0a, 0x01, 0x42, 0x10,
0x04, 0x12, 0x05, 0x0a, 0x01, 0x41, 0x10, 0x05, 0x22, 0x2b, 0x0a, 0x05, 0x41, 0x6c, 0x61, 0x72,
0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x6f,
0x64, 0x65, 0x6c, 0x2e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f,
0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x19, 0x65, 0x6c,
0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e,
0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e,
0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x02, 0x6b, 0x6d, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69, 0x6c, 0x6f,
0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x02, 0x6b, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x0b, 0x74, 0x75, 0x72, 0x6e, 0x6f,
0x75, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 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, 0x74, 0x75, 0x72, 0x6e, 0x6f, 0x75, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x53, 0x0a, 0x05,
0x53, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x03, 0x6b, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69, 0x6c, 0x6f, 0x6d,
0x65, 0x74, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x67,
0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x65, 0x67, 0x72, 0x65,
0x65, 0x22, 0x60, 0x0a, 0x12, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x75,
0x72, 0x76, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x03, 0x6b, 0x6d, 0x73, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69, 0x6c,
0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72,
0x61, 0x64, 0x69, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, 0x61, 0x64,
0x69, 0x75, 0x73, 0x22, 0x7c, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72,
0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x31, 0x0a,
0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x12, 0x1f, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b,
0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x70, 0x6f, 0x72,
0x74, 0x22, 0x7d, 0x0a, 0x09, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x14,
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61,
0x74, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10,
0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x12, 0x2e, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x69, 0x72, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x78, 0x0a, 0x10, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e,
0x76, 0x65, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x03, 0x6b, 0x6d, 0x41, 0x18, 0x01, 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, 0x41, 0x12, 0x22, 0x0a, 0x03, 0x6b, 0x6d, 0x42, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x4b, 0x69,
0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x6d, 0x42, 0x12, 0x1c, 0x0a, 0x09,
0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
0x09, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x6e, 0x64, 0x22, 0xeb, 0x01, 0x0a, 0x05, 0x52,
0x65, 0x6c, 0x61, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65,
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e,
0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x05, 0x6d, 0x6f, 0x64,
0x65, 0x6c, 0x22, 0x93, 0x01, 0x0a, 0x05, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x0b, 0x0a, 0x07,
0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x50, 0x58,
0x43, 0x5f, 0x31, 0x30, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x50, 0x58, 0x43,
0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x4a, 0x58, 0x43,
0x5f, 0x34, 0x38, 0x30, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x57, 0x4a, 0x58, 0x43, 0x5f,
0x48, 0x31, 0x32, 0x35, 0x5f, 0x38, 0x30, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x58,
0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x58, 0x43,
0x5f, 0x48, 0x33, 0x34, 0x30, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x59, 0x4a, 0x58, 0x43,
0x5f, 0x31, 0x36, 0x30, 0x5f, 0x32, 0x36, 0x30, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x4a, 0x5a,
0x58, 0x43, 0x5f, 0x48, 0x31, 0x38, 0x10, 0x08, 0x22, 0x3b, 0x0a, 0x15, 0x50, 0x68, 0x61, 0x73,
0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x6f,
0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x6f, 0x0a, 0x07, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x63, 0x6f, 0x64, 0x65, 0x12, 0x40, 0x0a, 0x0f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e,
0x69, 0x63, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e,
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63,
0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69,
0x63, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x61, 0x0a, 0x0f, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72,
0x6f, 0x6e, 0x69, 0x63, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3a, 0x0a,
0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72,
0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x63,
0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x58, 0x0a, 0x13, 0x45, 0x6c, 0x65,
0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x31, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x22, 0xf6, 0x01, 0x0a, 0x03, 0x4d, 0x6b, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x70,
0x73, 0x64, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x73, 0x64, 0x49,
0x64, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x63, 0x62, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x64,
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x63, 0x62, 0x42, 0x75, 0x74, 0x74,
0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x6f, 0x62, 0x42, 0x75, 0x74, 0x74,
0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6f, 0x62,
0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x61, 0x62,
0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
0x0c, 0x70, 0x61, 0x62, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x5d, 0x0a,
0x19, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
0x6e, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x1f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f,
0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x52, 0x0a, 0x18, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f,
0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75,
0x70, 0x52, 0x19, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d,
0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x7a, 0x0a, 0x08,
0x70, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65,
0x6e, 0x74, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6d,
0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x73, 0x22, 0xef, 0x01, 0x0a, 0x06, 0x42, 0x75,
0x74, 0x74, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x38, 0x0a, 0x0a, 0x62, 0x75, 0x74, 0x74,
0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d,
0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2e, 0x42, 0x75, 0x74, 0x74,
0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x54, 0x79,
0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04,
0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x68, 0x61, 0x73, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x22, 0x6b,
0x0a, 0x0a, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07,
0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4e, 0x4f, 0x5f,
0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x50, 0x72, 0x65, 0x73, 0x73, 0x10, 0x01, 0x12, 0x0f, 0x0a,
0x0b, 0x4e, 0x4f, 0x5f, 0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x55, 0x70, 0x10, 0x02, 0x12, 0x0f,
0x0a, 0x0b, 0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x50, 0x72, 0x65, 0x73, 0x73, 0x10, 0x03, 0x12,
0x0c, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x55, 0x70, 0x10, 0x04, 0x12, 0x0c, 0x0a,
0x08, 0x4b, 0x65, 0x79, 0x5f, 0x4b, 0x6e, 0x6f, 0x62, 0x10, 0x05, 0x22, 0x97, 0x01, 0x0a, 0x05,
0x4c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x61, 0x73, 0x70,
0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x64, 0x65,
0x6c, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x41, 0x73, 0x70,
0x65, 0x63, 0x74, 0x52, 0x06, 0x61, 0x73, 0x70, 0x65, 0x63, 0x74, 0x22, 0x38, 0x0a, 0x0b, 0x4c,
0x69, 0x67, 0x68, 0x74, 0x41, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x05, 0x0a, 0x01, 0x4c, 0x10,
0x00, 0x12, 0x05, 0x0a, 0x01, 0x48, 0x10, 0x01, 0x12, 0x05, 0x0a, 0x01, 0x55, 0x10, 0x02, 0x12,
0x06, 0x0a, 0x02, 0x48, 0x55, 0x10, 0x03, 0x12, 0x05, 0x0a, 0x01, 0x42, 0x10, 0x04, 0x12, 0x05,
0x0a, 0x01, 0x41, 0x10, 0x05, 0x22, 0x2b, 0x0a, 0x05, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x12, 0x0e,
0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12,
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
0x64, 0x65, 0x22, 0x6f, 0x0a, 0x07, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64,
0x65, 0x12, 0x40, 0x0a, 0x0f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x47,
0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64,
0x65, 0x6c, 0x2e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x47, 0x72, 0x6f,
0x75, 0x70, 0x52, 0x0f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x47, 0x72,
0x6f, 0x75, 0x70, 0x22, 0x61, 0x0a, 0x0f, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69,
0x63, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f,
0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69,
0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70,
0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x58, 0x0a, 0x13, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72,
0x6f, 0x6e, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x31, 0x0a,
0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x22, 0xd9, 0x01, 0x0a, 0x03, 0x4d, 0x6b, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x73, 0x64, 0x49,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x73, 0x64, 0x49, 0x64, 0x12, 0x20,
0x0a, 0x0b, 0x70, 0x63, 0x62, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x63, 0x62, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x64,
0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6f, 0x62, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x64, 0x18,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6f, 0x62, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e,
0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x62, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49,
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x62, 0x42, 0x75, 0x74, 0x74,
0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x63, 0x62, 0x6a, 0x49, 0x64, 0x18, 0x06,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x63, 0x62, 0x6a, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06,
0x70, 0x6f, 0x62, 0x6a, 0x49, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f,
0x62, 0x6a, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x62, 0x6a, 0x49, 0x64, 0x18, 0x08,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x62, 0x6a, 0x49, 0x64, 0x22, 0x7a, 0x0a, 0x08,
0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09,
@ -2955,49 +3069,55 @@ var file_model_proto_rawDesc = []byte{
0x72, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x6f, 0x77, 0x12, 0x10,
0x0a, 0x03, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x63, 0x6f, 0x6c,
0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20,
0x03, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x2a, 0xe4,
0x03, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a,
0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e,
0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x5f, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x5f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02,
0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54,
0x75, 0x72, 0x6e, 0x6f, 0x75, 0x74, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x10, 0x04, 0x12,
0x1a, 0x0a, 0x16, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72,
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x6c, 0x6f, 0x70, 0x65, 0x10,
0x06, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x75, 0x72, 0x76, 0x61, 0x74, 0x75,
0x72, 0x65, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79,
0x70, 0x65, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x4e, 0x6f, 0x64, 0x65,
0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x5f, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x10, 0x0a, 0x12, 0x24, 0x0a, 0x20, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x68, 0x61, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c,
0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x10, 0x0b, 0x12, 0x15,
0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x75, 0x74,
0x74, 0x6f, 0x6e, 0x10, 0x0c, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x10,
0x0e, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
0x50, 0x73, 0x64, 0x10, 0x0f, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x10, 0x12, 0x12, 0x0a,
0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6b, 0x78, 0x10,
0x11, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
0x4b, 0x65, 0x79, 0x10, 0x12, 0x2a, 0x25, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x08, 0x0a,
0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x41, 0x10, 0x01, 0x12, 0x05,
0x0a, 0x01, 0x42, 0x10, 0x02, 0x12, 0x05, 0x0a, 0x01, 0x43, 0x10, 0x03, 0x2a, 0x20, 0x0a, 0x09,
0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x45, 0x46,
0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x49, 0x47, 0x48, 0x54, 0x10, 0x01, 0x2a, 0x43,
0x0a, 0x0e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65,
0x12, 0x0c, 0x0a, 0x08, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x10, 0x00, 0x12, 0x0f,
0x0a, 0x0b, 0x41, 0x78, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x10, 0x01, 0x12,
0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x69, 0x6e,
0x74, 0x10, 0x02, 0x42, 0x1a, 0x5a, 0x18, 0x2e, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x03, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0x48,
0x0a, 0x08, 0x41, 0x73, 0x64, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72,
0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70,
0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x2a, 0xfd, 0x03, 0x0a, 0x0a, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12,
0x1e, 0x0a, 0x1a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x68,
0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x01, 0x12,
0x19, 0x0a, 0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x68,
0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65,
0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x75, 0x74,
0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x5f, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x6e,
0x64, 0x65, 0x72, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x5f, 0x53, 0x6c, 0x6f, 0x70, 0x65, 0x10, 0x06, 0x12, 0x21, 0x0a, 0x1d, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x61, 0x6c, 0x43, 0x75, 0x72, 0x76, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x07, 0x12, 0x13,
0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x6e,
0x6b, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70,
0x65, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x65, 0x6c, 0x61, 0x79,
0x10, 0x0a, 0x12, 0x24, 0x0a, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x5f, 0x50, 0x68, 0x61, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f,
0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x10, 0x0b, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x10, 0x0c, 0x12,
0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69,
0x67, 0x68, 0x74, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x5f, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x10, 0x0e, 0x12, 0x12, 0x0a, 0x0e, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x73, 0x64, 0x10, 0x0f, 0x12,
0x16, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x10, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6b, 0x78, 0x10, 0x11, 0x12, 0x12, 0x0a, 0x0e, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4b, 0x65, 0x79, 0x10, 0x12, 0x12,
0x17, 0x0a, 0x13, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x10, 0x13, 0x2a, 0x25, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74,
0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x41, 0x10,
0x01, 0x12, 0x05, 0x0a, 0x01, 0x42, 0x10, 0x02, 0x12, 0x05, 0x0a, 0x01, 0x43, 0x10, 0x03, 0x2a,
0x20, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04,
0x4c, 0x45, 0x46, 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x49, 0x47, 0x48, 0x54, 0x10,
0x01, 0x2a, 0x43, 0x0a, 0x0e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54,
0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x10,
0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x78, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4a,
0x6f, 0x69, 0x6e, 0x74, 0x10, 0x02, 0x42, 0x1a, 0x5a, 0x18, 0x2e, 0x2f, 0x72, 0x65, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -3013,7 +3133,7 @@ func file_model_proto_rawDescGZIP() []byte {
}
var file_model_proto_enumTypes = make([]protoimpl.EnumInfo, 10)
var file_model_proto_msgTypes = make([]protoimpl.MessageInfo, 28)
var file_model_proto_msgTypes = make([]protoimpl.MessageInfo, 29)
var file_model_proto_goTypes = []interface{}{
(DeviceType)(0), // 0: model.DeviceType
(Port)(0), // 1: model.Port
@ -3053,6 +3173,7 @@ var file_model_proto_goTypes = []interface{}{
(*CjData)(nil), // 35: model.CjData
(*CjDataItem)(nil), // 36: model.CjDataItem
(*QdData)(nil), // 37: model.QdData
(*AsdGroup)(nil), // 38: model.AsdGroup
}
var file_model_proto_depIdxs = []int32{
11, // 0: model.Repository.physicalSections:type_name -> model.PhysicalSection
@ -3089,23 +3210,23 @@ var file_model_proto_depIdxs = []int32{
19, // 31: model.Signal.turnoutPort:type_name -> model.DevicePort
24, // 32: model.Signal.electronicComponentGroups:type_name -> model.ElectronicComponentGroup
5, // 33: model.Signal.model:type_name -> model.Signal.Model
24, // 34: model.Psd.electronicComponentGroups:type_name -> model.ElectronicComponentGroup
20, // 35: model.Transponder.km:type_name -> model.Kilometer
19, // 36: model.Transponder.turnoutPort:type_name -> model.DevicePort
20, // 37: model.Slope.kms:type_name -> model.Kilometer
20, // 38: model.SectionalCurvature.kms:type_name -> model.Kilometer
0, // 39: model.DevicePort.deviceType:type_name -> model.DeviceType
1, // 40: model.DevicePort.port:type_name -> model.Port
2, // 41: model.Kilometer.direction:type_name -> model.Direction
20, // 42: model.KilometerConvert.kmA:type_name -> model.Kilometer
20, // 43: model.KilometerConvert.kmB:type_name -> model.Kilometer
6, // 44: model.Relay.model:type_name -> model.Relay.Model
7, // 45: model.Button.buttonType:type_name -> model.Button.ButtonType
8, // 46: model.Light.aspect:type_name -> model.Light.LightAspect
29, // 47: model.Station.electronicGroup:type_name -> model.ElectronicGroup
30, // 48: model.ElectronicGroup.components:type_name -> model.ElectronicComponent
0, // 49: model.ElectronicComponent.deviceType:type_name -> model.DeviceType
24, // 50: model.Mkx.electronicComponentGroups:type_name -> model.ElectronicComponentGroup
38, // 34: model.Psd.asdGroups:type_name -> model.AsdGroup
24, // 35: model.Psd.electronicComponentGroups:type_name -> model.ElectronicComponentGroup
20, // 36: model.Transponder.km:type_name -> model.Kilometer
19, // 37: model.Transponder.turnoutPort:type_name -> model.DevicePort
20, // 38: model.Slope.kms:type_name -> model.Kilometer
20, // 39: model.SectionalCurvature.kms:type_name -> model.Kilometer
0, // 40: model.DevicePort.deviceType:type_name -> model.DeviceType
1, // 41: model.DevicePort.port:type_name -> model.Port
2, // 42: model.Kilometer.direction:type_name -> model.Direction
20, // 43: model.KilometerConvert.kmA:type_name -> model.Kilometer
20, // 44: model.KilometerConvert.kmB:type_name -> model.Kilometer
6, // 45: model.Relay.model:type_name -> model.Relay.Model
7, // 46: model.Button.buttonType:type_name -> model.Button.ButtonType
8, // 47: model.Light.aspect:type_name -> model.Light.LightAspect
29, // 48: model.Station.electronicGroup:type_name -> model.ElectronicGroup
30, // 49: model.ElectronicGroup.components:type_name -> model.ElectronicComponent
0, // 50: model.ElectronicComponent.deviceType:type_name -> model.DeviceType
35, // 51: model.CentralizedStationRef.cjList:type_name -> model.CjData
37, // 52: model.CentralizedStationRef.qdList:type_name -> model.QdData
36, // 53: model.CjData.refRelays:type_name -> model.CjDataItem
@ -3459,6 +3580,18 @@ func file_model_proto_init() {
return nil
}
}
file_model_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AsdGroup); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -3466,7 +3599,7 @@ func file_model_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_model_proto_rawDesc,
NumEnums: 10,
NumMessages: 28,
NumMessages: 29,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -33,6 +33,9 @@ type PhysicalSection struct {
//在Link上的区间根据aKm和bKm计算出的start的offset一定小于end的offset
startLinkPosition *LinkPosition
endLinkPosition *LinkPosition
//物理区段所属集中站
centralizedStation string
}
func NewPhysicalSection(id string) *PhysicalSection {
@ -97,6 +100,9 @@ func (s *PhysicalSection) IsAxleSection() (bool, error) {
return false, fmt.Errorf("物理区段没有检测点")
}
}
func (s *PhysicalSection) CentralizedStation() string {
return s.centralizedStation
}
func (s *PhysicalSection) bindDevicePort(port proto.Port, devicePort DevicePort) error {
_, isSectionPort := devicePort.(*PhysicalSectionPort)
_, isTurnoutPort := devicePort.(*TurnoutPort)

24
repository/platform.go Normal file
View File

@ -0,0 +1,24 @@
package repository
import "joylink.club/rtsssimulation/repository/model/proto"
type Platform struct {
Identity
code string
station *Station
}
func NewPlatform(id string) *Platform {
return &Platform{Identity: identity{
id: id,
deviceType: proto.DeviceType_DeviceType_Platform,
}}
}
func (p *Platform) Code() string {
return p.code
}
func (p *Platform) Station() *Station {
return p.station
}

View File

@ -4,44 +4,41 @@ import "joylink.club/rtsssimulation/repository/model/proto"
type Psd struct {
Identity
platformId string
asdGroups []*AsdGroup
platform *Platform
asdAmount int32
asdGroups []*proto.AsdGroup
componentGroups []*ElectronicComponentGroup
}
func newPsd(id string) *Psd {
func newPsd(id string, asdAmount int32, asdGroups []*proto.AsdGroup) *Psd {
return &Psd{
Identity: identity{id, proto.DeviceType_DeviceType_Psd},
asdAmount: asdAmount,
asdGroups: asdGroups,
}
}
func (p *Psd) PlatformId() string {
return p.platformId
func (p *Psd) Platform() *Platform {
return p.platform
}
func (p *Psd) AsdGroups() []*AsdGroup {
func (p *Psd) AsdAmount() int32 {
return p.asdAmount
}
func (p *Psd) AsdGroups() []*proto.AsdGroup {
return p.asdGroups
}
func (p *Psd) FindAsdGroup(group int32) *proto.AsdGroup {
for _, asdGroup := range p.asdGroups {
if asdGroup.Group == group {
return asdGroup
}
}
return nil
}
func (p *Psd) ComponentGroups() []*ElectronicComponentGroup {
return p.componentGroups
}
// AsdGroup 滑动门编组
type AsdGroup struct {
group int //编组4/8编组
start int //编组起始的滑动门编号
end int //编组结束的滑动门编号
}
func (a *AsdGroup) Group() int {
return a.group
}
func (a *AsdGroup) Start() int {
return a.start
}
func (a *AsdGroup) End() int {
return a.end
}

View File

@ -29,6 +29,7 @@ type Repository struct {
mkxMap map[string]*Mkx
keyMap map[string]*Key
linkMap map[string]*Link
platformMap map[string]*Platform
centralizedMap map[string]*proto.CentralizedStationRef
}
@ -54,6 +55,7 @@ func newRepository(id string, version string) *Repository {
stationMap: make(map[string]*Station),
mkxMap: make(map[string]*Mkx),
keyMap: make(map[string]*Key),
platformMap: make(map[string]*Platform),
centralizedMap: make(map[string]*proto.CentralizedStationRef),
}
}
@ -207,6 +209,8 @@ func (repo *Repository) FindModel(deviceId string, deviceType proto.DeviceType)
return repo.sectionalCurvatureMap[deviceId], nil
case proto.DeviceType_DeviceType_Link:
return repo.linkMap[deviceId], nil
case proto.DeviceType_DeviceType_Psd:
return repo.psdMap[deviceId], nil
default:
return nil, fmt.Errorf("仓库中不存在[%s]类型的模型", deviceType)
}
@ -224,6 +228,14 @@ func (repo *Repository) FindPhysicalSection(id string) *PhysicalSection {
return repo.physicalSectionMap[id]
}
func (repo *Repository) FindPsd(id string) *Psd {
return repo.psdMap[id]
}
func (repo *Repository) FindPlatfrom(id string) *Platform {
return repo.platformMap[id]
}
func (repo *Repository) AddPhysicalSection(section *PhysicalSection) {
repo.physicalSectionMap[section.Id()] = section
}

View File

@ -97,7 +97,7 @@ func buildModels(source *proto.Repository, repository *Repository) error {
repository.buttonMap[m.Id()] = m
}
for _, protoData := range source.Psds {
m := newPsd(protoData.Id)
m := newPsd(protoData.Id, protoData.AsdAmount, protoData.AsdGroups)
repository.psdMap[m.Id()] = m
}
@ -114,7 +114,7 @@ func buildModels(source *proto.Repository, repository *Repository) error {
repository.stationMap[m.Id()] = m
}
for _, protoData := range source.Mkxs {
m := NewMkx(protoData.Id, protoData.PsdId)
m := NewMkx(protoData.Id)
repository.mkxMap[m.Id()] = m
}
for _, protoData := range source.Keys {
@ -171,33 +171,13 @@ func buildModelRelationship(source *proto.Repository, repository *Repository) er
func buildMkxRelationShip(source *proto.Repository, repo *Repository) error {
for _, protoData := range source.Mkxs {
mkx := repo.mkxMap[protoData.Id]
for _, group := range protoData.ElectronicComponentGroups {
var components []IGroupedElectronicComponent
for _, id := range group.GetComponentIds() {
if relay := repo.relayMap[id]; relay != nil {
components = append(components, relay)
}
}
mkx.componentGroups = append(mkx.componentGroups, &ElectronicComponentGroup{
code: group.Code,
components: components,
})
}
for _, buttonId := range protoData.PcbButtonIds {
if button := repo.buttonMap[buttonId]; button != nil {
mkx.pcbButtons = append(mkx.pcbButtons, button)
}
}
for _, buttonId := range protoData.PobButtonIds {
if button := repo.buttonMap[buttonId]; button != nil {
mkx.pobButtons = append(mkx.pobButtons, button)
}
}
for _, buttonId := range protoData.PabButtonIds {
if button := repo.buttonMap[buttonId]; button != nil {
mkx.pabButtons = append(mkx.pabButtons, button)
}
}
mkx.psd = repo.psdMap[protoData.GetPsdId()]
mkx.pcb = repo.buttonMap[protoData.GetPcbButtonId()]
mkx.pob = repo.buttonMap[protoData.GetPobButtonId()]
mkx.pab = repo.buttonMap[protoData.GetPabButtonId()]
mkx.pcbj = repo.relayMap[protoData.GetPcbjId()]
mkx.pobj = repo.relayMap[protoData.GetPobjId()]
mkx.pabj = repo.relayMap[protoData.GetPabjId()]
}
return nil
}
@ -433,6 +413,8 @@ func buildPhysicalSectionRelationShip(source *proto.Repository, repository *Repo
section.bindTurnouts(turnout)
turnout.section = section
}
//关联联锁集中站
section.centralizedStation = protoData.CentralizedStation
}
return nil
}

View File

@ -29,15 +29,11 @@ func BindSystem(w ecs.World) {
device_sys.NewLightSys(),
//屏蔽门
circuit_sys.NewPsdSys(),
device_sys.NewPsdMotorSys(),
//门控箱
//circuit_sys.NewMkxSys(),
//联锁机
device_sys.NewPscSys(),
device_sys.NewAsdSys(),
// IBP
circuit_sys.NewIBPSys(),
device_sys.NewAlarmSys(),
//物理区段
device_sys.NewAxleSectionSystem(),
device_sys.NewFaDcAxleDeviceSystem(),
)
}

View File

@ -1,57 +0,0 @@
package circuit_sys
import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
)
type MkxSys struct {
query *ecs.Query
}
func NewMkxSys() *MkxSys {
return &MkxSys{
query: ecs.NewQuery(filter.Contains(component.MkxCircuitType, component.MkxCollectionCircuitType)),
}
}
func (p *MkxSys) Update(world ecs.World) {
p.query.Each(world, func(entry *ecs.Entry) {
circuit := component.MkxCircuitType.Get(entry)
p.exciteRelay(circuit.MkxplBtn, circuit.PcbList, circuit.Pcbj)
p.exciteRelay(circuit.MkxplBtn, circuit.PobList, circuit.Pobj)
if circuit.Pabj != nil { //北岗子没有PABJ而是PDBJ
p.exciteRelay(circuit.MkxplBtn, circuit.PabList, circuit.Pabj)
}
//联锁采集
collectionCircuit := component.MkxCollectionCircuitType.Get(entry)
pcb := component.BitStateType.Get(circuit.Pcbj).Val
collectionCircuit.PcbXh = pcb
pob := component.BitStateType.Get(circuit.Pobj).Val
collectionCircuit.PobXh = pob
if circuit.Pabj != nil { //北岗子没有PABJ而是PDBJ原因未知
pab := component.BitStateType.Get(circuit.Pabj).Val
collectionCircuit.PabXh = pab
}
})
}
func (p *MkxSys) exciteRelay(mkxplBtn *ecs.Entry, entries []*ecs.Entry, relay *ecs.Entry) {
if !component.BitStateType.Get(mkxplBtn).Val {
return
}
on := false
for _, entry := range entries {
btn := component.BitStateType.Get(entry)
if btn.Val {
on = true
break
}
}
if on {
component.RelayDriveType.Get(relay).Td = true
} else {
component.RelayDriveType.Get(relay).Td = false
}
}

View File

@ -4,6 +4,10 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/component/component_proto"
"joylink.club/rtsssimulation/consts"
"joylink.club/rtsssimulation/entity"
"strings"
)
type PsdSys struct {
@ -12,28 +16,105 @@ type PsdSys struct {
func NewPsdSys() *PsdSys {
return &PsdSys{
query: ecs.NewQuery(filter.Contains(component.PsdDriveCircuitType)),
query: ecs.NewQuery(filter.Contains(entity.PsdBaseComponentTypeArr...)),
}
}
func (p *PsdSys) Update(world ecs.World) {
p.query.Each(world, func(entry *ecs.Entry) {
psdDrive := component.PsdDriveCircuitType.Get(entry)
psc := component.PscType.Get(entry)
//更新屏蔽门电路及PSC相关状态
asdList := component.AsdListType.Get(entry)
if entry.HasComponent(component.PsdCircuitType) { //有屏蔽门电路
psdDrive := component.PsdInterlockDriveCircuitType.Get(entry)
psdCircuit := component.PsdCircuitType.Get(entry)
p.exciteByDrive(psdCircuit, psdDrive)
p.exciteGMJ(nil, psdCircuit, psdDrive)
p.exciteKMJ4(nil, psdCircuit, psdDrive)
p.exciteKMJ8(nil, psdCircuit, psdDrive)
p.exciteMGJ(psdCircuit, nil)
} else { //无屏蔽门电路,直接驱动电机
p.driveMotor(nil, psdDrive.GMJ, psdDrive.KMJ4, psdDrive.KMJ8)
if psdCircuit.GMJ != nil {
p.exciteGMJ(psdCircuit, psdDrive)
psc.InterlockGM = component.BitStateType.Get(psdCircuit.GMJ).Val
}
if psdCircuit.KMJ4 != nil {
p.exciteKMJ4(psdCircuit, psdDrive)
psc.InterlockKM4 = component.BitStateType.Get(psdCircuit.KMJ4).Val
}
if psdCircuit.KMJ8 != nil {
p.exciteKMJ8(psdCircuit, psdDrive)
psc.InterlockKM8 = component.BitStateType.Get(psdCircuit.KMJ8).Val
}
if psdCircuit.MGJ != nil {
p.exciteMGJ(psdCircuit, asdList)
}
p.exciteMPLJ(world, psdCircuit, component.UidType.Get(entry))
psc.InterlockMPL = component.BitStateType.Get(psdCircuit.MPLJ).Val
}
psdState := component.PsdStateType.Get(entry)
p.updatePsdState(psdState, asdList)
//更新站台门控箱电路及PSC相关状态
pmc := component.PlatformMkxCircuitType.Get(entry)
var pcbTd bool
var pobTd bool
var pabTd bool
for _, mkxEntry := range pmc.MkxList {
mkx := component.MkxType.Get(mkxEntry)
if mkx.PCB != nil && component.BitStateType.Get(mkx.PCB).Val {
pcbTd = true
}
if mkx.POB != nil && component.BitStateType.Get(mkx.POB).Val {
pobTd = true
}
if mkx.PAB != nil && component.BitStateType.Get(mkx.PAB).Val {
pabTd = true
}
}
if pmc.PCBJ != nil {
component.RelayDriveType.Get(pmc.PCBJ).Td = pcbTd
psc.MkxGM = component.BitStateType.Get(pmc.PCBJ).Val
}
if pmc.POBJ != nil {
component.RelayDriveType.Get(pmc.POBJ).Td = pobTd
psc.MkxKM = component.BitStateType.Get(pmc.POBJ).Val
}
if pmc.PABJ != nil {
component.RelayDriveType.Get(pmc.PABJ).Td = pabTd
}
//设置滑动门电机通断电状态
repo := entity.GetWorldData(world).Repo
psd := repo.FindPsd(component.UidType.Get(entry).Id)
if psc.MkxGM { //优先门控箱的关门
p.gm(asdList)
} else if psc.MkxKM { //其次门控箱的开门
group := psd.FindAsdGroup(8)
p.km(group.Start, group.End, asdList)
} else if !psc.InterlockMPL { //联锁操作没有被旁路
if psc.InterlockGM {
p.gm(asdList)
} else if psc.InterlockKM8 {
group := psd.FindAsdGroup(8)
p.km(group.Start, group.End, asdList)
} else if psc.InterlockKM4 {
group := psd.FindAsdGroup(4)
p.km(group.Start, group.End, asdList)
}
}
p.updatePsdState(entry, nil)
})
}
func (p *PsdSys) exciteByDrive(psd *component.PsdCircuit, drive *component.PsdDriveCircuit) {
func (p *PsdSys) km(start int32, end int32, asdList *component.AsdList) {
for i := start; i <= end; i++ {
asd := asdList.List[i]
component.AsdMotorStateType.Get(asd).TD = true
component.AsdMotorStateType.Get(asd).KM = true
}
}
func (p *PsdSys) gm(asdList *component.AsdList) {
for _, asd := range asdList.List {
component.AsdMotorStateType.Get(asd).TD = true
component.AsdMotorStateType.Get(asd).KM = false
}
}
func (p *PsdSys) exciteByDrive(psd *component.PsdCircuit, drive *component.PsdInterlockDriveCircuit) {
if drive.GMJ {
component.RelayDriveType.Get(psd.GMJ).Td = true
component.BitStateType.Get(psd.GMJ).Val = true
@ -48,103 +129,101 @@ func (p *PsdSys) exciteByDrive(psd *component.PsdCircuit, drive *component.PsdDr
}
}
// 驱动电机
func (p *PsdSys) driveMotor(psdMotorState *component.AsdMotorState, gm, km4, km8 bool) {
//if gm {
// psdMotorState.Gm_Td = true
// psdMotorState.Km4_Td = false
// psdMotorState.Km8_Td = false
//} else if km4 {
// psdMotorState.Gm_Td = false
// psdMotorState.Km4_Td = true
// psdMotorState.Km8_Td = false
//} else if km8 {
// psdMotorState.Gm_Td = false
// psdMotorState.Km4_Td = false
// psdMotorState.Km8_Td = true
//}
func (p *PsdSys) exciteGMJ(psd *component.PsdCircuit, psdDrive *component.PsdInterlockDriveCircuit) {
gmj := component.BitStateType.Get(psd.GMJ)
kmj4 := component.BitStateType.Get(psd.KMJ4)
kmj8 := component.BitStateType.Get(psd.KMJ8)
if psdDrive.GMJ { //驱动电路接通
component.RelayDriveType.Get(psd.GMJ).Td = true
gmj.Val = true
} else if gmj.Val {
if !kmj4.Val && !kmj8.Val {
component.RelayDriveType.Get(psd.GMJ).Td = true
} else {
component.RelayDriveType.Get(psd.GMJ).Td = false
gmj.Val = false
}
}
}
func (p *PsdSys) exciteGMJ(state *component.AsdMotorState, psd *component.PsdCircuit, psdDrive *component.PsdDriveCircuit) {
//gmj := component.BitStateType.Get(psd.GMJ)
//kmj4 := component.BitStateType.Get(psd.KMJ4)
//kmj8 := component.BitStateType.Get(psd.KMJ8)
//if psdDrive.GMJ { //驱动电路接通
// component.RelayDriveType.Get(psd.GMJ).Td = true
// gmj.Val = true
//} else if gmj.Val {
// if !kmj4.Val && !kmj8.Val {
// component.RelayDriveType.Get(psd.GMJ).Td = true
// } else {
// component.RelayDriveType.Get(psd.GMJ).Td = false
// gmj.Val = false
// }
//}
//if gmj.Val && !kmj4.Val && !kmj8.Val {
// state.Gm_Td = true
//}
func (p *PsdSys) exciteKMJ4(psd *component.PsdCircuit, psdDrive *component.PsdInterlockDriveCircuit) {
kmj4 := component.BitStateType.Get(psd.KMJ4)
gmj := component.BitStateType.Get(psd.GMJ)
kmj8 := component.BitStateType.Get(psd.KMJ8)
if psdDrive.KMJ4 {
component.RelayDriveType.Get(psd.KMJ4).Td = true
kmj4.Val = true
} else if kmj4.Val {
if !gmj.Val && !kmj8.Val {
component.RelayDriveType.Get(psd.KMJ4).Td = true
} else {
component.RelayDriveType.Get(psd.KMJ4).Td = false
kmj4.Val = false
}
}
}
func (p *PsdSys) exciteKMJ4(state *component.AsdMotorState, psd *component.PsdCircuit, psdDrive *component.PsdDriveCircuit) {
//kmj4 := component.BitStateType.Get(psd.KMJ4)
//gmj := component.BitStateType.Get(psd.GMJ)
//kmj8 := component.BitStateType.Get(psd.KMJ8)
//if psdDrive.KMJ4 {
// component.RelayDriveType.Get(psd.KMJ4).Td = true
// kmj4.Val = true
//} else if kmj4.Val {
// if !gmj.Val && !kmj8.Val {
// component.RelayDriveType.Get(psd.KMJ4).Td = true
// } else {
// component.RelayDriveType.Get(psd.KMJ4).Td = false
// kmj4.Val = false
// }
//}
//if kmj4.Val && !gmj.Val && !kmj8.Val {
// state.Km4_Td = true
//}
func (p *PsdSys) exciteKMJ8(psd *component.PsdCircuit, psdDrive *component.PsdInterlockDriveCircuit) {
kmj8 := component.BitStateType.Get(psd.KMJ8)
gmj := component.BitStateType.Get(psd.GMJ)
kmj4 := component.BitStateType.Get(psd.KMJ4)
if psdDrive.KMJ4 {
component.RelayDriveType.Get(psd.KMJ8).Td = true
kmj8.Val = true
} else if kmj8.Val {
if !gmj.Val && !kmj4.Val {
component.RelayDriveType.Get(psd.KMJ8).Td = true
} else {
component.RelayDriveType.Get(psd.KMJ8).Td = false
kmj8.Val = false
}
}
}
func (p *PsdSys) exciteKMJ8(state *component.AsdMotorState, psd *component.PsdCircuit, psdDrive *component.PsdDriveCircuit) {
//kmj8 := component.BitStateType.Get(psd.KMJ8)
//gmj := component.BitStateType.Get(psd.GMJ)
//kmj4 := component.BitStateType.Get(psd.KMJ4)
//if psdDrive.KMJ4 {
// component.RelayDriveType.Get(psd.KMJ8).Td = true
// kmj8.Val = true
//} else if kmj8.Val {
// if !gmj.Val && !kmj4.Val {
// component.RelayDriveType.Get(psd.KMJ8).Td = true
// } else {
// component.RelayDriveType.Get(psd.KMJ8).Td = false
// kmj8.Val = false
// }
//}
//if kmj8.Val && !gmj.Val && !kmj4.Val {
// state.Km8_Td = true
//}
func (p *PsdSys) exciteMGJ(psdCircuit *component.PsdCircuit, asdList *component.AsdList) {
for _, asdEntry := range asdList.List {
asdMotor := component.AsdMotorStateType.Get(asdEntry)
if asdMotor.KM {
component.BitStateType.Get(psdCircuit.MGJ).Val = false
return
}
}
component.BitStateType.Get(psdCircuit.MGJ).Val = true
}
func (p *PsdSys) exciteMGJ(psdCircuit *component.PsdCircuit, state *component.AsdMotorState) {
//if state.Is4Km() || state.Is8Km() {
// component.RelayDriveType.Get(psdCircuit.MGJ).Td = false
// component.BitStateType.Get(psdCircuit.MGJ).Val = false
//} else {
// component.RelayDriveType.Get(psdCircuit.MGJ).Td = true
// component.BitStateType.Get(psdCircuit.MGJ).Val = true
//}
func (p *PsdSys) updatePsdState(psdState *component_proto.PsdState, asdList *component.AsdList) {
for _, asdEntry := range asdList.List {
position := component.TwoPositionTransformType.Get(asdEntry)
if position.GetPos() != consts.TwoPosMin {
psdState.Close = false
return
}
}
psdState.Close = true
}
func (p *PsdSys) updatePsdState(entry *ecs.Entry, psdMotorState *component.AsdMotorState) {
//psdState := component.PsdStateType.Get(entry)
//if psdMotorState.Is8Km() {
// psdState.Km8 = true
// psdState.Km4 = false
//} else if psdMotorState.Is4Km() {
// psdState.Km4 = true
// psdState.Km8 = false
//} else {
// psdState.Km4 = false
// psdState.Km8 = false
//}
func (p *PsdSys) exciteMPLJ(world ecs.World, circuit *component.PsdCircuit, uid *component.Uid) {
data := entity.GetWorldData(world)
psd := data.Repo.FindPsd(uid.Id)
platform := psd.Platform()
station := platform.Station()
var buttonCode string
if strings.Contains(platform.Code(), "上行") {
buttonCode = "S旁路"
} else if strings.Contains(platform.Code(), "下行") {
buttonCode = "X旁路"
} else {
return
}
for _, button := range station.GetIbpSpk().Buttons() {
if button.Code() != buttonCode {
return
}
btnEntry, ok := entity.GetEntityByUid(world, button.Id())
if !ok {
return
}
component.RelayDriveType.Get(circuit.MPLJ).Td = component.BitStateType.Get(btnEntry).Val
}
}

42
sys/device_sys/asd.go Normal file
View File

@ -0,0 +1,42 @@
package device_sys
import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/consts"
)
type AsdSys struct {
query *ecs.Query
}
func NewAsdSys() *AsdSys {
return &AsdSys{
query: ecs.NewQuery(filter.Contains(component.AsdMotorStateType, component.TwoPositionTransformType)),
}
}
func (s *AsdSys) Update(world ecs.World) {
var speed int32 = consts.TwoPosMax / 4
s.query.Each(world, func(entry *ecs.Entry) {
//设置两位置转换速度
psdMotorState := component.AsdMotorStateType.Get(entry)
twoPosition := component.TwoPositionTransformType.Get(entry)
if psdMotorState.TD {
if psdMotorState.KM {
twoPosition.Speed = speed
if twoPosition.Pos == consts.TwoPosMax { //开门到位后断电
psdMotorState.TD = false
}
} else {
twoPosition.Speed = -speed
if twoPosition.Pos == consts.TwoPosMin { //关门到位后断电
psdMotorState.TD = false
}
}
}
//门关继电器状态
psdMotorState.MG = twoPosition.Pos == consts.TwoPosMin
})
}

View File

@ -1,94 +0,0 @@
package device_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
)
// AxleSectionSystem 计轴区段设备
type AxleSectionSystem struct {
query *ecs.Query
}
func NewAxleSectionSystem() *AxleSectionSystem {
return &AxleSectionSystem{
query: ecs.NewQuery(filter.Contains(component.AxleSectionStateType, component.AxleSectionDeviceType, component.AxleSectionRuntimeType)),
}
}
func (s *AxleSectionSystem) Update(w ecs.World) {
s.query.Each(w, func(entry *donburi.Entry) {
s.calculateDrst(entry)
s.calculatePdrst(entry)
s.calculateSectionState(entry)
s.calculateHf(entry)
s.calculateAxleCount(entry)
/*
{
if component.UidType.Get(entry).Id == "北京_12_酒仙桥_6G" {
state := component.AxleSectionStateType.Get(entry)
device := component.AxleSectionDeviceType.Get(entry)
rt := component.AxleSectionRuntimeType.Get(entry)
fmt.Printf("===>>计轴区段(北京_12_酒仙桥_6G): Clr=%t, Occ=%t, Drst=%t, Pdrst=%t, Rac=%t, Rjo=%t, Rjt=%t, Count=%d Pdrsting=%t\n",
state.Clr, state.Occ, device.Drst, device.Pdrst, device.Rac, device.Rjo, device.Rjt, rt.Count(), rt.DoingPdrst)
}
}
*/
})
}
// 计算计轴区段内车轴数
// 目前通过查看有哪些车在该计轴区段内实现,定性
func (s *AxleSectionSystem) calculateAxleCount(entry *donburi.Entry) {
//收集该计轴区段上的车轴数
//device.Count = 该计轴区段上当前车轴数
}
// 计算计轴区段状态
func (s *AxleSectionSystem) calculateSectionState(entry *donburi.Entry) {
state := component.AxleSectionStateType.Get(entry)
rt := component.AxleSectionRuntimeType.Get(entry)
isIdle := rt.Count() <= 0 && !rt.DoingPdrst //区段空闲:区段内车轴数为零且没有预复位
state.Clr = isIdle
state.Occ = !isIdle
}
// 计轴直接复位
func (s *AxleSectionSystem) calculateDrst(entry *donburi.Entry) {
device := component.AxleSectionDeviceType.Get(entry)
rt := component.AxleSectionRuntimeType.Get(entry)
if device.Drst && !device.Rjo && !device.Rjt { //直接复位且没有拒绝原因
rt.SetCount(0)
rt.DoingPdrst = false
rt.CountTrainOutPulse = false
rt.CountTrainInPulse = false
}
}
// 计轴预复位
func (s *AxleSectionSystem) calculatePdrst(entry *donburi.Entry) {
device := component.AxleSectionDeviceType.Get(entry)
rt := component.AxleSectionRuntimeType.Get(entry)
if device.Pdrst && !device.Rjo && !device.Rjt && !rt.DoingPdrst { //预复位且没有拒绝原因
rt.SetCount(0)
rt.DoingPdrst = true
rt.CountTrainOutPulse = false
rt.CountTrainInPulse = false
}
//压道车通过该计轴区段,完成计轴预复位
if rt.CountTrainInPulse && rt.CountTrainOutPulse {
rt.DoingPdrst = false
}
}
// 复位回复运算
func (s *AxleSectionSystem) calculateHf(entry *donburi.Entry) {
device := component.AxleSectionDeviceType.Get(entry)
state := component.AxleSectionStateType.Get(entry)
rt := component.AxleSectionRuntimeType.Get(entry)
device.Rac = device.Drst || device.Pdrst
device.Rjo = device.Rac && state.Clr && !state.Occ && !rt.DoingPdrst //空闲拒绝复位(排除预复位过程中)
device.Rjt = false // 技术原因拒绝复位
}

View File

@ -0,0 +1,106 @@
package device_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"log/slog"
)
// FaDcAxleDeviceSystem FaDc计轴设备管理器系统
type FaDcAxleDeviceSystem struct {
query *ecs.Query
}
func NewFaDcAxleDeviceSystem() *FaDcAxleDeviceSystem {
return &FaDcAxleDeviceSystem{
query: ecs.NewQuery(filter.Contains(component.FaDcAxleDeviceType)),
}
}
func (s *FaDcAxleDeviceSystem) Update(w ecs.World) {
s.query.Each(w, func(entry *donburi.Entry) {
faDcDevice := component.FaDcAxleDeviceType.Get(entry)
for _, axleSectionEntry := range faDcDevice.Sections {
axleSectionId := component.UidType.Get(axleSectionEntry).Id
axleCounterEntry := faDcDevice.CounterMap[axleSectionId]
//
s.calculateHf(axleCounterEntry, axleSectionEntry)
s.calculateDrst(axleCounterEntry)
s.calculatePdrst(axleCounterEntry)
s.calculateSectionState(axleCounterEntry, axleSectionEntry)
s.calculateAxleCount(axleCounterEntry, axleSectionEntry)
if "北京_12_酒仙桥_12G" == axleSectionId && false {
section := component.AxleSectionType.Get(axleSectionEntry)
counter := component.AxleCounterType.Get(axleCounterEntry)
counterRt := component.AxleCounterRuntimeType.Get(axleCounterEntry)
sectionFault := component.AxleSectionFaultType.Get(axleSectionEntry)
slog.Info(axleSectionId,
"Drst", counterRt.Drst,
"Pdrst", counterRt.Pdrst,
"DoingPdrst", counterRt.DoingPdrst,
"Rac", counterRt.Rac,
"Rjo", counterRt.Rjo,
"Rjt", counterRt.Rjt,
"SectionFault", sectionFault.SectionFault,
"Occ", section.Occ,
"Count", counter.Count,
"Wave", counter.ShowCountWave())
}
}
})
}
// 计算计轴区段内车轴数
// 目前通过查看有哪些车在该计轴区段内实现,定性
func (s *FaDcAxleDeviceSystem) calculateAxleCount(axleCounterEntry *donburi.Entry, axleSectionEntry *donburi.Entry) {
//检查该区段内有没有车
// ...todo
}
// 计算计轴区段状态
func (s *FaDcAxleDeviceSystem) calculateSectionState(axleCounterEntry *donburi.Entry, axleSectionEntry *donburi.Entry) {
section := component.AxleSectionType.Get(axleSectionEntry)
counter := component.AxleCounterType.Get(axleCounterEntry)
counterRt := component.AxleCounterRuntimeType.Get(axleCounterEntry)
isIdle := counter.Count <= 0 && !counterRt.DoingPdrst //区段空闲:区段内车轴数为零且没有预复位
section.Occ = !isIdle
}
// 计轴直接复位
func (s *FaDcAxleDeviceSystem) calculateDrst(axleCounterEntry *donburi.Entry) {
counter := component.AxleCounterType.Get(axleCounterEntry)
counterRt := component.AxleCounterRuntimeType.Get(axleCounterEntry)
if counterRt.Drst && !counterRt.Rjo && !counterRt.Rjt { //直接复位且没有拒绝原因
counter.UpdateCount(0)
counter.ResetCountPulse()
counterRt.DoingPdrst = false
}
}
// 计轴预复位
func (s *FaDcAxleDeviceSystem) calculatePdrst(axleCounterEntry *donburi.Entry) {
counter := component.AxleCounterType.Get(axleCounterEntry)
counterRt := component.AxleCounterRuntimeType.Get(axleCounterEntry)
if counterRt.Pdrst && !counterRt.Rjo && !counterRt.Rjt && !counterRt.DoingPdrst { //预复位且没有拒绝原因
counter.UpdateCount(0)
counter.ResetCountPulse()
counterRt.DoingPdrst = true
}
//压道车通过该计轴区段,完成计轴预复位
if counter.IsCount010Pulse() {
counterRt.DoingPdrst = false
}
}
// 复位回复运算
func (s *FaDcAxleDeviceSystem) calculateHf(axleCounterEntry *donburi.Entry, axleSectionEntry *donburi.Entry) {
section := component.AxleSectionType.Get(axleSectionEntry)
sectionFault := component.AxleSectionFaultType.Get(axleSectionEntry)
counterRt := component.AxleCounterRuntimeType.Get(axleCounterEntry)
counterRt.Rac = counterRt.Drst || counterRt.Pdrst
counterRt.Rjo = counterRt.Rac && !section.Occ && !counterRt.DoingPdrst //空闲拒绝复位(排除预复位过程中)
counterRt.Rjt = counterRt.Rac && sectionFault.SectionFault // 技术原因拒绝复位
}

View File

@ -1,37 +0,0 @@
package device_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
)
// PscSys 中央控制盘系统
type PscSys struct {
query *ecs.Query
}
func NewPscSys() *PscSys {
return &PscSys{
query: ecs.NewQuery(filter.Contains(component.PscType)),
}
}
func (s *PscSys) Update(world ecs.World) {
s.query.Each(world, func(entry *donburi.Entry) {
psc := component.PscType.Get(entry)
mkxState := component.MkxCollectionCircuitType.Get(psc.Mkx)
if mkxState.PcbXh {
psdDriveCircuit := component.PsdDriveCircuitType.Get(psc.Psd)
psdDriveCircuit.GMJ = true
psdDriveCircuit.KMJ4 = false
psdDriveCircuit.KMJ8 = false
} else if mkxState.PobXh {
psdDriveCircuit := component.PsdDriveCircuitType.Get(psc.Psd)
psdDriveCircuit.GMJ = false
psdDriveCircuit.KMJ4 = false
psdDriveCircuit.KMJ8 = true
}
})
}

View File

@ -1,89 +0,0 @@
package device_sys
import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
)
type PsdMotorSys struct {
query *ecs.Query
}
func NewPsdMotorSys() *PsdMotorSys {
return &PsdMotorSys{
query: ecs.NewQuery(filter.Contains(component.AsdMotorStateType)),
}
}
func (s *PsdMotorSys) Update(world ecs.World) {
//var rate int32 = 10000 / 4
//s.query.Each(world, func(entry *ecs.Entry) {
// psdMotorState := component.AsdMotorStateType.Get(entry)
// if psdMotorState.Gm_Td {
// gm(psdMotorState, rate)
// } else if psdMotorState.Km4_Td {
// km4(psdMotorState, rate)
// } else if psdMotorState.Km8_Td {
// km8(psdMotorState, rate)
// }
//})
}
func gm(psdMotorState *component.AsdMotorState, rate int32) {
//if psdMotorState.Km4 != consts.TwoPosMin {
// newRate := psdMotorState.Km4 - rate
// if newRate < consts.TwoPosMin {
// psdMotorState.Km4 = consts.TwoPosMin
// } else {
// psdMotorState.Km4 = newRate
// }
//}
//if psdMotorState.Km8_4 != consts.TwoPosMin {
// newRate := psdMotorState.Km8_4 - rate
// if newRate < consts.TwoPosMin {
// psdMotorState.Km8_4 = consts.TwoPosMin
// } else {
// psdMotorState.Km8_4 = newRate
// }
//}
//if !psdMotorState.Is8Km() && !psdMotorState.Is4Km() {
// psdMotorState.Gm_Td = false
//}
}
func km4(psdMotorState *component.AsdMotorState, rate int32) {
//if psdMotorState.Km4 != consts.TwoPosMax {
// newRate := psdMotorState.Km4 + rate
// if newRate > consts.TwoPosMax {
// psdMotorState.Km4 = consts.TwoPosMax
// } else {
// psdMotorState.Km4 = newRate
// }
//}
//if psdMotorState.Is4Km() || psdMotorState.Is8Km() {
// psdMotorState.Km4_Td = false
//}
}
func km8(psdMotorState *component.AsdMotorState, rate int32) {
//if psdMotorState.Km4 != consts.TwoPosMax {
// newRate := psdMotorState.Km4 + rate
// if newRate > consts.TwoPosMax {
// psdMotorState.Km4 = consts.TwoPosMax
// } else {
// psdMotorState.Km4 = newRate
// }
//}
//if psdMotorState.Km8_4 != consts.TwoPosMax {
// newRate := psdMotorState.Km8_4 + rate
// if newRate > consts.TwoPosMax {
// psdMotorState.Km8_4 = consts.TwoPosMax
// } else {
// psdMotorState.Km8_4 = newRate
// }
//}
//if psdMotorState.Is8Km() {
// psdMotorState.Km8_Td = false
//}
}