Quellcode durchsuchen

SVI Переделка кода

SVI vor 1 Woche
Ursprung
Commit
7ac1975432
65 geänderte Dateien mit 1221 neuen und 829 gelöschten Zeilen
  1. 2 2
      go.mod
  2. 4 4
      go.sum
  3. 6 6
      lev0/alias/alias.go
  4. 12 0
      lev0/types/iarch_actor.go
  5. 10 0
      lev0/types/iarch_group_link.go
  6. 16 0
      lev0/types/iarch_link.go
  7. 19 0
      lev0/types/iarch_node.go
  8. 12 0
      lev0/types/iarch_text.go
  9. 12 0
      lev0/types/iarch_use_case.go
  10. 13 0
      lev0/types/iarch_use_group.go
  11. 4 4
      lev0/types/iarch_yaml.go
  12. 0 10
      lev0/types/ielem_actor.go
  13. 0 19
      lev0/types/ielem_base.go
  14. 0 10
      lev0/types/ielem_group_link.go
  15. 0 14
      lev0/types/ielem_link.go
  16. 0 12
      lev0/types/ielem_use_case.go
  17. 0 12
      lev0/types/ielem_use_group.go
  18. 2 2
      lev0/types/iengine_service.go
  19. 0 13
      lev0/types/imap_drawer.go
  20. 0 16
      lev0/types/iview_label.go
  21. 4 4
      lev0/types/iview_node.go
  22. 10 0
      lev0/types/iview_text.go
  23. 17 0
      lev0/types/iview_tree.go
  24. 32 0
      lev1/arch_actor/arch_actor.go
  25. 32 0
      lev1/arch_doc/arch_doc.go
  26. 24 23
      lev1/arch_group_link/arch_group_link.go
  27. 71 66
      lev1/arch_link/arch_link.go
  28. 79 0
      lev1/arch_node/arch_node.go
  29. 55 0
      lev1/arch_text/arch_text.go
  30. 96 0
      lev1/arch_use_case/arch_use_case.go
  31. 64 0
      lev1/arch_use_group/arch_use_group.go
  32. 0 11
      lev1/arch_yaml/arch_yaml.go
  33. 3 3
      lev1/canvas/canvas.go
  34. 0 47
      lev1/coord/coord.go
  35. 0 30
      lev1/elem_actor/elem_actor.go
  36. 0 60
      lev1/elem_base/elem_base.go
  37. 0 71
      lev1/elem_label/elem_label.go
  38. 0 79
      lev1/elem_use_case/elem_use_case.go
  39. 0 49
      lev1/elem_use_group/elem_use_group.go
  40. 47 0
      lev1/view_coord/view_coord.go
  41. 24 7
      lev1/view_link/view_link.go
  42. 4 0
      lev1/view_node/view_node.go
  43. 2 2
      lev1/view_offset/view_offset.go
  44. 18 14
      lev1/view_size/view_size.go
  45. 31 0
      lev1/view_text/view_text.go
  46. 12 8
      lev1/view_use_case/view_use_case.go
  47. 106 0
      lev2/engine_http/engine_http.go
  48. 18 0
      lev2/engine_http/http_api/http_api.go
  49. 116 0
      lev2/engine_http/http_api/http_arch_doc/http_arch_doc.go
  50. 0 186
      lev2/engine_http/serv_http.go
  51. 1 1
      lev3/fabrics/fabric_service.go
  52. 12 8
      pkg/views/view_actor/view_actor.go
  53. 21 10
      pkg/views/view_use_group/view_use_group.go
  54. 112 16
      vendor/golang.org/x/sys/unix/affinity_linux.go
  55. 1 1
      vendor/golang.org/x/sys/unix/mkall.sh
  56. 6 2
      vendor/golang.org/x/sys/unix/syscall_linux.go
  57. 3 0
      vendor/golang.org/x/sys/unix/syscall_linux_arm.go
  58. 3 0
      vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
  59. 3 0
      vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
  60. 3 0
      vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
  61. 2 2
      vendor/golang.org/x/sys/unix/zsyscall_linux.go
  62. 10 3
      vendor/golang.org/x/sys/windows/syscall_windows.go
  63. 29 0
      vendor/golang.org/x/sys/windows/types_windows.go
  64. 36 0
      vendor/golang.org/x/sys/windows/zsyscall_windows.go
  65. 2 2
      vendor/modules.txt

+ 2 - 2
go.mod

@@ -30,7 +30,7 @@ require (
 	go.opentelemetry.io/otel v1.43.0 // indirect
 	go.opentelemetry.io/otel v1.43.0 // indirect
 	go.opentelemetry.io/otel/metric v1.43.0 // indirect
 	go.opentelemetry.io/otel/metric v1.43.0 // indirect
 	go.opentelemetry.io/otel/trace v1.43.0 // indirect
 	go.opentelemetry.io/otel/trace v1.43.0 // indirect
-	golang.org/x/net v0.53.0 // indirect
-	golang.org/x/sys v0.43.0 // indirect
+	golang.org/x/net v0.54.0 // indirect
+	golang.org/x/sys v0.44.0 // indirect
 	google.golang.org/protobuf v1.36.11 // indirect
 	google.golang.org/protobuf v1.36.11 // indirect
 )
 )

+ 4 - 4
go.sum

@@ -75,16 +75,16 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
-golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
+golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
+golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
-golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
+golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

+ 6 - 6
lev0/alias/alias.go

@@ -1,14 +1,14 @@
 // package alias -- алиасы типов
 // package alias -- алиасы типов
 package alias
 package alias
 
 
-// Id -- ID объекта
-type Id string
+// ArchId -- архитектурный ID объекта
+type ArchId string
 
 
-// Label -- метка объекта
-type Label string
+// ArchText -- произвольный текст
+type ArchText string
 
 
-// Type -- тип объекта
-type Type string
+// ArchType -- архитектурный тип объекта
+type ArchType string
 
 
 // CoordX -- координата X
 // CoordX -- координата X
 type CoordX int
 type CoordX int

+ 12 - 0
lev0/types/iarch_actor.go

@@ -0,0 +1,12 @@
+package types
+
+// IArchActor -- интерфейс актора
+type IArchActor interface {
+	IArchNode
+	// Name -- имя актора
+	Name() string
+	// GroupLink -- возвращает группу ссылок актора
+	GroupLink() IArchGroupLink
+	// Text -- текст актора
+	Text() IArchText
+}

+ 10 - 0
lev0/types/iarch_group_link.go

@@ -0,0 +1,10 @@
+package types
+
+import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+
+// IArchGroupLink -- интерфейс группы ссылок
+type IArchGroupLink interface {
+	IArchNode
+	// Links -- ссылки в группе
+	Links() []alias.ArchId
+}

+ 16 - 0
lev0/types/iarch_link.go

@@ -0,0 +1,16 @@
+package types
+
+import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+
+// IArchLink -- интерфейс связи между узлами
+type IArchLink interface {
+	IArchText
+	// SrcId -- возвращает ID источника связи
+	SrcId() alias.ArchId
+	// DstId -- возвращает ID получателя связи
+	DstId() alias.ArchId
+	// CoordEnd -- координаты конца связи
+	// CoordEnd() IViewCoord
+	// TypeLink -- тип связи
+	TypeLink() string
+}

+ 19 - 0
lev0/types/iarch_node.go

@@ -0,0 +1,19 @@
+package types
+
+import (
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+)
+
+// IArchNode -- интерфейс архитектурного узла
+type IArchNode interface {
+	// Type -- возвращает тип архитектурного узла
+	Type() alias.ArchType
+	// Id -- возвращает идентификатор архитектурного узла
+	Id() alias.ArchId
+	// InvarCheck -- проверка инвариантов архитектурного узла
+	InvarCheck() ktypes.Option[error]
+	// ParentId -- возвращает родительский узел
+	ParentId() alias.ArchId
+}

+ 12 - 0
lev0/types/iarch_text.go

@@ -0,0 +1,12 @@
+package types
+
+import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+
+// IArchText -- интерфейс архитектурного текста
+type IArchText interface {
+	IArchNode
+	// Get -- возвращает архитектурный текст
+	Get() alias.ArchText
+	// String -- возвращает архитектурную строку
+	String() string
+}

+ 12 - 0
lev0/types/iarch_use_case.go

@@ -0,0 +1,12 @@
+package types
+
+import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+
+// IArchUseCase -- интерфейс к вариантам использования
+type IArchUseCase interface {
+	IArchNode
+	// Links -- ссылки вариантов использования
+	Links() map[alias.ArchId]IArchLink
+	// Text -- текст варианта использования
+	Text() IArchText
+}

+ 13 - 0
lev0/types/iarch_use_group.go

@@ -0,0 +1,13 @@
+package types
+
+import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+
+// IArchUseGroup -- интерфейс группы вариантов использования
+type IArchUseGroup interface {
+	IArchNode
+	// Links -- заглушка на связи между объектами
+	Links() []alias.ArchId
+	// Len -- количество ссылок
+	Len() int
+	// Size() IViewSize
+}

+ 4 - 4
lev0/types/iyaml_marsh.go → lev0/types/iarch_yaml.go

@@ -4,14 +4,14 @@ import (
 	"gopkg.in/yaml.v3"
 	"gopkg.in/yaml.v3"
 )
 )
 
 
-// YamlMarshal -- интерфейс для маршалера в YAML
-type YamlMarshal interface {
+// IArchYamlMarshal -- интерфейс для маршалера в YAML
+type IArchYamlMarshal interface {
 	// MarshalYAML -- метод должен возвращать то, что реально запишется в YAML
 	// MarshalYAML -- метод должен возвращать то, что реально запишется в YAML
 	MarshalYAML() (any, error)
 	MarshalYAML() (any, error)
 }
 }
 
 
-// YamlUnmarshal -- интерфейс для маршалера в YAML
-type YamlUnmarshal interface {
+// IArchYamlUnmarshal -- интерфейс для маршалера в YAML
+type IArchYamlUnmarshal interface {
 	// UnmarshalYAML -- метод должен возвращать то, что загрузится из YAML
 	// UnmarshalYAML -- метод должен возвращать то, что загрузится из YAML
 	UnmarshalYAML(value *yaml.Node) error
 	UnmarshalYAML(value *yaml.Node) error
 }
 }

+ 0 - 10
lev0/types/ielem_actor.go

@@ -1,10 +0,0 @@
-package types
-
-// IElemActor -- интерфейс актора
-type IElemActor interface {
-	IElemBase
-	// Name -- имя актора
-	Name() string
-	// GroupLink -- возвращает группу ссылок актора
-	GroupLink() IElemGroupLink
-}

+ 0 - 19
lev0/types/ielem_base.go

@@ -1,19 +0,0 @@
-package types
-
-import (
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-)
-
-// IElemBase -- интерфейс элемента схемы
-type IElemBase interface {
-	// Type -- возвращает тип элемента
-	Type() alias.Type
-	// Id -- возвращает идентификатор
-	Id() alias.Id
-	// SelfCheck -- самопроверка базового элемента
-	SelfCheck()
-	// InvarCheck -- проверка инвариантов
-	InvarCheck() string
-	// Coord -- возвращает координаты метки
-	// Coord() ICoord
-}

+ 0 - 10
lev0/types/ielem_group_link.go

@@ -1,10 +0,0 @@
-package types
-
-import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-
-// IElemGroupLink -- интерфейс группы ссылок
-type IElemGroupLink interface {
-	IElemBase
-	// Links -- ссылки актора
-	Links() []alias.Id
-}

+ 0 - 14
lev0/types/ielem_link.go

@@ -1,14 +0,0 @@
-package types
-
-// IElemLink -- интерфейс связи между объектами
-type IElemLink interface {
-	IViewLabel
-	// Src -- возвращает источник связи
-	Src() IElemBase
-	// Dst -- возвращает получателя связи
-	Dst() IElemBase
-	// CoordEnd -- координаты конца связи
-	CoordEnd() IViewCoord
-	// TypeLink -- тип связи
-	TypeLink() string
-}

+ 0 - 12
lev0/types/ielem_use_case.go

@@ -1,12 +0,0 @@
-package types
-
-import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-
-// IElemUseCase -- интерфейс к вариантам использования
-type IElemUseCase interface {
-	IElemBase
-	// Links -- ссылки вариантов использования
-	Links() map[alias.Id]IElemLink
-	// Label -- метка варианта использования
-	Label() IViewLabel
-}

+ 0 - 12
lev0/types/ielem_use_group.go

@@ -1,12 +0,0 @@
-package types
-
-import "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-
-// IElemUseGroup -- интерфейс группы вариантов использования
-type IElemUseGroup interface {
-	IElemBase
-	// Links -- заглушка на связи между объектами
-	Links() []alias.Id
-	// Size -- возвращает размер
-	Size() IViewSize
-}

+ 2 - 2
lev0/types/iservice.go → lev0/types/iengine_service.go

@@ -5,8 +5,8 @@ import (
 	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
 	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
 )
 )
 
 
-// IService -- интерфейс сервиса
-type IService interface {
+// IEngineService -- интерфейс движка сервиса
+type IEngineService interface {
 	// Run -- запуск сервиса
 	// Run -- запуск сервиса
 	Run() ktypes.Result[bool]
 	Run() ktypes.Result[bool]
 }
 }

+ 0 - 13
lev0/types/imap_drawer.go

@@ -1,13 +0,0 @@
-package types
-
-import (
-	svg "github.com/ajstarks/svgo"
-)
-
-// IMapDrawer -- интерфейс словаря для отрисовки
-type IMapDrawer interface {
-	// Draw -- рисует карту
-	Draw(canvas *svg.SVG)
-	// LstDrawers -- возвращает список отрисовщиков
-	LstDrawers() []IMapDrawer
-}

+ 0 - 16
lev0/types/iview_label.go

@@ -1,16 +0,0 @@
-package types
-
-import (
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-)
-
-// IViewLabel -- надпись
-type IViewLabel interface {
-	IViewBase
-	// Get -- возвращает метку
-	Get() alias.Label
-	// String -- возвращает строку
-	String() string
-	// Offset -- возвращает смещение метки
-	Offset() IViewOffset
-}

+ 4 - 4
lev0/types/iview_base.go → lev0/types/iview_node.go

@@ -2,11 +2,11 @@ package types
 
 
 import svg "github.com/ajstarks/svgo"
 import svg "github.com/ajstarks/svgo"
 
 
-// IViewBase -- интерфейс базовой схемы
-type IViewBase interface {
-	IElemBase
+// IViewNode -- интерфейс базовой схемы
+type IViewNode interface {
+	IArchNode
 	// Coord -- координаты элемента
 	// Coord -- координаты элемента
 	Coord() IViewCoord
 	Coord() IViewCoord
 	// Draw -- рисование элемента
 	// Draw -- рисование элемента
 	Draw(canvas *svg.SVG)
 	Draw(canvas *svg.SVG)
-}
+}

