package models import ( "crypto/sha256" "encoding/json" "errors" "fmt" "sort" "strings" ) type AttributeList map[string]string type Participant struct { Meta Firstname string Lastname string Token string Attributes AttributeList `csv:"Attributes"` } func (p *Participant) String() string { return fmt.Sprintf("%s %s", p.Lastname, p.Firstname) } func (p *Participant) GetHash() string { return fmt.Sprintf("%x", sha256.Sum256([]byte(strings.Join(append([]string{p.Lastname, p.Firstname}, p.AttributesToSlice()...), "")))) } func (p *Participant) AttributesToSlice() []string { result := make([]string, 0) for k, v := range p.Attributes { result = append(result, k, v) } return result } func (p *Participant) Marshal() ([]byte, error) { return json.Marshal(p) } func (p *Participant) Unmarshal(data []byte) error { return json.Unmarshal(data, p) } func (al AttributeList) MarshalCSV() (string, error) { result := convertMapToKeyValueOrderedString(al) return result, nil } func (al *AttributeList) UnmarshalCSV(csv string) error { if *al == nil { *al = make(AttributeList) } pairs := strings.Split(csv, ",") for _, pair := range pairs { attrVal := strings.Split(pair, ":") if len(attrVal) != 2 { return errors.New("Invalid input format for attribute list.") } attr := strings.TrimSpace(attrVal[0]) val := strings.TrimSpace(attrVal[1]) (*al)[attr] = val } return nil } func (al AttributeList) Get(key string) string { return al[key] } func (al AttributeList) String() string { result := make([]string, 0) for k, v := range al { result = append(result, fmt.Sprintf("%s: %s", k, v)) } return strings.Join(result, ",") } func convertMapToKeyValueOrderedString(m map[string]string) string { keys := make([]string, 0, len(m)) for key := range m { keys = append(keys, key) } sort.Strings(keys) var result strings.Builder for _, key := range keys { result.WriteString(key) result.WriteString(":") result.WriteString(m[key]) result.WriteString(",") } return strings.TrimSuffix(result.String(), ",") }