package storia import ( "bytes" "math" "os" "sort" "strconv" "strings" "git.phc.dm.unipi.it/phc/website/articles" "git.phc.dm.unipi.it/phc/website/util" "gopkg.in/yaml.v3" ) type StoriaService interface { GetStoria() ([]*GenericEvent, error) } type GenericEvent struct { // Campi principali Type string `yaml:"type"` Date string `yaml:"date"` // Altri campi utilizzati ogni tanto Title string `yaml:"title"` Description string `yaml:"description"` // Se il tipo di evento è riferito ad un utente usiamo anche questo campo apposta Uid string `yaml:"uid"` FullName string `yaml:"fullName"` // Se il tipo è "spacer" questa è la sua dimensione Size int `yaml:"size"` // Icona opzionale per il tipo "simple" Icon string `yaml:"icon"` } type Macchinista struct { Uid string `yaml:"uid"` FullName string `yaml:"fullName"` EntryDate string `yaml:"entryDate"` ExitDate string `yaml:"exitDate"` } type storiaDB struct { Macchinisti []*Macchinista `yaml:"macchinisti"` GenericEvent []*GenericEvent `yaml:"eventi"` } type JsonFileStoria struct { Path string } type byEventDateDescending []*GenericEvent func (m byEventDateDescending) Len() int { return len(m) } func (m byEventDateDescending) Swap(i, j int) { m[i], m[j] = m[j], m[i] } func (m byEventDateDescending) Less(i, j int) bool { return m[i].Date > m[j].Date } func (db *JsonFileStoria) GetStoria() ([]*GenericEvent, error) { history, err := db.GetRawStoria() if err != nil { return nil, err } events := history.GenericEvent[:] for _, m := range history.Macchinisti { if m.ExitDate != "" { events = append(events, &GenericEvent{ Type: "exit-macchinista", Uid: m.Uid, FullName: m.FullName, Date: m.ExitDate, }) } if m.EntryDate != "" { events = append(events, &GenericEvent{ Type: "entry-macchinista", Uid: m.Uid, FullName: m.FullName, Date: m.EntryDate, }) } } sort.Sort(byEventDateDescending(events)) // render descriptions to markdown for _, event := range events { var buf bytes.Buffer if err := articles.Markdown.Convert([]byte(event.Description), &buf); err != nil { return nil, err } event.Description = buf.String() } return withSpacers(events), nil } func (db *JsonFileStoria) GetRawStoria() (*storiaDB, error) { var rawHistory storiaDB f, err := os.Open(db.Path) if err != nil { return nil, err } if err := yaml.NewDecoder(f).Decode(&rawHistory); err != nil { return nil, err } return &rawHistory, nil } func withSpacers(events []*GenericEvent) []*GenericEvent { // crea un nuovo slice con capacità già almeno "len(events)" newEvents := make([]*GenericEvent, 0, len(events)) for i := 0; i < len(events)-1; i++ { newEvents = append(newEvents, events[i]) delta := util.Abs(getDateYear(events[i+1].Date) - getDateYear(events[i].Date)) if delta > 1 { logDelta := int(math.Log(float64(delta))) newEvents = append(newEvents, &GenericEvent{ Type: "spacer", Size: logDelta, }) } } newEvents = append(newEvents, events[len(events)-1]) return newEvents } func getDateYear(date string) int { year, err := strconv.Atoi(strings.Split(date, "/")[0]) if err != nil { panic(err) // Tanto nel caso si nota in fase di sviluppo visto che "_content/storia.json" è statico } return year }