+ 10 - 0
lev0/types/iview_text.go

@@ -0,0 +1,10 @@
+package types
+
+// IViewText -- текст для отображения
+type IViewText interface {
+	IViewNode
+	// Text -- возвращает текст
+	Text() IArchText
+	// Offset -- возвращает смещение текста
+	Offset() IViewOffset
+}

+ 17 - 0
lev0/types/iview_tree.go

@@ -0,0 +1,17 @@
+package types
+
+import (
+	svg "github.com/ajstarks/svgo"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+)
+
+// IViewTree -- интерфейс дерева для отрисовки
+type IViewTree interface {
+	// Draw -- рисует схему
+	Draw(canvas *svg.SVG)
+	// TreeView -- возвращает дерево отрисовщиков
+	TreeView() []IViewTree
+	// Get -- возвращает отрисовщик по ID
+	Get(id alias.ArchId) ktypes.Result[IViewNode]
+}

+ 32 - 0
lev1/arch_actor/arch_actor.go

@@ -0,0 +1,32 @@
+// package arch_actor -- сущность актора
+package arch_actor
+
+import (
+	"gitp78su.ipnodns.ru/svi/kern/v3"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_group_link"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_text"
+)
+
+// ArchActor -- сущность актора
+type ArchActor struct {
+	types.IArchNode
+	Label_        *arch_text.ArchText            `yaml:"label"`
+	UseGroupLink_ *arch_group_link.ArchGroupLink `yaml:"use_group_link"`
+}
+
+var (
+	hassert = kern.GetFnHassert()
+)
+
+// NewActor -- возвращает новый актор
+func NewActor(label *arch_text.ArchText, useGroupLink *arch_group_link.ArchGroupLink) *ArchActor {
+	hassert(label != nil, "NewActor(): label==nil")
+	hassert(useGroupLink != nil, "NewActor(): useGroupLink==nil")
+	sf := &ArchActor{
+		UseGroupLink_: useGroupLink,
+		Label_:        label,
+	}
+	return sf
+}

+ 32 - 0
lev1/arch_doc/arch_doc.go

@@ -0,0 +1,32 @@
+// package arch_yaml -- yaml-документ архитектуры
+package arch_doc
+
+import "sync"
+
+// ArchDoc -- документ архитектуры
+type ArchDoc struct {
+	Author    string `yaml:"author"`
+	Code_     string `yaml:"code"`
+	Name_     string `yaml:"name"`
+	Desc_     string `yaml:"desc"`
+	CreateAt_ string `yaml:"create_at"`
+	UpdateAt_ string `yaml:"update_at"`
+}
+
+var (
+	doc   *ArchDoc
+	block sync.Mutex
+)
+
+func GetArchDoc() *ArchDoc {
+	block.Lock()
+	defer block.Unlock()
+
+	if doc != nil {
+		return doc
+	}
+
+	sf := &ArchDoc{}
+	doc = sf
+	return doc
+}

+ 24 - 23
lev1/group_link/group_link.go → lev1/arch_group_link/arch_group_link.go

@@ -1,26 +1,26 @@
-// package group_link -- группа связей
-package group_link
+// package arch_group_link -- группа связей
+package arch_group_link
 
 
 import (
 import (
 	"fmt"
 	"fmt"
 
 
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/coord"
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/elem_base"
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/offset"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_node"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_coord"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_offset"
 )
 )
 
 
-// GroupLink -- группа связей
-type GroupLink struct {
-	ElemBase_ *elem_base.ElemBase `yaml:"elem_base"`
-	Links_    []alias.Id          `yaml:"link"` // Связи объекта
+// ArchGroupLink -- группа связей
+type ArchGroupLink struct {
+	*arch_node.ArchNode
+	Links_ []alias.ArchId `yaml:"link"` // Связи объекта
 }
 }
 
 
 // NewUseGroupLink -- возвращает новый группу связей в вариантах использования
 // NewUseGroupLink -- возвращает новый группу связей в вариантах использования
