package ui import ( "cli-mon/yabl" "github.com/gizak/termui/v3/widgets" "reflect" ) type connectorType struct { energy *yabl.PuPresentEnergy state *yabl.PuPeriphery } type contactorType struct { state *yabl.ContactorInternalState errors *yabl.ContactorInternalErrors } type modelTypes interface { *connectorType | *contactorType } type dataTypes interface { *yabl.PuPresentEnergy | *yabl.PuPeriphery | *yabl.ContactorInternalState | *yabl.ContactorInternalErrors } type fNewType[T modelTypes, V dataTypes] func(e V) T type fGetType[T modelTypes, V dataTypes] func(m T) V type fSetType[T modelTypes, V dataTypes] func(m T, e V) var connectors = make([]*connectorType, connectorsCount+1) var contactors = make([]*contactorType, contactorsCount+1) var connUI [connectorsCount + 1]*widgets.Paragraph var contUI [contactorsCount + 1]*widgets.Paragraph var contactorsErr *widgets.Paragraph func process(message yabl.Packet) { if message == nil { return } unitId := message.GetUnitId() switch msg := message.(type) { case *yabl.ContactorInternalState: if updateOrNew(contactors, unitId, msg, fNewCIS, fGetCIS, fSetCIS) { updateContactorsView(unitId) } case *yabl.ContactorInternalErrors: if updateOrNew(contactors, unitId, msg, fNewCES, fGetCES, fSetCES) { updateContactorsStateView() } case *yabl.PuPeriphery: if updateOrNew(connectors, unitId, msg, fNewPP, fGetPP, fSetPP) { updateConnectorsView(unitId) } case *yabl.PuPresentEnergy: if updateOrNew(connectors, unitId, msg, fNewPPE, fGetPPE, fSetPPE) { updateConnectorsView(unitId) } } } func updateOrNew[T modelTypes, V dataTypes](array []T, id uint, msg V, fNew fNewType[T, V], fGet fGetType[T, V], fSet fSetType[T, V]) bool { if model := array[id]; model != nil { if element := fGet(model); !reflect.DeepEqual(element, msg) { fSet(model, msg) return true } } else { model = fNew(msg) array[id] = model return true } return false }