]> git.lizzy.rs Git - go-anidb.git/commitdiff
anidb: Implement MYLISTSTATS
authorDiogo Franco (Kovensky) <diogomfranco@gmail.com>
Fri, 26 Jul 2013 23:34:09 +0000 (20:34 -0300)
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>
Fri, 26 Jul 2013 23:34:09 +0000 (20:34 -0300)
misc.go [new file with mode: 0644]
misccache.go [new file with mode: 0644]

diff --git a/misc.go b/misc.go
new file mode 100644 (file)
index 0000000..895196b
--- /dev/null
+++ b/misc.go
@@ -0,0 +1,33 @@
+package anidb
+
+import (
+       "github.com/Kovensky/go-fscache"
+       "strconv"
+       "strings"
+       "time"
+)
+
+type MyListStats struct {
+       Anime         int
+       Episodes      int
+       Files         int
+       Filesize      int64
+       AddedAnime    int
+       AddedEpisodes int
+       AddedFiles    int
+       AddedGroups   int
+
+       Leech             float32 // rate of Files to AddedFiles
+       Glory             float32 // meaning undocumented
+       ViewedPctDatabase float32
+       MyListPctDatabase float32
+       AnimePctDatabase  float32 // Only valid if the titles database is loaded
+       ViewedPctMyList   float32
+       ViewedEpisodes    int
+       Votes             int
+       Reviews           int
+
+       ViewedTime time.Duration
+
+       Cached time.Time
+}
diff --git a/misccache.go b/misccache.go
new file mode 100644 (file)
index 0000000..9583903
--- /dev/null
@@ -0,0 +1,112 @@
+package anidb
+
+import (
+       "github.com/Kovensky/go-fscache"
+       "strconv"
+       "strings"
+       "time"
+)
+
+func (s *MyListStats) setCachedTS(t time.Time) { s.Cached = t }
+
+func (s *MyListStats) IsStale() bool {
+       if s == nil || time.Now().Sub(s.Cached) > MyListCacheDuration {
+               return true
+       }
+       return false
+}
+
+var _ cacheable = &MyListStats{}
+
+func (u *User) Stats() *MyListStats {
+       if u == nil {
+               return nil
+       }
+       var s MyListStats
+       if CacheGet(&s, "mylist-stats", u.UID) == nil {
+               return &s
+       }
+       return nil
+}
+
+func (adb *AniDB) MyListStats(user *User) <-chan *MyListStats {
+       ch := make(chan *MyListStats, 1)
+       if user == nil || user.UID < 1 {
+               ch <- nil
+               close(ch)
+               return ch
+       }
+
+       key := []fscache.CacheKey{"mylist-stats", user.UID}
+
+       ic := make(chan notification, 1)
+       go func() { ch <- (<-ic).(*MyListStats) }()
+       if intentMap.Intent(ic, key...) {
+               return ch
+       }
+
+       stats := user.Stats()
+       if !stats.IsStale() {
+               defer intentMap.NotifyClose(stats, key...)
+               return ch
+       }
+
+       go func() {
+               if adb.User() == nil {
+                       r := adb.udp.ReAuth()
+                       if r.Code() >= 500 {
+                               intentMap.NotifyClose(stats, key...)
+                               return
+                       }
+               }
+
+               if user.UID != adb.User().UID {
+                       intentMap.NotifyClose(stats, key...)
+                       return
+               }
+
+               reply := <-adb.udp.SendRecv("MYLISTSTATS", nil)
+               switch reply.Code() {
+               case 222:
+                       parts := strings.Split(reply.Lines()[1], "|")
+                       ints := make([]int64, len(parts))
+                       for i := range parts {
+                               ints[i], _ = strconv.ParseInt(parts[i], 10, 64)
+                       }
+
+                       stats = &MyListStats{
+                               Anime:    int(ints[0]),
+                               Episodes: int(ints[1]),
+                               Files:    int(ints[2]),
+                               Filesize: ints[3] * 1024 * 1024, // it comes in MB
+
+                               AddedAnime:    int(ints[4]),
+                               AddedEpisodes: int(ints[5]),
+                               AddedFiles:    int(ints[6]),
+                               AddedGroups:   int(ints[7]),
+
+                               Leech: float32(ints[8]) / 100,
+                               Glory: float32(ints[9]) / 100,
+
+                               ViewedPctDatabase: float32(ints[10]) / 100,
+                               MyListPctDatabase: float32(ints[11]) / 100,
+                               // ViewedPctMyList: float32(ints[12]) / 100, // we can calculate a more accurate value
+                               ViewedEpisodes: int(ints[13]),
+
+                               Votes:   int(ints[14]),
+                               Reviews: int(ints[15]),
+
+                               ViewedTime: time.Duration(ints[16]) * time.Minute,
+                       }
+                       stats.ViewedPctMyList = float32(stats.ViewedEpisodes) / float32(stats.Episodes)
+
+                       if ac := AnimeCount(); ac > 0 {
+                               stats.AnimePctDatabase = float32(stats.Anime) / float32(ac)
+                       }
+
+                       CacheSet(stats, key...)
+               }
+               intentMap.NotifyClose(stats, key...)
+       }()
+       return ch
+}