-func NewUseGroupLink(elemBase *elem_base.ElemBase, id alias.Id, label_ alias.Label,
-	labelCoord *coord.Coord, labelOffset *offset.Offset,
-	type_ alias.Type, elem map[string]interface{}, binElem []byte) (*GroupLink, error) {
+func NewUseGroupLink(elemBase *arch_node.ArchNode, id alias.ArchId, label_ alias.ArchText,
+	labelCoord *view_coord.ViewCoord, labelOffset *view_offset.Offset,
+	type_ alias.ArchType, elem map[string]interface{}, binElem []byte) (*ArchGroupLink, error) {
 	_links0, isOk := elem["links"]
 	_links0, isOk := elem["links"]
 	if !isOk {
 	if !isOk {
 		return nil, fmt.Errorf("NewUseGroupLink(): id=%q, field `links` not found", id)
 		return nil, fmt.Errorf("NewUseGroupLink(): id=%q, field `links` not found", id)
@@ -29,44 +29,45 @@ func NewUseGroupLink(elemBase *elem_base.ElemBase, id alias.Id, label_ alias.Lab
 	if !isOk {
 	if !isOk {
 		return nil, fmt.Errorf("NewUseGroupLink(): id=%q, field `links`(%T, %+v) not []interface{}", id, _links0, _links0)
 		return nil, fmt.Errorf("NewUseGroupLink(): id=%q, field `links`(%T, %+v) not []interface{}", id, _links0, _links0)
 	}
 	}
-	var links []alias.Id
+	var links []alias.ArchId
 	for _, _id := range _links {
 	for _, _id := range _links {
 		id0, isOk := _id.(string)
 		id0, isOk := _id.(string)
 		if !isOk {
 		if !isOk {
 			return nil, fmt.Errorf("NewUseGroupLink(): id=%q, field `links`(%T, %+v) not string", id, _id, _id)
 			return nil, fmt.Errorf("NewUseGroupLink(): id=%q, field `links`(%T, %+v) not string", id, _id, _id)
 		}
 		}
-		id1 := alias.Id(id0)
+		id1 := alias.ArchId(id0)
 		if id1 == "" {
 		if id1 == "" {
 			return nil, fmt.Errorf("NewUseGroupLink(): id=%q, link=%q is empty", id, _id)
 			return nil, fmt.Errorf("NewUseGroupLink(): id=%q, link=%q is empty", id, _id)
 		}
 		}
 		links = append(links, id1)
 		links = append(links, id1)
 	}
 	}
-	sf := &GroupLink{
-		ElemBase_: elemBase,
-		Links_:    links,
+	sf := &ArchGroupLink{
+		ArchNode: elemBase,
+		Links_:   links,
 	}
 	}
 	return sf, nil
 	return sf, nil
 }
 }
 
 
 // Check -- проверяет ошибки связей
 // Check -- проверяет ошибки связей
-func (sf *GroupLink) Check(mapElem map[alias.Id]types.IDrawer) string {
+func (sf *ArchGroupLink) Check(mapElem types.IViewTree) string {
 	var msgErr string
 	var msgErr string
 	if len(sf.Links_) == 0 {
 	if len(sf.Links_) == 0 {
 		msgErr = "Список ссылок(links) пуст\n"
 		msgErr = "Список ссылок(links) пуст\n"
 	}
 	}
 	// Проверить, что ссылки реально существует
 	// Проверить, что ссылки реально существует
 	for _, id := range sf.Links_ {
 	for _, id := range sf.Links_ {
-		link, ok := mapElem[id]
-		if !ok {
+		resDrawer := mapElem.Get(id)
+		if resDrawer.IsErr() {
 			msgErr += fmt.Sprintf("UseGroupLink.Check(): ссылка %q не существует\n", id)
 			msgErr += fmt.Sprintf("UseGroupLink.Check(): ссылка %q не существует\n", id)
 			continue
 			continue
 		}
 		}
-		ln, isOk := link.(types.IElemLink)
+		link := resDrawer.Val()
+		ln, isOk := link.(types.IArchLink)
 		if !isOk {
 		if !isOk {
 			msgErr += fmt.Sprintf("UseGroupLink.Check(): ссылка %q не ILinker\n", id)
 			msgErr += fmt.Sprintf("UseGroupLink.Check(): ссылка %q не ILinker\n", id)
 			continue
 			continue
 		}
 		}
-		if !(ln.Src().Id() == sf.ElemBase_.Id_ || ln.Dst().Id() == sf.ElemBase_.Id_) {
+		if !(ln.SrcId() == sf.Id_ || ln.Id() == sf.Id_) {
 			msgErr += fmt.Sprintf("UseGroupLink.Check(): ссылка %q не взаимная\n", id)
 			msgErr += fmt.Sprintf("UseGroupLink.Check(): ссылка %q не взаимная\n", id)
 			continue
 			continue
 		}
 		}
@@ -75,6 +76,6 @@ func (sf *GroupLink) Check(mapElem map[alias.Id]types.IDrawer) string {
 }
 }
 
 
 // Links -- ссылки вариантов использования
 // Links -- ссылки вариантов использования
-func (sf *GroupLink) Links() []alias.Id {
+func (sf *ArchGroupLink) Links() []alias.ArchId {
 	return sf.Links_
 	return sf.Links_
 }
 }

+ 71 - 66
lev1/elem_link/elem_link.go → lev1/arch_link/arch_link.go

@@ -1,21 +1,25 @@
-// package elem_link -- связь между объектами
-package elem_link
+// package arch_link -- связь между архитектурными объектами
+package arch_link
 
 
 import (
 import (
 	"fmt"
 	"fmt"
 
 
 	"gitp78su.ipnodns.ru/svi/kern/v3"
 	"gitp78su.ipnodns.ru/svi/kern/v3"
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
 
 
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_text"
 )
 )
 
 
-// ElemLink -- связь между объектами
-type ElemLink struct {
-	types.IViewLabel
-	CoordEnd_ types.IViewCoord    `yaml:"coord_end"` // Координаты второй точки
-	Src_      types.IElemBase `yaml:"src"`       // Источник координат
-	Dst_      types.IElemBase `yaml:"dst"`       // Получатель координат
+// ArchLink -- связь между архитектурными объектами
+type ArchLink struct {
+	*arch_text.ArchText
+	SrcId_ alias.ArchId `yaml:"src_id"` // Источник координат
+	src    types.IArchNode
+	DstId_ alias.ArchId `yaml:"dst_id"` // Получатель координат
+	dst    types.IArchNode
 
 
 	TypeLink_ string `yaml:"type_link"` // Тип связи
 	TypeLink_ string `yaml:"type_link"` // Тип связи
 }
 }
@@ -24,54 +28,54 @@ var (
 	hassert = kern.GetFnHassert()
 	hassert = kern.GetFnHassert()
 )
 )
 
 
-// NewElemLink -- возвращает новую связь
-func NewElemLink(elemLabel types.IViewLabel, coordEnd types.IViewCoord,
-	src, dst types.IElemBase, typeLink string) types.IElemLink {
-
-	sf := &ElemLink{
-		IViewLabel: elemLabel,
-		CoordEnd_: coordEnd,
-		Src_:      src,
-		Dst_:      dst,
-		TypeLink_: typeLink,
+// NewArchLink -- возвращает новую связь
+func NewArchLink(archText *arch_text.ArchText) *ArchLink {
+	hassert(archText != nil, "NewArchLink: archText == nil")
+	sf := &ArchLink{
+		ArchText: archText,
 	}
 	}
-	sf.SelfCheck()
+	_ = types.IArchLink(sf)
 	return sf
 	return sf
 }
 }
 
 
-// SelfCheck -- самопроверка элемента
-func (sf *ElemLink) SelfCheck() {
-	sf.IViewLabel.SelfCheck()
-	hassert(sf.CoordEnd_ != nil, "ElemLink.SelfCheck(): id=%v, CoordEnd_ == nil", sf.Id())
-	hassert(sf.Src_ != nil, "ElemLink.SelfCheck(): id=%v, Src_ == nil", sf.Id())
-	hassert(sf.Dst_ != nil, "ElemLink.SelfCheck(): id=%v, Dst_ == nil", sf.Id())
-	hassert(sf.TypeLink_ != "", "ElemLink.SelfCheck(): id=%v, TypeLink_ is empty", sf.Id())
+// InvarCheck -- самопроверка элемента
+func (sf *ArchLink) InvarCheck() ktypes.Option[error] {
+	optErr := sf.InvarNode()
+	if optErr.IsVal() {
+		return optErr
+	}
+	if sf.SrcId_ == "" {
+		err := fmt.Errorf("ArchLink.SelfCheck(): id=%v, Src_ == nil", sf.Id())
+		return ktypes.NewSome(err)
+	}
+	if sf.DstId_ == "" {
+		err := fmt.Errorf("ArchLink.SelfCheck(): id=%v, Dst_ == nil", sf.Id())
+		return ktypes.NewSome(err)
+	}
+	if sf.TypeLink_ == "" {
+		err := fmt.Errorf("ArchLink.SelfCheck(): id=%v, TypeLink_ is empty", sf.Id())
+		return ktypes.NewSome(err)
+	}
+	return ktypes.NewNone[error]()
 }
 }
 
 
 // TypeLink -- тип связи
 // TypeLink -- тип связи
 //
 //
 //go:fix inline
 //go:fix inline
-func (sf *ElemLink) TypeLink() string {
+func (sf *ArchLink) TypeLink() string {
 	return sf.TypeLink_
 	return sf.TypeLink_
 }
 }
 
 
-// CoordEnd -- координаты конца связи
-//
-//go:fix inline
-func (sf *ElemLink) CoordEnd() types.IViewCoord {
-	return sf.CoordEnd_
-}
-
 // Links -- ссылки актора
 // Links -- ссылки актора
-func (sf *ElemLink) Links() []types.IElemBase {
-	return []types.IElemBase{sf.Src_, sf.Dst_}
+func (sf *ArchLink) Links() []types.IArchNode {
+	return []types.IArchNode{sf.src, sf.dst}
 }
 }
 
 
 // Check -- проверяет связи между объектами
 // Check -- проверяет связи между объектами
-func (sf *ElemLink) Check() string {
-	if sf.Dst_.Id() == sf.Src_.Id() {
+func (sf *ArchLink) Check() string {
+	if sf.DstId_ == sf.SrcId_ {
 		return fmt.Sprintf("ВНИМАНИЕ! Источник и получатель совпадают\nsrc=%v, dst=%v\n",
 		return fmt.Sprintf("ВНИМАНИЕ! Источник и получатель совпадают\nsrc=%v, dst=%v\n",
-			sf.Src_.Id(), sf.Dst_.Id())
+			sf.SrcId_, sf.DstId_)
 	}
 	}
 	if msgErr := sf.checkSrc(); msgErr != "" {
 	if msgErr := sf.checkSrc(); msgErr != "" {
 		return "ОШИБКА при проверке связи источника\n" + msgErr
 		return "ОШИБКА при проверке связи источника\n" + msgErr
@@ -86,16 +90,17 @@ func (sf *ElemLink) Check() string {
 }
 }
 
 
 // проверить связь получателя
 // проверить связь получателя
-func (sf *ElemLink) checkDst() string {
-	if sf.Dst_ == nil {
+func (sf *ArchLink) checkDst() string {
+	if sf.DstId_ == "" {
 		return "ОШИБКА получатель `dst` не задан"
 		return "ОШИБКА получатель `dst` не задан"
 	}
 	}
 	// Вычислить на допустимые типы для получателя
 	// Вычислить на допустимые типы для получателя
-	switch sf.Dst_.Type() {
+	switch sf.dst.Type() {
 	case cons.TypeUseActor:
 	case cons.TypeUseActor:
-		actor, isOk := sf.Dst_.(types.IElemActor)
+		actor, isOk := sf.dst.(types.IArchActor)
 		if !isOk {
 		if !isOk {
-			return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n", sf.Dst_.Id(), sf.Dst_.Type())
+			return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n",
+				sf.DstId_, sf.dst.Type())
 		}
 		}
 		isOk = false
 		isOk = false
 		for _, id := range actor.GroupLink().Links() {
 		for _, id := range actor.GroupLink().Links() {
@@ -109,20 +114,20 @@ func (sf *ElemLink) checkDst() string {
 				sf.Id(), actor.Id())
 				sf.Id(), actor.Id())
 		}
 		}
 	case cons.TypeUseLink:
 	case cons.TypeUseLink:
-		link, isOk := sf.Dst_.(types.IElemLink)
+		link, isOk := sf.dst.(types.IArchLink)
 		if !isOk {
 		if !isOk {
 			return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n",
 			return fmt.Sprintf("Недопустимый тип получателя(%q)\nтип=%q\n",
-				sf.Dst_.Id(), sf.Dst_.Type())
+				sf.DstId_, sf.dst.Type())
 		}
 		}
-		isOk = sf.Id() == link.Dst().Id() || sf.Id() == link.Src().Id()
+		isOk = sf.Id() == link.DstId() || sf.Id() == link.SrcId()
 		if !isOk {
 		if !isOk {
 			return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.Id(), link.Id())
 			return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n", sf.Id(), link.Id())
 		}
 		}
 	case cons.TypeUseCase:
 	case cons.TypeUseCase:
-		useCase, isOk := sf.Dst_.(types.IElemUseCase)
+		useCase, isOk := sf.dst.(types.IArchUseCase)
 		if !isOk {
 		if !isOk {
 			return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nтип=%q\n",
 			return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nтип=%q\n",
-				sf.Id(), sf.Dst_.Id(), sf.Dst_.Type())
+				sf.Id(), sf.DstId_, sf.dst.Type())
 		}
 		}
 		isOk = false
 		isOk = false
 		for id := range useCase.Links() {
 		for id := range useCase.Links() {
@@ -137,20 +142,20 @@ func (sf *ElemLink) checkDst() string {
 		}
 		}
 	default: // Недопустимый источник
 	default: // Недопустимый источник
 		return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nid=%q\n",
 		return fmt.Sprintf("id=%q, Недопустимый тип получателя(%q)\nid=%q\n",
-			sf.Id(), sf.Dst_.Type(), sf.Dst_.Id())
+			sf.Id(), sf.dst.Type(), sf.DstId_)
 	}
 	}
 	return ""
 	return ""
 }
 }
 
 
 // Проверяет связь источника
 // Проверяет связь источника
-func (sf *ElemLink) checkSrc() string {
-	if sf.Src_ == nil {
+func (sf *ArchLink) checkSrc() string {
+	if sf.src == nil {
 		return "ВНИМАНИЕ! Источник связи не задан(src)\n"
 		return "ВНИМАНИЕ! Источник связи не задан(src)\n"
 	}
 	}
-	switch sf.Src_.Type() {
+	switch sf.src.Type() {
 	case cons.TypeUseActor:
 	case cons.TypeUseActor:
 		isOk := false
 		isOk := false
-		actor := sf.Src_.(types.IElemActor)
+		actor := sf.src.(types.IArchActor)
 		for _, id := range actor.GroupLink().Links() { // Проверка на взаимность
 		for _, id := range actor.GroupLink().Links() { // Проверка на взаимность
 			if id == sf.Id() {
 			if id == sf.Id() {
 				isOk = true
 				isOk = true
@@ -161,21 +166,21 @@ func (sf *ElemLink) checkSrc() string {
 			return fmt.Sprintf("Невзаимная ссылка с актором %q\n", actor.Id())
 			return fmt.Sprintf("Невзаимная ссылка с актором %q\n", actor.Id())
 		}
 		}
 	case cons.TypeUseLink:
 	case cons.TypeUseLink:
-		link, isOk := sf.Src_.(types.IElemLink)
+		link, isOk := sf.src.(types.IArchLink)
 		if !isOk {
 		if !isOk {
 			return fmt.Sprintf("Несоответствие типа источника(%q)\nтип='useLink'\n",
 			return fmt.Sprintf("Несоответствие типа источника(%q)\nтип='useLink'\n",
-				sf.Src_.Id())
+				sf.SrcId_)
 		}
 		}
-		isOk = sf.Id() == link.Dst().Id() || sf.Id() == link.Src().Id()
+		isOk = sf.Id() == link.DstId() || sf.Id() == link.SrcId()
 		if !isOk {
 		if !isOk {
 			return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n",
 			return fmt.Sprintf("id=%q, Невзаимная ссылка(%q)\n",
 				sf.Id(), link.Id())
 				sf.Id(), link.Id())
 		}
 		}
 	case cons.TypeUseCase:
 	case cons.TypeUseCase:
-		useCase, isOk := sf.Src_.(types.IElemUseCase)
+		useCase, isOk := sf.src.(types.IArchUseCase)
 		if !isOk {
 		if !isOk {
 			return fmt.Sprintf("id=%q, Тип источника(%q) не совпадает с фактическим\nтип='useCase'\n",
 			return fmt.Sprintf("id=%q, Тип источника(%q) не совпадает с фактическим\nтип='useCase'\n",
-				sf.Id(), sf.Src_.Id())
+				sf.Id(), sf.SrcId())
 		}
 		}
 		isOk = false
 		isOk = false
 		for id := range useCase.Links() { // Проверка на взаимность
 		for id := range useCase.Links() { // Проверка на взаимность
@@ -190,21 +195,21 @@ func (sf *ElemLink) checkSrc() string {
 		}
 		}
 	default: // Неизвестный источник
 	default: // Неизвестный источник
 		return fmt.Sprintf("id=%q, неизвестный тип источника(%q)<br>id=%q\n",
 		return fmt.Sprintf("id=%q, неизвестный тип источника(%q)<br>id=%q\n",
-			sf.Id(), sf.Src_.Type(), sf.Src_.Id())
+			sf.Id(), sf.src.Type(), sf.SrcId())
 	}
 	}
 	return ""
 	return ""
 }
 }
 
 
-// Src -- возвращает источник связи
+// SrcId -- возвращает ID источника связи
 //
 //
 //go:fix inline
 //go:fix inline
-func (sf *ElemLink) Src() types.IElemBase {
-	return sf.Src_
+func (sf *ArchLink) SrcId() alias.ArchId {
+	return sf.SrcId_
 }
 }
 
 
-// Dst -- возвращает получателя связи
+// DstId -- возвращает ID получателя связи
 //
 //
 //go:fix inline
 //go:fix inline
-func (sf *ElemLink) Dst() types.IElemBase {
-	return sf.Dst_
+func (sf *ArchLink) DstId() alias.ArchId {
+	return sf.DstId_
 }
 }

+ 79 - 0
lev1/arch_node/arch_node.go

@@ -0,0 +1,79 @@
+// package arch_node -- архитектурный узел
+package arch_node
+
+import (
+	"fmt"
+
+	"github.com/google/uuid"
+	"gitp78su.ipnodns.ru/svi/kern/v3"
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+)
+
+// ArchNode -- архитектурный узел
+type ArchNode struct {
+	Id_       alias.ArchId   `yaml:"id"`        // Идентификатор узла
+	Type_     alias.ArchType `yaml:"type"`      // Тип узла
+	ParentId_ alias.ArchId   `yaml:"parent_id"` // ID предка
+}
+
+var (
+	hassert = kern.GetFnHassert()
+)
+
+// NewArchNode -- возвращает новый архитектурный узел
+func NewArchNode(archType alias.ArchType, parentId alias.ArchId) *ArchNode {
+	sf := &ArchNode{
+		Id_:       alias.ArchId(uuid.New().String()),
+		Type_:     archType,
+		ParentId_: parentId,
+	}
+	sf.selfCheck()
+	return sf
+}
+
+// ParentId -- возвращает ID родителя
+//
+//go:fix inline
+func (sf *ArchNode) ParentId() alias.ArchId {
+	return sf.ParentId_
+}
+
+// Type -- возвращает тип объекта
+//
+//go:fix inline
+func (sf *ArchNode) Type() alias.ArchType {
+	return sf.Type_
+}
+
+// Id -- возвращает ID объекта
+//
+//go:fix inline
+func (sf *ArchNode) Id() alias.ArchId {
+	return sf.Id_
+}
+
+// SelfCheck -- самопроверка базового элемента
+func (sf *ArchNode) selfCheck() {
+	hassert(sf.Id_ != "", "ArchNode.selfCheck(): id is empty")
+	hassert(sf.Type_ != "", "ArchNode.selfCheck(): id:%s, Type_ is empty", sf.Id_)
+	hassert(sf.ParentId_ != "", "ArchNode.selfCheck(): id:%s, ParentId_ is empty", sf.Id_)
+}
+
+// InvarNode -- проверка инвариантов
+func (sf *ArchNode) InvarNode() ktypes.Option[error] {
+	if sf.Id_ == "" {
+		err := fmt.Errorf("ArchNode.InvarNode(): Id_ is empty")
+		return ktypes.NewSome(err)
+	}
+	if sf.Type_ == "" {
+		err := fmt.Errorf("ArchNode.InvarNode(): id:%s, Type_ is empty", sf.Id_)
+		return ktypes.NewSome(err)
+	}
+	if sf.ParentId_ == "" {
+		err := fmt.Errorf("ArchNode.InvarNode(): id:%s, ParentId_ is empty", sf.Id_)
+		return ktypes.NewSome(err)
+	}
+	return ktypes.NewNone[error]()
+}

+ 55 - 0
lev1/arch_text/arch_text.go

@@ -0,0 +1,55 @@
+// package arch_text -- архитектурный текст
+package arch_text
+
+import (
+	"fmt"
+
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_node"
+)
+
+// ArchText -- архитектурный текст
+type ArchText struct {
+	*arch_node.ArchNode
+	Text_ alias.ArchText `yaml:"text"` // Значение текста
+}
+
+// NewArchText -- возвращает новый архитектурный текст
+func NewArchText(text alias.ArchText, parentId alias.ArchId) ktypes.Result[*ArchText] {
+	sf := &ArchText{
+		ArchNode: arch_node.NewArchNode("arch_text", parentId),
+		Text_:    text,
+	}
+	someErr := sf.InvarCheck()
+	if someErr.IsVal() {
+		return ktypes.NewErr[*ArchText](someErr.Val())
+	}
+	_ = types.IArchText(sf)
+	return ktypes.NewOk(sf)
+}
+
+// InvarCheck -- проверка инвариантов
+func (sf *ArchText) InvarCheck() ktypes.Option[error] {
+	if sf.ArchNode == nil {
+		err := fmt.Errorf("ArchText.InvarCheck(): ArchNode==nil")
+		return ktypes.NewSome(err)
+	}
+	return ktypes.NewNone[error]()
+}
+
+// String -- возвращает метку
+//
+//go:fix inline
+func (sf *ArchText) String() string {
+	return string(sf.Text_)
+}
+
+// Get -- возвращает метку
+//
+//go:fix inline
+func (sf *ArchText) Get() alias.ArchText {
+	return sf.Text_
+}

+ 96 - 0
lev1/arch_use_case/arch_use_case.go

@@ -0,0 +1,96 @@
+// package arch_use_case -- вариант использования
+package arch_use_case
+
+import (
+	"fmt"
+
+	// "gitp78su.ipnodns.ru/svi/kern/v3"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_node"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_text"
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+)
+
+// ArchUseCase -- вариант использования
+type ArchUseCase struct {
+	*arch_node.ArchNode
+	Links_  []alias.ArchId `yaml:"links_id"` // Список ссылок
+	links   map[alias.ArchId]types.IArchLink
+	TextId_ alias.ArchId `yaml:"text_id"` // ID текста
+	text    *arch_text.ArchText
+}
+
+// var (
+// 	hassert = kern.GetFnHassert()
+// )
+
+// NewUseCase -- возвращает новый вариант использования
+func NewUseCase(links []alias.ArchId, parentId alias.ArchId) *ArchUseCase {
+	// id := elemBase.Id()
+	// _links0, isOk := elemBase.Elem_["links"]
+	// hassert(isOk, "NewUseCase(): id=%q, links not found", id)
+	// _links, isOk := _links0.([]interface{})
+	// hassert(isOk, "NewUseCase(): id=%q, `links`(%+v) not []interface{}", id, _links0)
+	// for _, _id := range _links {
+	// 	id0, isOk := _id.(string)
+	// 	hassert(isOk, "NewUseCase(): id=%q, `link`(%T, %+v) not string", id, _id, _id)
+	// 	id1 := alias.Id(id0)
+	// 	hassert(id1 != "", "NewUseCase(): id=%q, `link` is empty", id)
+	// 	links = append(links, id1)
+	// }
+	sf := &ArchUseCase{
+		ArchNode: arch_node.NewArchNode("use_case", parentId),
+		Links_:   links,
+	}
+	sf.SelfCheck()
+	_ = types.IArchUseCase(sf)
+	return sf
+}
+
+// Text -- текст варианта использования
+//
+//go:fix inline
+func (sf *ArchUseCase) Text() types.IArchText {
+	return sf.text
+}
+
+// InvarCheck -- проверка собственного состояния
+func (sf *ArchUseCase) InvarCheck() ktypes.Option[error] {
+	optErr := sf.ArchNode.InvarNode()
+	if optErr.IsVal() {
+		err := fmt.Errorf("ArchUseCase.InvarCheck(): err=\n\t%w", optErr.Val())
+		return ktypes.NewSome(err)
+	}
+	sf.SelfCheck()
+	return ktypes.NewNone[error]()
+}
+
+// SelfCheck -- самопроверка
+func (sf *ArchUseCase) SelfCheck() {
+	sf.InvarNode()
+	var msgErr string
+	// Нет ссылок
+	if len(sf.Links_) == 0 {
+		return
+	}
+	// Проверить, что ссылки реально существует
+	for id, link := range sf.links {
+		if link.Type() != cons.TypeUseLink {
+			msgErr += fmt.Sprintf("id=%q, не тип %q, тип=%q\n", id, cons.TypeUseLink, link.Type())
+			continue
+		}
+		// Проверить что ссылка взаимная
+		if !(link.SrcId() == sf.Id() || link.DstId() == sf.Id()) {
+			msgErr += fmt.Sprintf("id=%q, ссылка не взаимная\nsrc=%q, dst=%q\n",
+				id, link.SrcId(), link.DstId())
+		}
+	}
+}
+
+// Links -- ссылки вариантов использования
+func (sf *ArchUseCase) Links() map[alias.ArchId]types.IArchLink {
+	return sf.links
+}

+ 64 - 0
lev1/arch_use_group/arch_use_group.go

@@ -0,0 +1,64 @@
+// package arch_use_group -- группа вариантов использования
+package arch_use_group
+
+import (
+	"fmt"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_node"
+	"gitp78su.ipnodns.ru/svi/kern/v3"
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+)
+
+// ArchUseCaseGroup -- группа вариантов использования
+type ArchUseCaseGroup struct {
+	*arch_node.ArchNode
+}
+
+var (
+	hassert = kern.GetFnHassert()
+)
+
+// NewArchUseCaseGroup -- возвращает новую группу вариантов использования
+func NewArchUseCaseGroup(parentId alias.ArchId) *ArchUseCaseGroup {
+	sf := &ArchUseCaseGroup{
+		ArchNode: arch_node.NewArchNode("use_case_group", parentId),
+	}
+	sf.SelfCheck()
+	_ = types.IArchUseGroup(sf)
+	return sf
+}
+
+// Len -- заглушка на длину
+func (sf *ArchUseCaseGroup) Len() int {
+	return 0
+}
+
+// InvarCheck -- проверка инвариантов
+func (sf *ArchUseCaseGroup) InvarCheck() ktypes.Option[error] {
+	if sf.ArchNode == nil {
+		err := fmt.Errorf("ArchUseCaseGroup.InvarCheck(): ArchNode==nil")
+		return ktypes.NewSome(err)
+	}
+	return ktypes.NewNone[error]()
+}
+
+// Size -- возвращает размер
+//
+//go:fix inline
+// func (sf *ArchUseCaseGroup) Size() types.IViewSize {
+// 	return sf.Size_
+// }
+
+// Links -- заглушка на связи между объектами
+//
+//go:fix inline
+func (sf *ArchUseCaseGroup) Links() []alias.ArchId {
+	return []alias.ArchId{sf.Id()}
+}
+
+// Check -- заглушка под проверку
+func (sf *ArchUseCaseGroup) SelfCheck() {
+	hassert(sf.ArchNode != nil, "NewUseGroup(): IElemBase is nil")
+}

+ 0 - 11
lev1/arch_yaml/arch_yaml.go

@@ -1,11 +0,0 @@
-// package arch_yaml -- yaml-документ архитектуры
-package arch_yaml
-
-// ArchYaml -- yaml-документ архитектуры
-type ArchYaml struct {
-	Code_     string `yaml:"code"`
-	Name_     string `yaml:"name"`
-	Desc_     string `yaml:"desc"`
-	CreateAt_ string `yaml:"create_at"`
-	UpdateAt_ string `yaml:"update_at"`
-}

+ 3 - 3
pkg/elems/canvas/canvas.go → lev1/canvas/canvas.go

@@ -34,8 +34,8 @@ func NewCanvas(diaMode string, size types.IViewSize, pos types.IViewCoord) *Canv
 
 
 // Draw -- рисует холст
 // Draw -- рисует холст
 func (sf *Canvas) Draw(canvas *svg.SVG) {
 func (sf *Canvas) Draw(canvas *svg.SVG) {
-	x,y := sf.pos.Int()
-	w,h := sf.size.Int()
+	x, y := sf.pos.Int()
+	w, h := sf.size.Int()
 	canvas.Rect(0, 0, w, h, "fill:white;stroke:red;stroke-width:1")
 	canvas.Rect(0, 0, w, h, "fill:white;stroke:red;stroke-width:1")
 	canvas.Text(x, y+2, "АРХИТЕКТУРНОЕ РЕШЕНИЕ", "font-size: 20px; font-family: sans-serif; fill: black")
 	canvas.Text(x, y+2, "АРХИТЕКТУРНОЕ РЕШЕНИЕ", "font-size: 20px; font-family: sans-serif; fill: black")
 	canvas.Text(x+15, y+20, sf.diaMode, "font-size: 14px; font-family: sans-serif; fill: black")
 	canvas.Text(x+15, y+20, sf.diaMode, "font-size: 14px; font-family: sans-serif; fill: black")
@@ -44,6 +44,6 @@ func (sf *Canvas) Draw(canvas *svg.SVG) {
 // Size -- возвращает размер холста
 // Size -- возвращает размер холста
 //
 //
 //go:fix inline
 //go:fix inline
-func (sf *Canvas) Size()types.IViewSize {
+func (sf *Canvas) Size() types.IViewSize {
 	return sf.size
 	return sf.size
 }
 }

+ 0 - 47
lev1/coord/coord.go

@@ -1,47 +0,0 @@
-// package coord -- координаты точки
-package coord
-
-import (
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-)
-
-// Coord -- координаты точки
-type Coord struct {
-	X_ alias.CoordX `yaml:"x"` // Координата X
-	Y_ alias.CoordY `yaml:"y"` // Координата Y
-}
-
-// NewCoord -- возвращает новую координаты
-func NewCoord(x alias.CoordX, y alias.CoordY) types.IViewCoord {
-	sf := &Coord{
-		X_: x,
-		Y_: y,
-	}
-	return sf
-}
-
-// X -- возвращает координату X
-func (sf *Coord) X() alias.CoordX {
-	return sf.X_
-}
-
-// Y -- возвращает координату Y
-func (sf *Coord) Y() alias.CoordY {
-	return sf.Y_
-}
-
-// Coord -- возвращает координаты
-func (sf *Coord) Coord() (alias.CoordX, alias.CoordY) {
-	return sf.X_, sf.Y_
-}
-
-// Int -- возвращает целые координаты
-func (sf *Coord) Int() (int, int) {
-	return int(sf.X_), int(sf.Y_)
-}
-
-// Get -- возвращает целые координаты
-func (sf *Coord) Get() (alias.CoordX, alias.CoordY) {
-	return sf.X_, sf.Y_
-}

+ 0 - 30
lev1/elem_actor/elem_actor.go

@@ -1,30 +0,0 @@
-// package elem_actor -- сущность актора
-package elem_actor
-
-import (
-	"gitp78su.ipnodns.ru/svi/kern/v3"
-
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/elem_label"
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/group_link"
-)
-
-// Actor -- сущность актора
-type Actor struct {
-	Label_        *elem_label.ElemLabel `yaml:"label"`
-	UseGroupLink_ *group_link.GroupLink `yaml:"use_group_link"`
-}
-
-var (
-	hassert = kern.GetFnHassert()
-)
-
-// NewActor -- возвращает новый актор
-func NewActor(label *elem_label.ElemLabel, useGroupLink *group_link.GroupLink) (*Actor, error) {
-	hassert(label != nil, "NewActor(): label==nil")
-	hassert(useGroupLink != nil, "NewActor(): useGroupLink==nil")
-	sf := &Actor{
-		UseGroupLink_: useGroupLink,
-		Label_:        label,
-	}
-	return sf, nil
-}

+ 0 - 60
lev1/elem_base/elem_base.go

@@ -1,60 +0,0 @@
-// package elem_base -- базовый объект
-package elem_base
-
-import (
-	"github.com/google/uuid"
-
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-	"gitp78su.ipnodns.ru/svi/kern/v3"
-)
-
-// ElemBase -- базовый объект
-type ElemBase struct {
-	Id_    alias.Id     `yaml:"id"`    // Идентификатор объекта
-	Type_  alias.Type   `yaml:"type"`  // Тип объекта
-	Coord_ types.IViewCoord `yaml:"coord"` // Координаты элемента
-}
-
-var (
-	hassert = kern.GetFnHassert()
-)
-
-// NewElemBase -- возвращает новый базовый объект
-func NewElemBase(coord types.IViewCoord, type_ alias.Type) types.IElemBase {
-	sf := &ElemBase{
-		Coord_: coord,
-		Id_:    alias.Id(uuid.New().String()),
-		Type_:  type_,
-	}
-	sf.SelfCheck()
-	return sf
-}
-
-
-// InvarCheck -- проверяет инварианты базового элемента
-func (sf *ElemBase) InvarCheck() string {
-	hassert(false, "ElemBase.InvarCheck(): id:%v, not implemented", sf.Id_)
-	return ""
-}
-
-// Type -- возвращает тип объекта
-//
-//go:fix inline
-func (sf *ElemBase) Type() alias.Type {
-	return sf.Type_
-}
-
-// Id -- возвращает ID объекта
-//
-//go:fix inline
-func (sf *ElemBase) Id() alias.Id {
-	return sf.Id_
-}
-
-// SelfCheck -- самопроверка базового элемента
-func (sf *ElemBase) SelfCheck() {
-	hassert(sf.Id_ != "", "ElemBase.SelfCheck(): Id_ is empty")
-	hassert(sf.Type_ != "", "NewElemBase(): Type_ is empty")
-	hassert(sf.Coord_ != nil, "NewElemBase(): Coord_ == nil")
-}

+ 0 - 71
lev1/elem_label/elem_label.go

@@ -1,71 +0,0 @@
-// package elem_label -- текстовая метка для отображения
-package elem_label
-
-import (
-	svg "github.com/ajstarks/svgo"
-	"gitp78su.ipnodns.ru/svi/kern/v3"
-
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/elem_base"
-)
-
-// ElemLabel -- текстовая метка для отображения
-type ElemLabel struct {
-	types.IElemBase
-	Val_    alias.Label   `yaml:"val"`    // Метка для вывода
-	Offset_ types.IViewOffset `yaml:"offset"` // Смещение метки
-}
-
-var (
-	hassert = kern.GetFnHassert()
-)
-
-// NewElemLabel -- возвращает новую метку
-func NewElemLabel(label alias.Label, coord types.IViewCoord, offset types.IViewOffset) types.IViewLabel {
-	sf := &ElemLabel{
-		IElemBase: elem_base.NewElemBase(coord, "elem_label"),
-		Val_:      label,
-		Offset_:   offset,
-	}
-	sf.SelfCheck()
-	return sf
-}
-
-// Draw -- отрисовка метки
-func (sf *ElemLabel) Draw(canvas *svg.SVG) {
-	strLabel := sf.String()
-	if strLabel != "" {
-		x, y := sf.Offset_.Int()
-		offX := int(sf.Offset_.X())
-		canvas.Text(x+offX, y-8, strLabel,
-			"font-size: 14px; font-family: Courier; fill: black")
-	}
-}
-
-// SelfCheck -- самопроверка типа
-func (sf *ElemLabel) SelfCheck() {
-	sf.IElemBase.SelfCheck()
-	hassert(sf.Offset_ != nil, "SelfCheck(): Offset_ is nil")
-}
-
-// String -- возвращает метку
-//
-//go:fix inline
-func (sf *ElemLabel) String() string {
-	return string(sf.Val_)
-}
-
-// Get -- возвращает метку
-//
-//go:fix inline
-func (sf *ElemLabel) Get() alias.Label {
-	return sf.Val_
-}
-
-// Offset -- возвращает смещение метки
-//
-//go:fix inline
-func (sf *ElemLabel) Offset() types.IViewOffset {
-	return sf.Offset_
-}

+ 0 - 79
lev1/elem_use_case/elem_use_case.go

@@ -1,79 +0,0 @@
-// package elem_use_case -- вариант использования
-package elem_use_case
-
-import (
-	"fmt"
-
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-	"gitp78su.ipnodns.ru/svi/kern/v3"
-)
-
-// UseCase -- вариант использования
-type UseCase struct {
-	types.IElemBase
-	Size_  types.IViewSize                       `yaml:"size"`
-	Links_ map[alias.Id]types.IElemGroupLink `yaml:"links"` // Список ссылок
-}
-
-var (
-	hassert = kern.GetFnHassert()
-)
-
-// NewUseCase -- возвращает новый вариант использования
-func NewUseCase(elemBase types.IElemBase, size types.IViewSize,
-	links map[alias.Id]types.IElemGroupLink) *UseCase {
-	// id := elemBase.Id()
-	// _links0, isOk := elemBase.Elem_["links"]
-	// hassert(isOk, "NewUseCase(): id=%q, links not found", id)
-	// _links, isOk := _links0.([]interface{})
-	// hassert(isOk, "NewUseCase(): id=%q, `links`(%+v) not []interface{}", id, _links0)
-	// for _, _id := range _links {
-	// 	id0, isOk := _id.(string)
-	// 	hassert(isOk, "NewUseCase(): id=%q, `link`(%T, %+v) not string", id, _id, _id)
-	// 	id1 := alias.Id(id0)
-	// 	hassert(id1 != "", "NewUseCase(): id=%q, `link` is empty", id)
-	// 	links = append(links, id1)
-	// }
-	sf := &UseCase{
-		IElemBase: elemBase,
-		Size_:     size,
-		Links_:    links,
-	}
-	sf.SelfCheck()
-	return sf
-}
-
-// SelfCheck -- самопроверка
-func (sf *UseCase) SelfCheck() {
-	sf.IElemBase.SelfCheck()
-	hassert(sf.Size_ != nil, "UseCase.SelfCheck(): Size_ == nil")
-	var msgErr string
-	// Нет ссылок
-	if len(sf.Links_) == 0 {
-		return
-	}
-	// Проверить, что ссылки реально существует
-	for id, link := range sf.Links_ {
-		if link.Type() != cons.TypeUseLink {
-			msgErr += fmt.Sprintf("id=%q, не тип %q, тип=%q\n", id, cons.TypeUseLink, link.Type())
-			continue
-		}
-		ln, isOk := link.(types.IElemLink)
-		if !isOk {
-			msgErr += fmt.Sprintf("id=%q, не тип `link`, link=%#v\n", id, link)
-			continue
-		}
-		// Проверить что ссылка взаимная
-		if !(ln.Src().Id() == sf.Id() || ln.Dst().Id() == sf.Id()) {
-			msgErr += fmt.Sprintf("id=%q, ссылка не взаимная\nsrc=%q, dst=%q\n",
-			id, ln.Src().Id(), ln.Dst().Id())
-		}
-	}
-}
-
-// Links -- ссылки вариантов использования
-func (sf *UseCase) Links() map[alias.Id]types.IElemGroupLink {
-	return sf.Links_
-}

+ 0 - 49
lev1/elem_use_group/elem_use_group.go

@@ -1,49 +0,0 @@
-// package elem_use_group -- группа вариантов использования
-package elem_use_group
-
-import (
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-	"gitp78su.ipnodns.ru/svi/kern/v3"
-)
-
-// UseGroup -- группа вариантов использования
-type UseGroup struct {
-	types.IElemBase
-	Size_ types.IViewSize
-}
-
-var (
-	hassert = kern.GetFnHassert()
-)
-
-// NewUseGroup -- возвращает новую группу вариант использования
-func NewUseGroup(elemBase types.IElemBase, size types.IViewSize) types.IElemUseGroup {
-	sf := &UseGroup{
-		IElemBase: elemBase,
-		Size_:     size,
-	}
-	sf.SelfCheck()
-	return sf
-}
-
-// Size -- возвращает размер
-//
-//go:fix inline
-func (sf *UseGroup) Size() types.IViewSize {
-	return sf.Size_
-}
-
-
-// Links -- заглушка на связи между объектами
-//
-//go:fix inline
-func (sf *UseGroup) Links() []alias.Id {
-	return []alias.Id{sf.IElemBase.Id()}
-}
-
-// Check -- заглушка под проверку
-func (sf *UseGroup) SelfCheck() {
-	hassert(sf.IElemBase != nil, "NewUseGroup(): IElemBase is nil")
-	hassert(sf.Size_ != nil, "NewUseGroup(): Size_ is nil")
-}

+ 47 - 0
lev1/view_coord/view_coord.go

@@ -0,0 +1,47 @@
+// package view_coord -- координаты точки
+package view_coord
+
+import (
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+)
+
+// ViewCoord -- координаты точки
+type ViewCoord struct {
+	X_ alias.CoordX `yaml:"x"` // Координата X
+	Y_ alias.CoordY `yaml:"y"` // Координата Y
+}
+
+// NewViewCoord -- возвращает новую координату
+func NewViewCoord(x alias.CoordX, y alias.CoordY) types.IViewCoord {
+	sf := &ViewCoord{
+		X_: x,
+		Y_: y,
+	}
+	return sf
+}
+
+// X -- возвращает координату X
+func (sf *ViewCoord) X() alias.CoordX {
+	return sf.X_
+}
+
+// Y -- возвращает координату Y
+func (sf *ViewCoord) Y() alias.CoordY {
+	return sf.Y_
+}
+
+// Coord -- возвращает координаты
+func (sf *ViewCoord) Coord() (alias.CoordX, alias.CoordY) {
+	return sf.X_, sf.Y_
+}
+
+// Int -- возвращает целые координаты
+func (sf *ViewCoord) Int() (int, int) {
+	return int(sf.X_), int(sf.Y_)
+}
+
+// Get -- возвращает координаты
+func (sf *ViewCoord) Get() (alias.CoordX, alias.CoordY) {
+	return sf.X_, sf.Y_
+}

+ 24 - 7
lev1/view_link/view_link.go

@@ -6,11 +6,15 @@ import (
 	"gitp78su.ipnodns.ru/svi/kern/v3"
 	"gitp78su.ipnodns.ru/svi/kern/v3"
 
 
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_link"
 )
 )
 
 
 // ViewLink -- отображение связи между объектами
 // ViewLink -- отображение связи между объектами
 type ViewLink struct {
 type ViewLink struct {
-	types.IElemLink
+	*arch_link.ArchLink
+	Coord_    types.IViewCoord
+	CoordEnd_ types.IViewCoord
+	Offset_   types.IViewOffset
 }
 }
 
 
 var (
 var (
@@ -18,19 +22,25 @@ var (
 )
 )
 
 
 // NewViewLink -- возвращает новое отображение связи
 // NewViewLink -- возвращает новое отображение связи
-func NewViewLink(useLink types.IElemLink) *ViewLink {
-	hassert(useLink != nil, "NewViewLink: useLink is nil")
+func NewViewLink(archLink *arch_link.ArchLink, coord, coordEnd types.IViewCoord,
+	offset types.IViewOffset) *ViewLink {
+	hassert(archLink != nil, "NewViewLink: archLink == nil")
+	hassert(coord != nil, "NewViewLink: coord == nil")
+	hassert(offset != nil, "NewViewLink: offset == nil")
 	sf := &ViewLink{
 	sf := &ViewLink{
-		IElemLink: useLink,
+		ArchLink:  archLink,
+		Coord_:    coord,
+		CoordEnd_: coordEnd,
+		Offset_:   offset,
 	}
 	}
 	return sf
 	return sf
 }
 }
 
 
 // Draw -- рисует связь между объектами
 // Draw -- рисует связь между объектами
 func (sf *ViewLink) Draw(canvas *svg.SVG) {
 func (sf *ViewLink) Draw(canvas *svg.SVG) {
-	x, y := sf.Coord().Int()
-	x1, y1 := sf.CoordEnd().Int()
-	offX, offY := sf.Offset().Int()
+	x, y := sf.Coord_.Int()
+	x1, y1 := sf.CoordEnd_.Int()
+	offX, offY := sf.Offset_.Int()
 	// Линия
 	// Линия
 	canvas.Line(x, y, x1, y1, "stroke:black;stroke-width:1")
 	canvas.Line(x, y, x1, y1, "stroke:black;stroke-width:1")
 	strLabel := sf.String()
 	strLabel := sf.String()
@@ -47,3 +57,10 @@ func (sf *ViewLink) Draw(canvas *svg.SVG) {
 	}
 	}
 	canvas.Gend() // Group end
 	canvas.Gend() // Group end
 }
 }
+
+// CoordEnd -- координаты конца связи
+//
+//go:fix inline
+func (sf *ViewLink) CoordEnd() types.IViewCoord {
+	return sf.CoordEnd_
+}

+ 4 - 0
lev1/view_node/view_node.go

@@ -0,0 +1,4 @@
+package view_node
+
+type ViewNode struct {
+}

+ 2 - 2
lev1/offset/offset.go → lev1/view_offset/view_offset.go

@@ -1,5 +1,5 @@
-// package offset -- смещение точки
-package offset
+// package view_offset -- смещение точки
+package view_offset
 
 
 import (
 import (
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"

+ 18 - 14
lev1/size/size.go → lev1/view_size/view_size.go

@@ -1,16 +1,19 @@
-// package size -- размер области
-package size
+// package view_size -- размер области
+package view_size
 
 
 import (
 import (
 	"fmt"
 	"fmt"
 
 
+	"gitp78su.ipnodns.ru/svi/kern/v3"
+
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-	"gitp78su.ipnodns.ru/svi/kern/v3"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_node"
 )
 )
 
 
-// Size -- размер области
-type Size struct {
+// ViewSize -- размер области
+type ViewSize struct {
+	*view_node.ViewNode
 	W_ alias.SizeX
 	W_ alias.SizeX
 	H_ alias.SizeY
 	H_ alias.SizeY
 }
 }
@@ -19,43 +22,44 @@ var (
 	hassert = kern.GetFnHassert()
 	hassert = kern.GetFnHassert()
 )
 )
 
 
-// NewSize -- возвращает новый размер
-func NewSize(w alias.SizeX, h alias.SizeY) types.IViewSize {
-	sf := &Size{
+// NewViewSize -- возвращает новый размер
+func NewViewSize(w alias.SizeX, h alias.SizeY) *ViewSize {
+	sf := &ViewSize{
 		W_: w,
 		W_: w,
 		H_: h,
 		H_: h,
 	}
 	}
 	sf.SelfCheck()
 	sf.SelfCheck()
+	_ = types.IViewSize(sf)
 	return sf
 	return sf
 }
 }
 
 
 // SelfCheck -- проверяет корректность размера
 // SelfCheck -- проверяет корректность размера
-func (sf *Size) SelfCheck() {
+func (sf *ViewSize) SelfCheck() {
 	hassert(sf.H_ >= 0, "Size.SelfCheck(): H_(%v)<0", sf.H_)
 	hassert(sf.H_ >= 0, "Size.SelfCheck(): H_(%v)<0", sf.H_)
 	hassert(sf.W_ >= 0, "Size.SelfCheck(): W_(%v)<0", sf.W_)
 	hassert(sf.W_ >= 0, "Size.SelfCheck(): W_(%v)<0", sf.W_)
 }
 }
 
 
 // String -- возвращает строковое представление размера
 // String -- возвращает строковое представление размера
-func (sf *Size) String() string {
+func (sf *ViewSize) String() string {
 	return fmt.Sprintf("size:%vx%v", sf.W_, sf.H_)
 	return fmt.Sprintf("size:%vx%v", sf.W_, sf.H_)
 }
 }
 
 
 // W -- возвращает ширину
 // W -- возвращает ширину
-func (sf *Size) W() alias.SizeX {
+func (sf *ViewSize) W() alias.SizeX {
 	return sf.W_
 	return sf.W_
 }
 }
 
 
 // H -- возвращает высоту
 // H -- возвращает высоту
-func (sf *Size) H() alias.SizeY {
+func (sf *ViewSize) H() alias.SizeY {
 	return sf.H_
 	return sf.H_
 }
 }
 
 
 // Get -- возвращает размер
 // Get -- возвращает размер
-func (sf *Size) Get() (alias.SizeX, alias.SizeY) {
+func (sf *ViewSize) Get() (alias.SizeX, alias.SizeY) {
 	return sf.W_, sf.H_
 	return sf.W_, sf.H_
 }
 }
 
 
 // Int -- возвращает размер
 // Int -- возвращает размер
-func (sf *Size) Int() (int, int) {
+func (sf *ViewSize) Int() (int, int) {
 	return int(sf.W_), int(sf.H_)
 	return int(sf.W_), int(sf.H_)
 }
 }

+ 31 - 0
lev1/view_text/view_text.go

@@ -0,0 +1,31 @@
+package view_text
+
+import (
+	svg "github.com/ajstarks/svgo"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_text"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_offset"
+)
+
+type ViewText struct {
+	*arch_text.ArchText
+	Offset_ *view_offset.Offset
+}
+
+// Draw -- отрисовка метки
+func (sf *ViewText) Draw(canvas *svg.SVG) {
+	strLabel := sf.String()
+	if strLabel != "" {
+		x, y := sf.Offset_.Int()
+		offX := int(sf.Offset_.X())
+		canvas.Text(x+offX, y-8, strLabel,
+			"font-size: 14px; font-family: Courier; fill: black")
+	}
+}
+
+// Offset -- возвращает смещение метки
+//
+//go:fix inline
+func (sf *ViewText) Offset() types.IViewOffset {
+	return sf.Offset_
+}

+ 12 - 8
lev1/view_use_case/view_use_case.go

@@ -5,19 +5,23 @@ import (
 	svg "github.com/ajstarks/svgo"
 	svg "github.com/ajstarks/svgo"
 
 
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_use_case"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_coord"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_text"
 )
 )
 
 
 // ViewUseCase -- вариант использования
 // ViewUseCase -- вариант использования
 type ViewUseCase struct {
 type ViewUseCase struct {
-	types.IElemUseCase
-	Size_ types.IViewSize
+	*arch_use_case.ArchUseCase
+	Size_  types.IViewSize
+	Coord_ view_coord.ViewCoord
+	text   *view_text.ViewText
 }
 }
 
 
-
 // NewViewUseCase -- возвращает новый вариант использования
 // NewViewUseCase -- возвращает новый вариант использования
-func NewViewUseCase(useCase types.IElemUseCase) *ViewUseCase {
+func NewViewUseCase(useCase *arch_use_case.ArchUseCase) *ViewUseCase {
 	sf := &ViewUseCase{
 	sf := &ViewUseCase{
-		IElemUseCase: useCase,
+		ArchUseCase: useCase,
 	}
 	}
 	sf.SelfCheck()
 	sf.SelfCheck()
 	return sf
 	return sf
@@ -25,19 +29,19 @@ func NewViewUseCase(useCase types.IElemUseCase) *ViewUseCase {
 
 
 // SelfCheck -- проверяет корректность элемента
 // SelfCheck -- проверяет корректность элемента
 func (sf *ViewUseCase) SelfCheck() {
 func (sf *ViewUseCase) SelfCheck() {
-	sf.IElemUseCase.SelfCheck()
+	sf.ArchUseCase.SelfCheck()
 	sf.Size_.SelfCheck()
 	sf.Size_.SelfCheck()
 }
 }
 
 
 // Draw -- рисует вариант использования
 // Draw -- рисует вариант использования
 func (sf *ViewUseCase) Draw(canvas *svg.SVG) {
 func (sf *ViewUseCase) Draw(canvas *svg.SVG) {
-	x, y := sf.Coord().Int()
+	x, y := sf.Coord_.Int()
 	// offX := int(sf.Label().Offset().X())
 	// offX := int(sf.Label().Offset().X())
 	w, h := sf.Size_.Int()
 	w, h := sf.Size_.Int()
 	// Овал
 	// Овал
 	canvas.Ellipse(x+70, y, w, h, "fill:none;stroke:black")
 	canvas.Ellipse(x+70, y, w, h, "fill:none;stroke:black")
 	// strLabel := sf.Label().String()
 	// strLabel := sf.Label().String()
-	sf.Label().Draw(canvas)
+	sf.text.Draw(canvas)
 	// if strLabel != "" {
 	// if strLabel != "" {
 	// 	canvas.Text(x+offX, y+6, strLabel, "font-size: 14px; font-family: Courier; fill: black")
 	// 	canvas.Text(x+offX, y+6, strLabel, "font-size: 14px; font-family: Courier; fill: black")
 	// }
 	// }

+ 106 - 0
lev2/engine_http/engine_http.go

@@ -0,0 +1,106 @@
+// package mod_http -- http-движок для архитектуры
+package engine_http
+
+import (
+	_ "embed"
+	"fmt"
+	"time"
+
+	"github.com/gofiber/fiber/v2"
+	"gitp78su.ipnodns.ru/svi/kern/v3"
+	"gitp78su.ipnodns.ru/svi/kern/v3/kc/log_buf"
+	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_doc"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_coord"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_size"
+	"gitp78su.ipnodns.ru/svi/goarch/lev2/engine_http/http_api"
+)
+
+//go:embed index.html
+var indexHtml []byte
+
+// CanvasSize -- размер хоста
+type CanvasSize struct {
+	SizeX_ int `form:"w"`
+	SizeY_ int `form:"h"`
+}
+
+func (sf *CanvasSize) String() string {
+	return fmt.Sprintf("w:%v; h:%v", sf.SizeX_, sf.SizeY_)
+}
+
+// EngineHttp -- http-движок для архитектуры
+type EngineHttp struct {
+	// fibApp     *fiber.App
+	kCtx     ktypes.IKernelCtx
+	log      ktypes.ILogBuf
+	diaMode  string            // Режим диаграммы
+	canvSize CanvasSize        // Размер холста
+	size     types.IViewSize   // Размер холста в его координатах
+	pos      types.IViewCoord  // Координаты холста
+	archDoc  *arch_doc.ArchDoc // Документ архитектуры
+	httpApi  *http_api.HttpApi
+}
+
+// NewEngineHttp -- возвращает новый движок HTTP
+func NewEngineHttp() *EngineHttp {
+	optTerm := log_buf.OptIsTerm(true)
+	optPref := log_buf.OptPrefix("EngineHttp")
+	log := log_buf.NewLogBuf(optTerm, optPref)
+	sf := &EngineHttp{
+		kCtx:    kern.GetKernelCtx(),
+		log:     log,
+		diaMode: cons.ModeUseCase,
+		size:    view_size.NewViewSize(800, 600),
+		pos:     view_coord.NewViewCoord(0, 0),
+		archDoc: arch_doc.GetArchDoc(),
+		httpApi: http_api.NewHttpApi(),
+	}
+	sHttp := kern.GetKernelServerHttp()
+	fibApp := sHttp.Fiber()
+	fibApp.Static("/static", "./static", fiber.Static{
+		Compress:      true,
+		Browse:        true,
+		CacheDuration: time.Second * 10,
+	})
+	fibApp.Get("/", sf.getIndex)
+	fibApp.Get("/api/use_case", sf.postSetModeUseCase)
+	fibApp.Post("/api/canvas/size/set", sf.postSetCanvasSize)
+	return sf
+}
+
+// Устанавливает размер холста
+func (sf *EngineHttp) postSetCanvasSize(ctx *fiber.Ctx) error {
+	err := ctx.BodyParser(&sf.canvSize)
+	if err != nil {
+		sf.log.Err("postSetCanvasSize(): on body parser, err=\n\t%v", err)
+	}
+	var (
+		w alias.SizeX
+		h alias.SizeY
+	)
+	if sf.canvSize.SizeX_ > 0 {
+		w = alias.SizeX(sf.canvSize.SizeX_ - 10)
+	}
+	if sf.canvSize.SizeY_ > 0 {
+		h = alias.SizeY(sf.canvSize.SizeY_ - 10)
+	}
+	sf.size = view_size.NewViewSize(w, h)
+	return ctx.SendString(sf.size.String())
+}
+
+// Возвращает картинку архитектуры
+func (sf *EngineHttp) postSetModeUseCase(ctx *fiber.Ctx) error {
+	sf.diaMode = cons.ModeUseCase
+	return ctx.SendString("[mode='" + sf.diaMode + "']")
+}
+
+// Возвращает главную страницу сервиса
+func (sf *EngineHttp) getIndex(ctx *fiber.Ctx) error {
+	ctx.Response().Header.Set("Content-Type", "text/html")
+	return ctx.Send(indexHtml)
+}

+ 18 - 0
lev2/engine_http/http_api/http_api.go

@@ -0,0 +1,18 @@
+// package http_api -- API для HTTP
+package http_api
+
+import (
+	"gitp78su.ipnodns.ru/svi/goarch/lev2/engine_http/http_api/http_arch_doc"
+)
+
+// HttpApi -- API для HTTP
+type HttpApi struct {
+	httpArchDoc *http_arch_doc.HttpArchDoc
+}
+
+// NewHttpApi -- создание нового экземпляра API для HTTP
+func NewHttpApi() *HttpApi {
+	return &HttpApi{
+		httpArchDoc: http_arch_doc.NewHttpArchDoc(),
+	}
+}

+ 116 - 0
lev2/engine_http/http_api/http_arch_doc/http_arch_doc.go

@@ -0,0 +1,116 @@
+// package http_arch_doc -- HTTP-API для ArchDoc
+package http_arch_doc
+
+import (
+	"bytes"
+	_ "embed"
+	"fmt"
+
+	svg "github.com/ajstarks/svgo"
+	"github.com/gofiber/fiber/v2"
+	"gitp78su.ipnodns.ru/svi/kern/v3"
+	"gopkg.in/yaml.v3"
+
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
+	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/canvas"
+)
+
+// HttpArchDoc -- HTTP-API для ArchDoc
+type HttpArchDoc struct {
+	oldBinArch []byte           // Кеш старой архитектуры
+	diaMode    string           // Режим диаграммы
+	size       types.IViewSize  // Размер холста в его координатах
+	pos        types.IViewCoord // Координаты холста
+	mapDrawer  types.IViewTree  // Словарь отрисовщиков
+}
+
+// NewHttpArchDoc -- создание нового экземпляра HTTP-API для ArchDoc
+func NewHttpArchDoc() *HttpArchDoc {
+	sf := &HttpArchDoc{
+		diaMode: cons.ModeUseCase,
+	}
+	sHttp := kern.GetKernelServerHttp()
+	fibApp := sHttp.Fiber()
+	fibApp.Post("/api/arch_doc/parse", sf.postArchDocParse)
+	return sf
+}
+
+// FormArch -- извлекает данные из текстового поля для обновления
+type FormArch struct {
+	StrData string `form:"text"`
+}
+
+// По запросу парсит, что получилось -- обновляет архитектуру
+func (sf *HttpArchDoc) postArchDocParse(ctx *fiber.Ctx) error {
+	form := &FormArch{}
+	if err := ctx.BodyParser(form); err != nil {
+		return ctx.SendString(fmt.Sprintf("HttpArchDoc.postArchDocParse(): in BodyParser, err=<br>%v", err))
+	}
+	binData := []byte(form.StrData)
+	if len(binData) == len(sf.oldBinArch) {
+		return ctx.Send(sf.oldBinArch)
+	}
+	mapElem := []map[string]interface{}{}
+	err := yaml.Unmarshal(binData, &mapElem)
+	if err != nil {
+		return ctx.SendString(fmt.Sprintf("HttpArchDoc.postArchDocParse(): in Decode JSON, err=<br>%v", err))
+	}
+	wr := bytes.NewBuffer(nil)
+	canvas, err := sf.getCanvas(wr, mapElem)
+	if err != nil {
+		return ctx.SendString(fmt.Sprintf("HttpArchDoc.postArchDocParse(): in create canvas, err=<br>%v", err))
+	}
+	switch sf.diaMode {
+	case cons.ModeUseCase: // режим вариантов использования
+		if err := sf.useCase(canvas); err != nil {
+			return ctx.SendString(fmt.Sprintf("HttpArchDoc.postArchDocParse(): in useCase, err=<br>%v", err))
+		}
+	default: // неизвестный режим
+		return ctx.SendString(fmt.Sprintf("HttpArchDoc.postArchDocParse(): unknown mode=%q", sf.diaMode))
+	}
+
+	canvas.End()
+	binData = wr.Bytes()
+	return ctx.Send(binData)
+}
+
+// Возвращает новый холст
+func (sf *HttpArchDoc) getCanvas(wr *bytes.Buffer, lstElem []map[string]interface{}) (*svg.SVG, error) {
+	var (
+		elem         map[string]interface{}
+		isFind, isOk bool
+		_section     interface{}
+	)
+	for _, elem = range lstElem {
+		_section, isOk = elem["type"]
+		if !isOk {
+			continue
+		}
+		section, isOk := _section.(string)
+		if !isOk {
+			return nil, fmt.Errorf("ServHttp.canvas(): in mapElem, type(%#+v) not string<br>%#+v", _section, elem)
+		}
+		if section == cons.SectionConfig {
+			isFind = true
+			break
+		}
+	}
+	if !isFind {
+		return nil, fmt.Errorf("ServHttp.canvas(): in mapElem, config not found")
+	}
+	confCanvas := canvas.NewCanvas(sf.diaMode, sf.size, sf.pos)
+	sizeX, sizeY := confCanvas.Size().Int()
+	canvas := svg.New(wr)
+	canvas.Start(sizeX, sizeY)
+	confCanvas.Draw(canvas)
+	return canvas, nil
+}
+
+// Формирует варианты использования
+func (sf *HttpArchDoc) useCase(canvas *svg.SVG) error {
+	for _, drawer := range sf.mapDrawer.TreeView() {
+		drawer.Draw(canvas)
+	}
+	return nil
+}

+ 0 - 186
lev2/engine_http/serv_http.go

@@ -1,186 +0,0 @@
-// package mod_http -- http-движок для архитектуры
-package engine_http
-
-import (
-	"bytes"
-	_ "embed"
-	"fmt"
-	"time"
-
-	svg "github.com/ajstarks/svgo"
-	"github.com/gofiber/fiber/v2"
-	"gitp78su.ipnodns.ru/svi/kern/v3"
-	"gitp78su.ipnodns.ru/svi/kern/v3/kc/log_buf"
-	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
-	"gopkg.in/yaml.v3"
-
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
-	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/coord"
-	"gitp78su.ipnodns.ru/svi/goarch/lev1/size"
-	"gitp78su.ipnodns.ru/svi/goarch/pkg/elems/canvas"
-)
-
-//go:embed index.html
-var indexHtml []byte
-
-// CanvasSize -- размер хоста
-type CanvasSize struct {
-	SizeX_ int `form:"w"`
-	SizeY_ int `form:"h"`
-}
-
-func (sf *CanvasSize) String() string {
-	return fmt.Sprintf("w:%v; h:%v", sf.SizeX_, sf.SizeY_)
-}
-
-// EngineHttp -- http-движок для архитектуры
-type EngineHttp struct {
-	// fibApp     *fiber.App
-	kCtx       ktypes.IKernelCtx
-	log        ktypes.ILogBuf
-	diaMode    string           // Режим диаграммы
-	oldBinArch []byte           // Кеш старой архитектуры
-	canvSize   CanvasSize       // Размер холста
-	size       types.IViewSize  // Размер холста в его координатах
-	pos        types.IViewCoord // Координаты холста
-	mapDrawer  types.IMapDrawer // Словарь отрисовщиков
-}
-
-// NewEngineHttp -- возвращает новый движок HTTP
-func NewEngineHttp() *EngineHttp {
-	optTerm := log_buf.OptIsTerm(true)
-	optPref := log_buf.OptPrefix("EngineHttp")
-	log := log_buf.NewLogBuf(optTerm, optPref)
-	sf := &EngineHttp{
-		kCtx:    kern.GetKernelCtx(),
-		log:     log,
-		diaMode: cons.ModeUseCase,
-		size:    size.NewSize(800, 600),
-		pos:     coord.NewCoord(0, 0),
-	}
-	sHttp := kern.GetKernelServerHttp()
-	fibApp := sHttp.Fiber()
-	fibApp.Static("/static", "./static", fiber.Static{
-		Compress:      true,
-		Browse:        true,
-		CacheDuration: time.Second * 10,
-	})
-	fibApp.Get("/", sf.getIndex)
-	fibApp.Get("/api/use_case", sf.postSetModeUseCase)
-	fibApp.Post("/api/arch", sf.postArch)
-	fibApp.Post("/api/canvas_size", sf.postSetCanvasSize)
-	return sf
-}
-
-// FormArch -- извлекает данные из текстового поля для обновления
-type FormArch struct {
-	StrData string `form:"text"`
-}
-
-// Устанавливает размер холста
-func (sf *EngineHttp) postSetCanvasSize(ctx *fiber.Ctx) error {
-	err := ctx.BodyParser(&sf.canvSize)
-	if err != nil {
-		sf.log.Err("postSetCanvasSize(): on body parser, err=\n\t%v", err)
-	}
-	var (
-		w alias.SizeX
-		h alias.SizeY
-	)
-	if sf.canvSize.SizeX_ > 0 {
-		w = alias.SizeX(sf.canvSize.SizeX_ - 10)
-	}
-	if sf.canvSize.SizeY_ > 0 {
-		h = alias.SizeY(sf.canvSize.SizeY_ - 10)
-	}
-	sf.size = size.NewSize(w, h)
-	return ctx.SendString(sf.size.String())
-}
-
-// Возвращает новый холст
-func (sf *EngineHttp) canvas(wr *bytes.Buffer, lstElem []map[string]interface{}) (*svg.SVG, error) {
-	var (
-		elem         map[string]interface{}
-		isFind, isOk bool
-		_section     interface{}
-	)
-	for _, elem = range lstElem {
-		_section, isOk = elem["type"]
-		if !isOk {
-			continue
-		}
-		section, isOk := _section.(string)
-		if !isOk {
-			return nil, fmt.Errorf("ServHttp.canvas(): in mapElem, type(%#+v) not string<br>%#+v", _section, elem)
-		}
-		if section == cons.SectionConfig {
-			isFind = true
-			break
-		}
-	}
-	if !isFind {
-		return nil, fmt.Errorf("ServHttp.canvas(): in mapElem, config not found")
-	}
-	confCanvas := canvas.NewCanvas(sf.diaMode, sf.size, sf.pos)
-	sizeX, sizeY := confCanvas.Size().Int()
-	canvas := svg.New(wr)
-	canvas.Start(sizeX, sizeY)
-	confCanvas.Draw(canvas)
-	return canvas, nil
-}
-
-// По запросу парсит, что получилось -- обновляет архитектуру
-func (sf *EngineHttp) postArch(ctx *fiber.Ctx) error {
-	form := &FormArch{}
-	if err := ctx.BodyParser(form); err != nil {
-		return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in BodyParser, err=<br>%v", err))
-	}
-	binData := []byte(form.StrData)
-	if len(binData) == len(sf.oldBinArch) {
-		return ctx.Send(sf.oldBinArch)
-	}
-	mapElem := []map[string]interface{}{}
-	err := yaml.Unmarshal(binData, &mapElem)
-	if err != nil {
-		return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in Decode JSON, err=<br>%v", err))
-	}
-	wr := bytes.NewBuffer(nil)
-	canvas, err := sf.canvas(wr, mapElem)
-	if err != nil {
-		return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in create canvas, err=<br>%v", err))
-	}
-	switch sf.diaMode {
-	case cons.ModeUseCase: // режим вариантов использования
-		if err := sf.useCase(canvas); err != nil {
-			return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in useCase, err=<br>%v", err))
-		}
-	default: // неизвестный режим
-		return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): unknown mode=%q", sf.diaMode))
-	}
-
-	canvas.End()
-	binData = wr.Bytes()
-	return ctx.Send(binData)
-}
-
-// Формирует варианты использования
-func (sf *EngineHttp) useCase(canvas *svg.SVG) error {
-	for _, elem := range sf.mapDrawer.LstDrawers() {
-		elem.Draw(canvas)
-	}
-	return nil
-}
-
-// Возвращает картинку архитектуры
-func (sf *EngineHttp) postSetModeUseCase(ctx *fiber.Ctx) error {
-	sf.diaMode = cons.ModeUseCase
-	return ctx.SendString("[mode='" + sf.diaMode + "']")
-}
-
-// Возвращает главную страницу сервиса
-func (sf *EngineHttp) getIndex(ctx *fiber.Ctx) error {
-	ctx.Response().Header.Set("Content-Type", "text/html")
-	return ctx.Send(indexHtml)
-}

+ 1 - 1
lev3/fabrics/fabric_service.go

@@ -10,7 +10,7 @@ import (
 )
 )
 
 
 // NewService -- возвращает новый сервис
 // NewService -- возвращает новый сервис
-func NewService() types.IService {
+func NewService() types.IEngineService {
 	sf := service.NewService()
 	sf := service.NewService()
 	return sf
 	return sf
 }
 }

+ 12 - 8
pkg/views/view_actor/view_actor.go

@@ -8,11 +8,15 @@ import (
 	"gitp78su.ipnodns.ru/svi/kern/v3"
 	"gitp78su.ipnodns.ru/svi/kern/v3"
 
 
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_coord"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_text"
 )
 )
 
 
 // ViewActor -- SVG-фигура актора
 // ViewActor -- SVG-фигура актора
 type ViewActor struct {
 type ViewActor struct {
-	types.IElemActor
+	types.IArchActor
+	Coord_ *view_coord.ViewCoord
+	text   *view_text.ViewText
 }
 }
 
 
 var (
 var (
@@ -20,18 +24,18 @@ var (
 )
 )
 
 
 // NewViewActor -- возвращает новый SVG-актор
 // NewViewActor -- возвращает новый SVG-актор
-func NewViewActor(actor types.IElemActor) *ViewActor {
+func NewViewActor(actor types.IArchActor) *ViewActor {
 	hassert(actor != nil, "in NewViewActor(), actor is nil")
 	hassert(actor != nil, "in NewViewActor(), actor is nil")
 	sf := &ViewActor{
 	sf := &ViewActor{
-		IElemActor: actor,
+		IArchActor: actor,
 	}
 	}
 	return sf
 	return sf
 }
 }
 
 
 // Draw -- рисует фигуру актора
 // Draw -- рисует фигуру актора
 func (sf *ViewActor) Draw(canvas *svg.SVG) {
 func (sf *ViewActor) Draw(canvas *svg.SVG) {
-	x, y := sf.Coord().Int()
-	offX, offY := sf.Offset().Int()
+	x, y := sf.Coord_.Int()
+	offX, offY := sf.text.Offset().Int()
 	// Голова
 	// Голова
 	canvas.Circle(x, y, 10, "fill:none;stroke:red")
 	canvas.Circle(x, y, 10, "fill:none;stroke:red")
 	// Туловище
 	// Туловище
@@ -44,10 +48,10 @@ func (sf *ViewActor) Draw(canvas *svg.SVG) {
 	canvas.Line(x, y+40, x+10, y+55, "stroke:red;stroke-width:1")
 	canvas.Line(x, y+40, x+10, y+55, "stroke:red;stroke-width:1")
 	// Надпись
 	// Надпись
 	log.Printf("ViewActor.Draw(): x=%d, y=%d, offX=%d, offY=%d", x, y, offX, offY)
 	log.Printf("ViewActor.Draw(): x=%d, y=%d, offX=%d, offY=%d", x, y, offX, offY)
-	canvas.Text(x+offX, y+offY, sf.String(), "font-size: 14px; font-family: sans-serif; fill: black")
-	if msgErr := sf.Check(); msgErr != "" { // Проверки на ошибки
+	canvas.Text(x+offX, y+offY, sf.text.String(), "font-size: 14px; font-family: sans-serif; fill: black")
+	if optErr := sf.InvarCheck(); optErr.IsVal() { // Проверки на ошибки
 		canvas.Group("Ошибка")
 		canvas.Group("Ошибка")
-		canvas.Title(msgErr)
+		canvas.Title(optErr.Val().Error())
 		canvas.Image(x+offX-20, y+offY-20, 16, 16, "/static/img/warning.png")
 		canvas.Image(x+offX-20, y+offY-20, 16, 16, "/static/img/warning.png")
 	}
 	}
 	canvas.Gend()
 	canvas.Gend()

+ 21 - 10
pkg/views/view_use_group/view_use_group.go

@@ -6,12 +6,17 @@ import (
 	"gitp78su.ipnodns.ru/svi/kern/v3"
 	"gitp78su.ipnodns.ru/svi/kern/v3"
 
 
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
 	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_use_group"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_coord"
+	"gitp78su.ipnodns.ru/svi/goarch/lev1/view_size"
 )
 )
 
 
 // ViewUseGroup -- отображение группы вариантов использования
 // ViewUseGroup -- отображение группы вариантов использования
 type ViewUseGroup struct {
 type ViewUseGroup struct {
-	types.IElemUseGroup
-	Label_ types.IViewLabel
+	*arch_use_group.ArchUseCaseGroup
+	text  types.IViewText
+	coord *view_coord.ViewCoord
+	size  *view_size.ViewSize
 }
 }
 
 
 var (
 var (
@@ -19,29 +24,35 @@ var (
 )
 )
 
 
 // NewViewUseGroup -- возвращает новое отображение группы вариант использования
 // NewViewUseGroup -- возвращает новое отображение группы вариант использования
-func NewViewUseGroup(useGroup types.IElemUseGroup, label types.IViewLabel) types.IDrawer {
+func NewViewUseGroup(useGroup *arch_use_group.ArchUseCaseGroup, label types.IViewText) *ViewUseGroup {
 	hassert(useGroup != nil, "NewViewUseGroup(): useGroup == nil")
 	hassert(useGroup != nil, "NewViewUseGroup(): useGroup == nil")
 	sf := &ViewUseGroup{
 	sf := &ViewUseGroup{
-		IElemUseGroup: useGroup,
-		Label_:        label,
+		ArchUseCaseGroup: useGroup,
+		text:             label,
 	}
 	}
 	sf.SelfCheck()
 	sf.SelfCheck()
+	_ = types.IViewNode(sf)
 	return sf
 	return sf
 }
 }
 
 
+// Coord -- координаты группы вариантов использования
+func (sf *ViewUseGroup) Coord() types.IViewCoord {
+	return sf.coord
+}
+
 // SelfCheck -- проверяет корректность элемента
 // SelfCheck -- проверяет корректность элемента
 func (sf *ViewUseGroup) SelfCheck() {
 func (sf *ViewUseGroup) SelfCheck() {
-	hassert(sf.IElemUseGroup != nil, "ViewUseGroup.SelfCheck(): IElemUseGroup == nil")
-	hassert(sf.Label_ != nil, "ViewUseGroup.SelfCheck(): Label_ == nil")
+	hassert(sf.ArchUseCaseGroup != nil, "ViewUseGroup.SelfCheck(): IElemUseGroup == nil")
+	hassert(sf.text != nil, "ViewUseGroup.SelfCheck(): Label_ == nil")
 }
 }
 
 
 // Draw -- рисует группу вариантов использования
 // Draw -- рисует группу вариантов использования
 func (sf *ViewUseGroup) Draw(canvas *svg.SVG) {
 func (sf *ViewUseGroup) Draw(canvas *svg.SVG) {
-	x, y := sf.Coord().Int()
-	w, h := sf.Size().Int()
+	x, y := sf.coord.Int()
+	w, h := sf.size.Int()
 	// Главный квадрат
 	// Главный квадрат
 	canvas.Rect(x, y, w, h, "fill:none;stroke:black")
 	canvas.Rect(x, y, w, h, "fill:none;stroke:black")
 	// Заголовок
 	// Заголовок
 	canvas.Rect(x, y-26, h/2, 26, "fill:none;stroke:black")
 	canvas.Rect(x, y-26, h/2, 26, "fill:none;stroke:black")
-	sf.Label_.Draw(canvas)
+	sf.text.Draw(canvas)
 }
 }

+ 112 - 16
vendor/golang.org/x/sys/unix/affinity_linux.go

@@ -13,11 +13,19 @@ import (
 
 
 const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
 const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
 
 
-// CPUSet represents a CPU affinity mask.
+// CPUSet represents a bit mask of CPUs, to be used with [SchedGetaffinity], [SchedSetaffinity],
+// and [SetMemPolicy].
+//
+// Note this type can only represent CPU IDs 0 through 1023.
+// Use [CPUSetDynamic]/[NewCPUSet] instead to avoid this limit.
 type CPUSet [cpuSetSize]cpuMask
 type CPUSet [cpuSetSize]cpuMask
 
 
-func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
-	_, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set)))
+// CPUSetDynamic represents a bit mask of CPUs, to be used with [SchedGetaffinityDynamic],
+// [SchedSetaffinityDynamic], and [SetMemPolicyDynamic]. Use [NewCPUSet] to allocate.
+type CPUSetDynamic []cpuMask
+
+func schedAffinity(trap uintptr, pid int, size uintptr, ptr unsafe.Pointer) error {
+	_, _, e := RawSyscall(trap, uintptr(pid), uintptr(size), uintptr(ptr))
 	if e != 0 {
 	if e != 0 {
 		return errnoErr(e)
 		return errnoErr(e)
 	}
 	}
@@ -27,13 +35,13 @@ func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
 // SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
 // SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
 // If pid is 0 the calling thread is used.
 // If pid is 0 the calling thread is used.
 func SchedGetaffinity(pid int, set *CPUSet) error {
 func SchedGetaffinity(pid int, set *CPUSet) error {
-	return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
+	return schedAffinity(SYS_SCHED_GETAFFINITY, pid, unsafe.Sizeof(*set), unsafe.Pointer(set))
 }
 }
 
 
 // SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
 // SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
 // If pid is 0 the calling thread is used.
 // If pid is 0 the calling thread is used.
 func SchedSetaffinity(pid int, set *CPUSet) error {
 func SchedSetaffinity(pid int, set *CPUSet) error {
-	return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
+	return schedAffinity(SYS_SCHED_SETAFFINITY, pid, unsafe.Sizeof(*set), unsafe.Pointer(set))
 }
 }
 
 
 // Zero clears the set s, so that it contains no CPUs.
 // Zero clears the set s, so that it contains no CPUs.
@@ -45,9 +53,7 @@ func (s *CPUSet) Zero() {
 // will silently ignore any invalid CPU bits in [CPUSet] so this is an
 // will silently ignore any invalid CPU bits in [CPUSet] so this is an
 // efficient way of resetting the CPU affinity of a process.
 // efficient way of resetting the CPU affinity of a process.
 func (s *CPUSet) Fill() {
 func (s *CPUSet) Fill() {
-	for i := range s {
-		s[i] = ^cpuMask(0)
-	}
+	cpuMaskFill(s[:])
 }
 }
 
 
 func cpuBitsIndex(cpu int) int {
 func cpuBitsIndex(cpu int) int {
@@ -58,24 +64,27 @@ func cpuBitsMask(cpu int) cpuMask {
 	return cpuMask(1 << (uint(cpu) % _NCPUBITS))
 	return cpuMask(1 << (uint(cpu) % _NCPUBITS))
 }
 }
 
 
-// Set adds cpu to the set s.
-func (s *CPUSet) Set(cpu int) {
+func cpuMaskFill(s []cpuMask) {
+	for i := range s {
+		s[i] = ^cpuMask(0)
+	}
+}
+
+func cpuMaskSet(s []cpuMask, cpu int) {
 	i := cpuBitsIndex(cpu)
 	i := cpuBitsIndex(cpu)
 	if i < len(s) {
 	if i < len(s) {
 		s[i] |= cpuBitsMask(cpu)
 		s[i] |= cpuBitsMask(cpu)
 	}
 	}
 }
 }
 
 
-// Clear removes cpu from the set s.
-func (s *CPUSet) Clear(cpu int) {
+func cpuMaskClear(s []cpuMask, cpu int) {
 	i := cpuBitsIndex(cpu)
 	i := cpuBitsIndex(cpu)
 	if i < len(s) {
 	if i < len(s) {
 		s[i] &^= cpuBitsMask(cpu)
 		s[i] &^= cpuBitsMask(cpu)
 	}
 	}
 }
 }
 
 
-// IsSet reports whether cpu is in the set s.
-func (s *CPUSet) IsSet(cpu int) bool {
+func cpuMaskIsSet(s []cpuMask, cpu int) bool {
 	i := cpuBitsIndex(cpu)
 	i := cpuBitsIndex(cpu)
 	if i < len(s) {
 	if i < len(s) {
 		return s[i]&cpuBitsMask(cpu) != 0
 		return s[i]&cpuBitsMask(cpu) != 0
@@ -83,11 +92,98 @@ func (s *CPUSet) IsSet(cpu int) bool {
 	return false
 	return false
 }
 }
 
 
-// Count returns the number of CPUs in the set s.
-func (s *CPUSet) Count() int {
+func cpuMaskCount(s []cpuMask) int {
 	c := 0
 	c := 0
 	for _, b := range s {
 	for _, b := range s {
 		c += bits.OnesCount64(uint64(b))
 		c += bits.OnesCount64(uint64(b))
 	}
 	}
 	return c
 	return c
 }
 }
+
+// Set adds cpu to the set s. If cpu is out of bounds for s, no action is taken.
+func (s *CPUSet) Set(cpu int) {
+	cpuMaskSet(s[:], cpu)
+}
+
+// Clear removes cpu from the set s. If cpu is out of bounds for s, no action is taken.
+func (s *CPUSet) Clear(cpu int) {
+	cpuMaskClear(s[:], cpu)
+}
+
+// IsSet reports whether cpu is in the set s.
+func (s *CPUSet) IsSet(cpu int) bool {
+	return cpuMaskIsSet(s[:], cpu)
+}
+
+// Count returns the number of CPUs in the set s.
+func (s *CPUSet) Count() int {
+	return cpuMaskCount(s[:])
+}
+
+// NewCPUSet creates a CPU affinity mask capable of representing CPU IDs
+// up to maxCPU (exclusive).
+func NewCPUSet(maxCPU int) CPUSetDynamic {
+	numMasks := (maxCPU + _NCPUBITS - 1) / _NCPUBITS
+	if numMasks == 0 {
+		numMasks = 1
+	}
+	return make(CPUSetDynamic, numMasks)
+}
+
+// Zero clears the set s, so that it contains no CPUs.
+func (s CPUSetDynamic) Zero() {
+	clear(s)
+}
+
+// Fill adds all possible CPU bits to the set s. On Linux, [SchedSetaffinityDynamic]
+// will silently ignore any invalid CPU bits in [CPUSetDynamic] so this is an
+// efficient way of resetting the CPU affinity of a process.
+func (s CPUSetDynamic) Fill() {
+	cpuMaskFill(s)
+}
+
+// Set adds cpu to the set s. If cpu is out of bounds for s, no action is taken.
+func (s CPUSetDynamic) Set(cpu int) {
+	cpuMaskSet(s, cpu)
+}
+
+// Clear removes cpu from the set s. If cpu is out of bounds for s, no action is taken.
+func (s CPUSetDynamic) Clear(cpu int) {
+	cpuMaskClear(s, cpu)
+}
+
+// IsSet reports whether cpu is in the set s.
+func (s CPUSetDynamic) IsSet(cpu int) bool {
+	return cpuMaskIsSet(s, cpu)
+}
+
+// Count returns the number of CPUs in the set s.
+func (s CPUSetDynamic) Count() int {
+	return cpuMaskCount(s)
+}
+
+func (s CPUSetDynamic) size() uintptr {
+	return uintptr(len(s)) * unsafe.Sizeof(cpuMask(0))
+}
+
+func (s CPUSetDynamic) pointer() unsafe.Pointer {
+	if len(s) == 0 {
+		return nil
+	}
+	return unsafe.Pointer(&s[0])
+}
+
+// SchedGetaffinityDynamic gets the CPU affinity mask of the thread specified by pid.
+// If pid is 0 the calling thread is used.
+//
+// If the set is smaller than the size of the affinity mask used by the kernel,
+// [EINVAL] is returned.
+func SchedGetaffinityDynamic(pid int, set CPUSetDynamic) error {
+	return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set.size(), set.pointer())
+}
+
+// SchedSetaffinityDynamic sets the CPU affinity mask of the thread specified by pid.
+// If pid is 0 the calling thread is used.
+func SchedSetaffinityDynamic(pid int, set CPUSetDynamic) error {
+	return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set.size(), set.pointer())
+}

+ 1 - 1
vendor/golang.org/x/sys/unix/mkall.sh

@@ -51,7 +51,7 @@ if [[ "$GOOS" = "linux" ]]; then
 	# Files generated through docker (use $cmd so you can Ctl-C the build or run)
 	# Files generated through docker (use $cmd so you can Ctl-C the build or run)
 	set -e
 	set -e
 	$cmd docker build --tag generate:$GOOS $GOOS
 	$cmd docker build --tag generate:$GOOS $GOOS
-	$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS
+	$cmd docker run --rm --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS
 	exit
 	exit
 fi
 fi
 
 

+ 6 - 2
vendor/golang.org/x/sys/unix/syscall_linux.go

@@ -2644,8 +2644,12 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) {
 //sys	Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
 //sys	Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
 //sys	Mseal(b []byte, flags uint) (err error)
 //sys	Mseal(b []byte, flags uint) (err error)
 
 
-//sys	setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY
+//sys	setMemPolicy(mode int, mask unsafe.Pointer, size uintptr) (err error) = SYS_SET_MEMPOLICY
 
 
 func SetMemPolicy(mode int, mask *CPUSet) error {
 func SetMemPolicy(mode int, mask *CPUSet) error {
-	return setMemPolicy(mode, mask, _CPU_SETSIZE)
+	return setMemPolicy(mode, unsafe.Pointer(mask), _CPU_SETSIZE)
+}
+
+func SetMemPolicyDynamic(mode int, mask CPUSetDynamic) error {
+	return setMemPolicy(mode, mask.pointer(), mask.size())
 }
 }

+ 3 - 0
vendor/golang.org/x/sys/unix/syscall_linux_arm.go

@@ -82,6 +82,9 @@ func Time(t *Time_t) (Time_t, error) {
 }
 }
 
 
 func Utime(path string, buf *Utimbuf) error {
 func Utime(path string, buf *Utimbuf) error {
+	if buf == nil {
+		return Utimes(path, nil)
+	}
 	tv := []Timeval{
 	tv := []Timeval{
 		{Sec: buf.Actime},
 		{Sec: buf.Actime},
 		{Sec: buf.Modtime},
 		{Sec: buf.Modtime},

+ 3 - 0
vendor/golang.org/x/sys/unix/syscall_linux_arm64.go

@@ -113,6 +113,9 @@ func Time(t *Time_t) (Time_t, error) {
 }
 }
 
 
 func Utime(path string, buf *Utimbuf) error {
 func Utime(path string, buf *Utimbuf) error {
+	if buf == nil {
+		return Utimes(path, nil)
+	}
 	tv := []Timeval{
 	tv := []Timeval{
 		{Sec: buf.Actime},
 		{Sec: buf.Actime},
 		{Sec: buf.Modtime},
 		{Sec: buf.Modtime},

+ 3 - 0
vendor/golang.org/x/sys/unix/syscall_linux_loong64.go

@@ -150,6 +150,9 @@ func Time(t *Time_t) (Time_t, error) {
 }
 }
 
 
 func Utime(path string, buf *Utimbuf) error {
 func Utime(path string, buf *Utimbuf) error {
+	if buf == nil {
+		return Utimes(path, nil)
+	}
 	tv := []Timeval{
 	tv := []Timeval{
 		{Sec: buf.Actime},
 		{Sec: buf.Actime},
 		{Sec: buf.Modtime},
 		{Sec: buf.Modtime},

+ 3 - 0
vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go

@@ -112,6 +112,9 @@ func Time(t *Time_t) (Time_t, error) {
 }
 }
 
 
 func Utime(path string, buf *Utimbuf) error {
 func Utime(path string, buf *Utimbuf) error {
+	if buf == nil {
+		return Utimes(path, nil)
+	}
 	tv := []Timeval{
 	tv := []Timeval{
 		{Sec: buf.Actime},
 		{Sec: buf.Actime},
 		{Sec: buf.Modtime},
 		{Sec: buf.Modtime},

+ 2 - 2
vendor/golang.org/x/sys/unix/zsyscall_linux.go

@@ -2241,8 +2241,8 @@ func Mseal(b []byte, flags uint) (err error) {
 
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 
-func setMemPolicy(mode int, mask *CPUSet, size int) (err error) {
-	_, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size))
+func setMemPolicy(mode int, mask unsafe.Pointer, size uintptr) (err error) {
+	_, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(mask), uintptr(size))
 	if e1 != 0 {
 	if e1 != 0 {
 		err = errnoErr(e1)
 		err = errnoErr(e1)
 	}
 	}

+ 10 - 3
vendor/golang.org/x/sys/windows/syscall_windows.go

@@ -892,9 +892,13 @@ const socket_error = uintptr(^uint32(0))
 //sys	MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
 //sys	MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
 //sys	getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
 //sys	getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
 //sys   GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
 //sys   GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
+//sys   GetIfTable2Ex(level uint32, table **MibIfTable2) (errcode error) = iphlpapi.GetIfTable2Ex
 //sys   GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2
 //sys   GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2
 //sys   GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2
 //sys   GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2
+//sys   GetIpInterfaceEntry(row *MibIpInterfaceRow) (errcode error) = iphlpapi.GetIpInterfaceEntry
+//sys   GetIpInterfaceTable(family uint16, table **MibIpInterfaceTable) (errcode error) = iphlpapi.GetIpInterfaceTable
 //sys   GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
 //sys   GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
+//sys   GetUnicastIpAddressTable(family uint16, table **MibUnicastIpAddressTable) (errcode error) = iphlpapi.GetUnicastIpAddressTable
 //sys   FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable
 //sys   FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable
 //sys   NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
 //sys   NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
 //sys   NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2
 //sys   NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2
@@ -1693,10 +1697,13 @@ func NewNTUnicodeString(s string) (*NTUnicodeString, error) {
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	n := uint16(len(s16) * 2)
+	n := len(s16) * 2
+	if n > (1<<16)-1 {
+		return nil, syscall.EINVAL
+	}
 	return &NTUnicodeString{
 	return &NTUnicodeString{
-		Length:        n - 2, // subtract 2 bytes for the NULL terminator
-		MaximumLength: n,
+		Length:        uint16(n) - 2, // subtract 2 bytes for the NULL terminator
+		MaximumLength: uint16(n),
 		Buffer:        &s16[0],
 		Buffer:        &s16[0],
 	}, nil
 	}, nil
 }
 }

+ 29 - 0
vendor/golang.org/x/sys/windows/types_windows.go

@@ -2320,6 +2320,21 @@ type MibIfRow2 struct {
 	OutQLen                     uint64
 	OutQLen                     uint64
 }
 }
 
 
+// MIB_IF_TABLE_LEVEL enumeration from netioapi.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ne-netioapi-mib_if_table_level.
+const (
+	MibIfTableNormal                  = 0
+	MibIfTableRaw                     = 1
+	MibIfTableNormalWithoutStatistics = 2
+)
+
+// MibIfTable2 contains a table of logical and physical interface entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_if_table2.
+type MibIfTable2 struct {
+	NumEntries uint32
+	Table      [1]MibIfRow2
+}
+
 // IP_ADDRESS_PREFIX stores an IP address prefix. See
 // IP_ADDRESS_PREFIX stores an IP address prefix. See
 // https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix.
 // https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix.
 type IpAddressPrefix struct {
 type IpAddressPrefix struct {
@@ -2413,6 +2428,13 @@ type MibUnicastIpAddressRow struct {
 	CreationTimeStamp  Filetime
 	CreationTimeStamp  Filetime
 }
 }
 
 
+// MibUnicastIpAddressTable contains a table of unicast IP address entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_table.
+type MibUnicastIpAddressTable struct {
+	NumEntries uint32
+	Table      [1]MibUnicastIpAddressRow
+}
+
 const ScopeLevelCount = 16
 const ScopeLevelCount = 16
 
 
 // MIB_IPINTERFACE_ROW stores interface management information for a particular IP address family on a network interface.
 // MIB_IPINTERFACE_ROW stores interface management information for a particular IP address family on a network interface.
@@ -2455,6 +2477,13 @@ type MibIpInterfaceRow struct {
 	DisableDefaultRoutes                 uint8
 	DisableDefaultRoutes                 uint8
 }
 }
 
 
+// MibIpInterfaceTable contains a table of IP interface entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipinterface_table.
+type MibIpInterfaceTable struct {
+	NumEntries uint32
+	Table      [1]MibIpInterfaceRow
+}
+
 // Console related constants used for the mode parameter to SetConsoleMode. See
 // Console related constants used for the mode parameter to SetConsoleMode. See
 // https://docs.microsoft.com/en-us/windows/console/setconsolemode for details.
 // https://docs.microsoft.com/en-us/windows/console/setconsolemode for details.
 
 

+ 36 - 0
vendor/golang.org/x/sys/windows/zsyscall_windows.go

@@ -188,9 +188,13 @@ var (
 	procGetBestInterfaceEx                                   = modiphlpapi.NewProc("GetBestInterfaceEx")
 	procGetBestInterfaceEx                                   = modiphlpapi.NewProc("GetBestInterfaceEx")
 	procGetIfEntry                                           = modiphlpapi.NewProc("GetIfEntry")
 	procGetIfEntry                                           = modiphlpapi.NewProc("GetIfEntry")
 	procGetIfEntry2Ex                                        = modiphlpapi.NewProc("GetIfEntry2Ex")
 	procGetIfEntry2Ex                                        = modiphlpapi.NewProc("GetIfEntry2Ex")
+	procGetIfTable2Ex                                        = modiphlpapi.NewProc("GetIfTable2Ex")
 	procGetIpForwardEntry2                                   = modiphlpapi.NewProc("GetIpForwardEntry2")
 	procGetIpForwardEntry2                                   = modiphlpapi.NewProc("GetIpForwardEntry2")
 	procGetIpForwardTable2                                   = modiphlpapi.NewProc("GetIpForwardTable2")
 	procGetIpForwardTable2                                   = modiphlpapi.NewProc("GetIpForwardTable2")
+	procGetIpInterfaceEntry                                  = modiphlpapi.NewProc("GetIpInterfaceEntry")
+	procGetIpInterfaceTable                                  = modiphlpapi.NewProc("GetIpInterfaceTable")
 	procGetUnicastIpAddressEntry                             = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
 	procGetUnicastIpAddressEntry                             = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
+	procGetUnicastIpAddressTable                             = modiphlpapi.NewProc("GetUnicastIpAddressTable")
 	procNotifyIpInterfaceChange                              = modiphlpapi.NewProc("NotifyIpInterfaceChange")
 	procNotifyIpInterfaceChange                              = modiphlpapi.NewProc("NotifyIpInterfaceChange")
 	procNotifyRouteChange2                                   = modiphlpapi.NewProc("NotifyRouteChange2")
 	procNotifyRouteChange2                                   = modiphlpapi.NewProc("NotifyRouteChange2")
 	procNotifyUnicastIpAddressChange                         = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
 	procNotifyUnicastIpAddressChange                         = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
@@ -1674,6 +1678,14 @@ func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) {
 	return
 	return
 }
 }
 
 
+func GetIfTable2Ex(level uint32, table **MibIfTable2) (errcode error) {
+	r0, _, _ := syscall.SyscallN(procGetIfTable2Ex.Addr(), uintptr(level), uintptr(unsafe.Pointer(table)))
+	if r0 != 0 {
+		errcode = syscall.Errno(r0)
+	}
+	return
+}
+
 func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) {
 func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) {
 	r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row)))
 	r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row)))
 	if r0 != 0 {
 	if r0 != 0 {
@@ -1690,6 +1702,22 @@ func GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode erro
 	return
 	return
 }
 }
 
 
+func GetIpInterfaceEntry(row *MibIpInterfaceRow) (errcode error) {
+	r0, _, _ := syscall.SyscallN(procGetIpInterfaceEntry.Addr(), uintptr(unsafe.Pointer(row)))
+	if r0 != 0 {
+		errcode = syscall.Errno(r0)
+	}
+	return
+}
+
+func GetIpInterfaceTable(family uint16, table **MibIpInterfaceTable) (errcode error) {
+	r0, _, _ := syscall.SyscallN(procGetIpInterfaceTable.Addr(), uintptr(family), uintptr(unsafe.Pointer(table)))
+	if r0 != 0 {
+		errcode = syscall.Errno(r0)
+	}
+	return
+}
+
 func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
 func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
 	r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row)))
 	r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row)))
 	if r0 != 0 {
 	if r0 != 0 {
@@ -1698,6 +1726,14 @@ func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
 	return
 	return
 }
 }
 
 
+func GetUnicastIpAddressTable(family uint16, table **MibUnicastIpAddressTable) (errcode error) {
+	r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressTable.Addr(), uintptr(family), uintptr(unsafe.Pointer(table)))
+	if r0 != 0 {
+		errcode = syscall.Errno(r0)
+	}
+	return
+}
+
 func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
 func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
 	var _p0 uint32
 	var _p0 uint32
 	if initialNotification {
 	if initialNotification {

+ 2 - 2
vendor/modules.txt

@@ -189,11 +189,11 @@ go.opentelemetry.io/otel/trace
 go.opentelemetry.io/otel/trace/embedded
 go.opentelemetry.io/otel/trace/embedded
 go.opentelemetry.io/otel/trace/internal/telemetry
 go.opentelemetry.io/otel/trace/internal/telemetry
 go.opentelemetry.io/otel/trace/noop
 go.opentelemetry.io/otel/trace/noop
-# golang.org/x/net v0.53.0
+# golang.org/x/net v0.54.0
 ## explicit; go 1.25.0
 ## explicit; go 1.25.0
 golang.org/x/net/internal/timeseries
 golang.org/x/net/internal/timeseries
 golang.org/x/net/trace
 golang.org/x/net/trace
-# golang.org/x/sys v0.43.0
+# golang.org/x/sys v0.44.0
 ## explicit; go 1.25.0
 ## explicit; go 1.25.0
 golang.org/x/sys/unix
 golang.org/x/sys/unix
 golang.org/x/sys/windows
 golang.org/x/sys/windows