8caf0ac3aa
Added framework to generate DOT and png files of character map chart from data folder. Added all figures in the 1-2 chapters. Added font file SimSum for render chart
95 lines
2.9 KiB
Go
95 lines
2.9 KiB
Go
package entity
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
r "xyj-figures/pkg/relationship"
|
|
|
|
yaml "gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Entity struct {
|
|
Schema string `yaml:"schema,flow"`
|
|
Type string `yaml:"type,flow"`
|
|
Details interface{} `yaml:"details,flow"`
|
|
}
|
|
|
|
type EntityType string
|
|
|
|
const (
|
|
EntityTypeCharacter = "character"
|
|
EntityTypeGroup = "group"
|
|
)
|
|
|
|
type EntityDetails interface {
|
|
GetRelationships() []r.Relationship
|
|
}
|
|
|
|
func NewEntity() (*Entity, error) {
|
|
return &Entity{Schema: "v1"}, nil
|
|
}
|
|
|
|
func Load(path string) (*Entity, error) {
|
|
f, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to open file: %v", err)
|
|
}
|
|
e, _ := NewEntity()
|
|
if err = yaml.Unmarshal(f, &e); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal file: %v", err)
|
|
}
|
|
switch e.Type {
|
|
case EntityTypeCharacter:
|
|
tmp, err := yaml.Marshal(e.Details)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to marshal filed %s: %v", EntityTypeCharacter, err)
|
|
}
|
|
c := Character{}
|
|
if err = yaml.Unmarshal(tmp, &c); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal filed %s: %v", EntityTypeCharacter, err)
|
|
}
|
|
e.Details = c
|
|
case EntityTypeGroup:
|
|
tmp, err := yaml.Marshal(e.Details)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to marshal filed %s: %v", EntityTypeGroup, err)
|
|
}
|
|
g := Group{}
|
|
if err = yaml.Unmarshal(tmp, &g); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal filed %s: %v", EntityTypeGroup, err)
|
|
}
|
|
e.Details = g
|
|
}
|
|
return e, nil
|
|
}
|
|
|
|
func (e Entity) Merge(other Entity) error {
|
|
if (e.Schema != other.Schema) || (e.Type != other.Type) {
|
|
return fmt.Errorf("unmatch merge between %v and %v", e, other)
|
|
}
|
|
switch e.Type {
|
|
case EntityTypeCharacter:
|
|
if e.Details.(Character).Name != other.Details.(Character).Name {
|
|
return fmt.Errorf("unmatch merge between %v and %v: names unmatch", e, other)
|
|
}
|
|
e.Details = Character{
|
|
Name: e.Details.(Character).Name,
|
|
OtherNames: append(e.Details.(Character).OtherNames, other.Details.(Character).OtherNames...),
|
|
Relationships: append(e.Details.(Character).Relationships, other.Details.(Character).Relationships...),
|
|
Description: fmt.Sprintf("%s%s", e.Details.(Character).Description, other.Details.(Character).Description),
|
|
Links: append(e.Details.(Character).Links, other.Details.(Character).Links...),
|
|
}
|
|
case EntityTypeGroup:
|
|
e.Details = Group{
|
|
Name: e.Details.(Group).Name,
|
|
OtherNames: append(e.Details.(Group).OtherNames, other.Details.(Group).OtherNames...),
|
|
Members: append(e.Details.(Group).Members, other.Details.(Group).Members...),
|
|
Relationships: append(e.Details.(Group).Relationships, other.Details.(Group).Relationships...),
|
|
Description: fmt.Sprintf("%s%s", e.Details.(Group).Description, other.Details.(Group).Description),
|
|
Links: append(e.Details.(Group).Links, other.Details.(Group).Links...),
|
|
}
|
|
}
|
|
return nil
|
|
}
|