]> git.lizzy.rs Git - go-anidb.git/commitdiff
misc: (*EpisodeRange).Split(*Episode) -- Splits a range
authorDiogo Franco (Kovensky) <diogomfranco@gmail.com>
Wed, 17 Jul 2013 17:26:02 +0000 (14:26 -0300)
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>
Wed, 17 Jul 2013 17:26:02 +0000 (14:26 -0300)
Also define Inc/IncNumber/Dec/DecNumber for episodes, used internally by
Split. Includes test.

misc/episode.go
misc/episoderange.go
misc/episoderange_test.go

index 72140d4abb602967f7ba90fe6e3d3c3d34a27469..1dbd1726e899236efb37bea898ad6389d8a7a9dd 100644 (file)
@@ -134,6 +134,34 @@ func (ep *Episode) FormatLog(max int) string {
        return ep.Format(scale(max))
 }
 
+func (ep *Episode) Inc() {
+       if ep.Parts > 0 && ep.Part == ep.Parts-1 {
+               ep.IncNumber()
+       } else {
+               ep.Part++
+       }
+}
+
+func (ep *Episode) IncNumber() {
+       ep.Part = -1
+       ep.Parts = 0
+       ep.Number++
+}
+
+func (ep *Episode) Dec() {
+       if ep.Part > 0 {
+               ep.Part--
+       } else {
+               ep.DecNumber()
+       }
+}
+
+func (ep *Episode) DecNumber() {
+       ep.Part = -1
+       ep.Parts = 0
+       ep.Number--
+}
+
 // Parses a string in the usual AniDB API episode format and converts into
 // an Episode.
 func ParseEpisode(s string) *Episode {
index fb91caab9fc2c041acc31f5c12f5265a5f3d8ec5..729d2c8ea2965366d22a691bdf9cebf306115c01 100644 (file)
@@ -144,6 +144,132 @@ func (a *EpisodeRange) Merge(b *EpisodeRange) (c *EpisodeRange) {
        return
 }
 
+// Check if the given range is not nil, has a defined start
+// and, if it has an end, that the end ends after the start.
+func (er *EpisodeRange) Valid() bool {
+       switch {
+       case er == nil, er.Start == nil:
+               return false
+       case er.End == nil:
+               return true
+       case er.Start.Number < er.End.Number:
+               return true
+       case er.Start.Number > er.End.Number:
+               return false
+       case er.Start.Part <= er.End.Part:
+               return true
+       default:
+               return false
+       }
+}
+
+// Simplifies the Start/End ranges if one contains the other.
+// Sets the pointers to be identical if the range is modified.
+//
+// Modifies in-place, returns itself.
+func (er *EpisodeRange) Simplify() *EpisodeRange {
+       switch {
+       case er.Start.ContainsEpisodes(er.End):
+               er.End = er.Start
+       case er.End != nil && er.End.ContainsEpisodes(er.Start):
+               er.Start = er.End
+       }
+       return er
+}
+
+// Splits the range into one or two ranges, using the given
+// Episode as the split point. The Episode is not included in
+// the resulting ranges.
+func (er *EpisodeRange) Split(ep *Episode) []*EpisodeRange {
+       if !er.ContainsEpisodes(ep) { // implies same type
+               return []*EpisodeRange{er}
+       }
+       if !er.Valid() {
+               return []*EpisodeRange{nil, nil}
+       }
+
+       a := *er.Start
+
+       inf := er.End == nil
+       b := Episode{}
+       if !inf {
+               b = *er.End
+       }
+
+       end := &b
+       if inf {
+               end = nil
+       }
+
+       switch {
+       case a.ContainsEpisodes(ep) && b.ContainsEpisodes(ep):
+               return []*EpisodeRange{nil, nil}
+       case a.ContainsEpisodes(ep):
+               if ep.Part >= 0 {
+                       a.Inc()
+               } else {
+                       a.IncNumber()
+               }
+               if a.Number == b.Number && b.Parts > 0 {
+                       a.Parts = b.Parts
+               }
+
+               r := &EpisodeRange{
+                       Type:  er.Type,
+                       Start: &a,
+                       End:   end,
+               }
+               return []*EpisodeRange{nil, r.Simplify()}
+       case b.ContainsEpisodes(ep):
+               if ep.Part >= 0 {
+                       b.Dec()
+               } else {
+                       b.DecNumber()
+               }
+               if b.Number == a.Number {
+                       if a.Parts > 0 {
+                               b.Parts = a.Parts
+                               b.Part = a.Parts - 1
+                       } else if b.Part < 0 {
+                               b.Part = a.Part
+                       }
+               }
+               r := &EpisodeRange{
+                       Type:  er.Type,
+                       Start: &a,
+                       End:   &b,
+               }
+               return []*EpisodeRange{r.Simplify(), nil}
+       default:
+               ra := &EpisodeRange{
+                       Type:  er.Type,
+                       Start: &a,
+                       End:   ep,
+               }
+               rb := &EpisodeRange{
+                       Type:  er.Type,
+                       Start: ep,
+                       End:   end,
+               }
+
+               ra = ra.Split(ep)[0]
+               rb = rb.Split(ep)[1]
+
+               if ra.Valid() {
+                       ra.Simplify()
+               } else {
+                       ra = nil
+               }
+               if rb.Valid() {
+                       rb.Simplify()
+               } else {
+                       rb = nil
+               }
+
+               return []*EpisodeRange{ra, rb}
+       }
+}
+
 // Returns true if both ranges are of the same type and
 // have identical start/end positions
 func (a *EpisodeRange) Equals(b *EpisodeRange) bool {
index df6726865b09e4dd49bedfce7da68acda30c260c..2402cdd5462940c11b9c60e387faab77bdb0182f 100644 (file)
@@ -50,3 +50,32 @@ func ExampleEpisodeRange_PartialMerge() {
        // <nil>
        // 1-2.3
 }
+
+func ExampleEpisodeRange_Split() {
+       a := misc.ParseEpisodeRange("1.0-1.3")
+       b := misc.ParseEpisode("1.2")
+       fmt.Println(a.Split(b))
+
+       b = misc.ParseEpisode("1")
+       fmt.Println(a.Split(b))
+
+       a = misc.ParseEpisodeRange("1.1-2")
+       fmt.Println(a.Split(b))
+
+       b = misc.ParseEpisode("2")
+       fmt.Println(a.Split(b))
+
+       a = misc.ParseEpisodeRange("1-10")
+       fmt.Println(a.Split(b))
+
+       b = misc.ParseEpisode("4")
+       fmt.Println(a.Split(b))
+
+       // Output:
+       // [1.0-1.1 1.3]
+       // [<nil> <nil>]
+       // [<nil> 2]
+       // [1.1 <nil>]
+       // [1 03-10]
+       // [1-3 05-10]
+}