10 type EpisodeCount struct {
19 type EpisodeList []*EpisodeRange
21 func EpisodeToList(ep *Episode) EpisodeList {
22 return RangesToList(EpisodeToRange(ep))
25 func RangesToList(ranges ...*EpisodeRange) EpisodeList {
26 return EpisodeList(ranges)
29 func ContainerToList(ec EpisodeContainer) EpisodeList {
30 switch v := ec.(type) {
32 return EpisodeToList(v)
34 return RangesToList(v)
38 panic("unimplemented")
42 // Converts the EpisodeList into the AniDB API list format.
43 func (el EpisodeList) String() string {
44 scales := map[EpisodeType]int{}
46 for _, er := range el {
52 if s > scales[er.Type] {
57 parts := make([]string, len(el))
58 for i, er := range el {
59 parts[i] = er.Format(scales[er.Type])
62 return strings.Join(parts, ",")
65 // Formats the list according to the number of digits of
66 // the count for its type, given in the EpisodeCount.
67 func (el EpisodeList) FormatLog(ec EpisodeCount) string {
68 parts := make([]string, len(el))
69 for i, er := range el {
71 case EpisodeTypeRegular:
72 parts[i] = er.FormatLog(ec.RegularCount)
73 case EpisodeTypeSpecial:
74 parts[i] = er.FormatLog(ec.SpecialCount)
75 case EpisodeTypeCredits:
76 parts[i] = er.FormatLog(ec.CreditsCount)
77 case EpisodeTypeOther:
78 parts[i] = er.FormatLog(ec.OtherCount)
79 case EpisodeTypeTrailer:
80 parts[i] = er.FormatLog(ec.TrailerCount)
81 case EpisodeTypeParody:
82 parts[i] = er.FormatLog(ec.ParodyCount)
84 parts[i] = er.Format(er.scale())
88 return strings.Join(parts, ",")
91 func (el EpisodeList) Infinite() bool {
100 // Returns a channel that can be used to iterate using for/range.
102 // If the EpisodeList is infinite, then the channel is also infinite.
103 // The caller is allowed to close the channel in such case.
105 // NOTE: Not thread safe.
106 func (el EpisodeList) Episodes() chan Episode {
107 ch := make(chan Episode, 1)
113 defer func() { recover(); abort = true }()
118 for _, er := range el {
119 for ep := range er.Episodes() {
131 // Returns true if any of the contained EpisodeRanges contain the
132 // given EpisodeContainer.
133 func (el EpisodeList) ContainsEpisodes(ec EpisodeContainer) bool {
134 for _, i := range el {
135 if i != nil && i.ContainsEpisodes(ec) {
142 // Parses a string in the AniDB API list format and converts into
145 // ParseEpisodeList("01") <=> EpisodeList{ParseEpisodeRange("01")}
146 // ParseEpisodeList("S2-S3") <=> EpisodeList{ParseEpisodeRange("S2-S3")}
147 // ParseEpisodeList("T1,C1-C3") <=> EpisodeList{ParseEpisodeRange("T1"), ParseEpisodeRange("C1-C3")}
148 func ParseEpisodeList(s string) (el EpisodeList) {
149 parts := strings.Split(s, ",")
151 el = make(EpisodeList, len(parts))
152 for i := range parts {
153 el[i] = ParseEpisodeRange(parts[i])
159 // Returns a simplified version of the EpisodeList (removes nil ranges, merges mergeable ranges, sorts).
160 func (el EpisodeList) Simplify() EpisodeList {
161 nl := make(EpisodeList, 0, len(el))
164 for _, er := range el {
171 for n, changed := 0, true; changed; n++ {
173 used := map[int]bool{}
176 for i, a := range nl {
180 for j, b := range nl[i+1:] {
181 if c := a.Merge(b); c != nil {
192 panic(fmt.Sprintf("Too many iterations (%d) when simplifing %s!", n, el))
199 func (el EpisodeList) CountEpisodes() (ec EpisodeCount) {
200 for _, er := range el {
203 case EpisodeTypeRegular:
205 case EpisodeTypeSpecial:
207 case EpisodeTypeCredits:
209 case EpisodeTypeOther:
211 case EpisodeTypeTrailer:
213 case EpisodeTypeParody:
225 *c += er.End.Number - er.Start.Number
230 func (el EpisodeList) Len() int {
234 func (el EpisodeList) Less(i, j int) bool {
240 case el[i].Type < el[j].Type:
242 case el[i].Type > el[j].Type:
244 case el[i].Start.Number < el[j].Start.Number:
250 func (el EpisodeList) Swap(i, j int) {
251 el[i], el[j] = el[j], el[i]
254 func (el *EpisodeList) Add(ec EpisodeContainer) {
255 *el = append(*el, ContainerToList(ec)...)
259 func (el *EpisodeList) Sub(ec EpisodeContainer) {
260 el2 := make(EpisodeList, 0, len(*el)*2)
261 switch e, ok := ec.(canInfinite); {
268 for _, r := range *el {
269 el2 = append(el2, r.Split(&ep)[0])
275 for ep := range ec.Episodes() {
276 for _, r := range *el {
277 el2 = append(el2, r.Split(&ep)...)
282 *el = append(*el, el2.Simplify()...)
285 // Equivalent to marshaling el.String()
286 func (el EpisodeList) MarshalJSON() ([]byte, error) {
287 return json.Marshal(el.String())
290 // NOTE: Since the String() representation doesn't include them,
291 // it's not exactly reversible if the user has set .Parts in any
292 // of the contained episodes.
293 func (el EpisodeList) UnmarshalJSON(b []byte) error {
295 if err := json.Unmarshal(b, &v); err != nil {
299 l := ParseEpisodeList(v)