]> git.lizzy.rs Git - go-anidb.git/blob - misc/episodelist.go
misc: Add FormatLog method to Episode/EpisodeList/EpisodeRange
[go-anidb.git] / misc / episodelist.go
1 package misc
2
3 import (
4         "fmt"
5         "sort"
6         "strings"
7 )
8
9 type EpisodeCount struct {
10         RegularCount int
11         SpecialCount int
12         CreditsCount int
13         OtherCount   int
14         TrailerCount int
15         ParodyCount  int
16 }
17
18 type EpisodeList []*EpisodeRange
19
20 // Converts the EpisodeList into the AniDB API list format.
21 func (el EpisodeList) String() string {
22         scales := map[EpisodeType]int{}
23
24         for _, er := range el {
25                 if er == nil {
26                         continue
27                 }
28
29                 s := er.scale()
30                 if s > scales[er.Type] {
31                         scales[er.Type] = s
32                 }
33         }
34
35         parts := make([]string, len(el))
36         for i, er := range el {
37                 parts[i] = er.Format(scales[er.Type])
38         }
39
40         return strings.Join(parts, ",")
41 }
42
43 // Formats the list according to the number of digits of
44 // the count for its type, given in the EpisodeCount.
45 func (el EpisodeList) FormatLog(ec EpisodeCount) string {
46         parts := make([]string, len(el))
47         for i, er := range el {
48                 switch er.Type {
49                 case EpisodeTypeRegular:
50                         parts[i] = er.FormatLog(ec.RegularCount)
51                 case EpisodeTypeSpecial:
52                         parts[i] = er.FormatLog(ec.SpecialCount)
53                 case EpisodeTypeCredits:
54                         parts[i] = er.FormatLog(ec.CreditsCount)
55                 case EpisodeTypeOther:
56                         parts[i] = er.FormatLog(ec.OtherCount)
57                 case EpisodeTypeTrailer:
58                         parts[i] = er.FormatLog(ec.TrailerCount)
59                 case EpisodeTypeParody:
60                         parts[i] = er.FormatLog(ec.ParodyCount)
61                 default:
62                         parts[i] = er.Format(er.scale())
63                 }
64         }
65
66         return strings.Join(parts, ",")
67 }
68
69 // Returns true if any of the contained EpisodeRanges contain the
70 // given EpisodeContainer.
71 func (el EpisodeList) ContainsEpisodes(ec EpisodeContainer) bool {
72         for _, i := range el {
73                 if i != nil && i.ContainsEpisodes(ec) {
74                         return true
75                 }
76         }
77         return false
78 }
79
80 // Parses a string in the AniDB API list format and converts into
81 // an EpisodeList.
82 //
83 //      ParseEpisodeList("01")       <=> EpisodeList{ParseEpisodeRange("01")}
84 //      ParseEpisodeList("S2-S3")    <=> EpisodeList{ParseEpisodeRange("S2-S3")}
85 //      ParseEpisodeList("T1,C1-C3") <=> EpisodeList{ParseEpisodeRange("T1"), ParseEpisodeRange("C1-C3")}
86 func ParseEpisodeList(s string) (el EpisodeList) {
87         parts := strings.Split(s, ",")
88
89         el = make(EpisodeList, len(parts))
90         for i := range parts {
91                 el[i] = ParseEpisodeRange(parts[i])
92         }
93
94         return
95 }
96
97 // Returns a simplified version of the EpisodeList (removes nil ranges, merges mergeable ranges, sorts).
98 func (el EpisodeList) Simplify() EpisodeList {
99         nl := make(EpisodeList, 0, len(el))
100
101         // drop nil ranges
102         for _, er := range el {
103                 if er != nil {
104                         nl = append(nl, er)
105                 }
106         }
107
108         // merge ranges
109         for n, changed := 0, true; changed; n++ {
110                 tmp := EpisodeList{}
111                 used := map[int]bool{}
112                 changed = false
113
114                 for i, a := range nl {
115                         if used[i] {
116                                 continue
117                         }
118                         for j, b := range nl[i+1:] {
119                                 if c := a.Merge(b); c != nil {
120                                         changed = true
121                                         used[j+i+1] = true
122                                         a = c
123                                 }
124                         }
125                         tmp = append(tmp, a)
126                 }
127                 nl = tmp
128
129                 if n > len(el) {
130                         panic(fmt.Sprintf("Too many iterations (%d) when simplifing %s!", n, el))
131                 }
132         }
133         sort.Sort(nl)
134         return nl
135 }
136
137 func (el EpisodeList) Len() int {
138         return len(el)
139 }
140
141 func (el EpisodeList) Less(i, j int) bool {
142         switch {
143         case el[i] == nil:
144                 return true
145         case el[j] == nil:
146                 return false
147         case el[i].Type < el[j].Type:
148                 return true
149         case el[i].Type > el[j].Type:
150                 return false
151         case el[i].Start.Number < el[j].Start.Number:
152                 return true
153         }
154         return false
155 }
156
157 func (el EpisodeList) Swap(i, j int) {
158         el[i], el[j] = el[j], el[i]
159 }