10 type EpisodeContainer interface {
11 // Returns true if this EpisodeContainer is equivalent or a superset of the given EpisodeContainer
12 ContainsEpisodes(EpisodeContainer) bool
15 type Formatter interface {
16 // Returns a string where the number portion is 0-padded to fit 'width' digits
17 Format(width int) string
19 // Returns a string where the number portion is 0-padded to be the same length
21 FormatLog(max int) string
27 EpisodeTypeRegular = EpisodeType(1 + iota)
28 EpisodeTypeSpecial // "S" episode
29 EpisodeTypeCredits // "C" episode
30 EpisodeTypeTrailer // "T" episode
31 EpisodeTypeParody // "P" episode
32 EpisodeTypeOther // "O" episode
35 func parseEpisodeType(typ string) EpisodeType {
38 return EpisodeTypeRegular
40 return EpisodeTypeSpecial
42 return EpisodeTypeCredits
44 return EpisodeTypeTrailer
46 return EpisodeTypeParody
48 return EpisodeTypeOther
53 func (et EpisodeType) String() string {
55 case EpisodeTypeRegular:
57 case EpisodeTypeSpecial:
59 case EpisodeTypeCredits:
61 case EpisodeTypeTrailer:
63 case EpisodeTypeParody:
65 case EpisodeTypeOther:
76 // returns how many digits are needed to represent this int
77 func scale(i int) int {
78 return 1 + int(math.Floor(math.Log10(float64(i))))
81 // Converts the Episode into AniDB API episode format.
82 func (ep *Episode) String() string {
86 // returns how many digits are needed to represent this episode
87 func (ep *Episode) scale() int {
91 return scale(ep.Number)
94 // Returns true if ec is an Episode and is identical to this episode,
95 // or if ec is a single episode EpisodeRange / EpisodeList that
96 // contain only this episode.
97 func (ep *Episode) ContainsEpisodes(ec EpisodeContainer) bool {
98 switch e := ec.(type) {
100 return ep != nil && ep.Type == e.Type && ep.Number == e.Number
103 return EpisodeList{&EpisodeRange{Type: ep.Type, Start: ep, End: ep}}.ContainsEpisodes(ep)
109 func (ep *Episode) Format(width int) string {
110 return fmt.Sprintf("%s%0"+strconv.Itoa(width)+"d", ep.Type, ep.Number)
113 func (ep *Episode) FormatLog(max int) string {
114 return ep.Format(scale(max))
117 // Parses a string in the usual AniDB API episode format and converts into
119 func ParseEpisode(s string) *Episode {
120 if no, err := strconv.ParseInt(s, 10, 32); err == nil {
121 return &Episode{Type: EpisodeTypeRegular, Number: int(no)}
122 } else if len(s) < 1 {
124 } else if no, err = strconv.ParseInt(s[1:], 10, 30); err == nil {
125 return &Episode{Type: parseEpisodeType(s[:1]), Number: int(no)}