package engine import ( "math/rand" "time" "github.com/deluan/gosonic/domain" "github.com/deluan/gosonic/utils" ) // TODO Use Entries instead of Albums type ListGenerator interface { GetNewest(offset int, size int) (domain.Albums, error) GetRecent(offset int, size int) (domain.Albums, error) GetFrequent(offset int, size int) (domain.Albums, error) GetHighest(offset int, size int) (domain.Albums, error) GetRandom(offset int, size int) (domain.Albums, error) GetStarred() (Entries, error) GetNowPlaying() (Entries, error) } func NewListGenerator(alr domain.AlbumRepository, mfr domain.MediaFileRepository, npr NowPlayingRepository) ListGenerator { return listGenerator{alr, mfr, npr} } type listGenerator struct { albumRepo domain.AlbumRepository mfRepository domain.MediaFileRepository npRepo NowPlayingRepository } func (g listGenerator) query(qo domain.QueryOptions, offset int, size int) (domain.Albums, error) { qo.Offset = offset qo.Size = size return g.albumRepo.GetAll(qo) } func (g listGenerator) GetNewest(offset int, size int) (domain.Albums, error) { qo := domain.QueryOptions{SortBy: "CreatedAt", Desc: true, Alpha: true} return g.query(qo, offset, size) } func (g listGenerator) GetRecent(offset int, size int) (domain.Albums, error) { qo := domain.QueryOptions{SortBy: "PlayDate", Desc: true, Alpha: true} return g.query(qo, offset, size) } func (g listGenerator) GetFrequent(offset int, size int) (domain.Albums, error) { qo := domain.QueryOptions{SortBy: "PlayCount", Desc: true} return g.query(qo, offset, size) } func (g listGenerator) GetHighest(offset int, size int) (domain.Albums, error) { qo := domain.QueryOptions{SortBy: "Rating", Desc: true} return g.query(qo, offset, size) } func (g listGenerator) GetRandom(offset int, size int) (domain.Albums, error) { ids, err := g.albumRepo.GetAllIds() if err != nil { return nil, err } size = utils.MinInt(size, len(ids)) perm := rand.Perm(size) r := make(domain.Albums, size) for i := 0; i < size; i++ { v := perm[i] al, err := g.albumRepo.Get((ids)[v]) if err != nil { return nil, err } r[i] = *al } return r, nil } func (g listGenerator) GetStarred() (Entries, error) { albums, err := g.albumRepo.GetStarred(domain.QueryOptions{}) if err != nil { return nil, err } entries := make(Entries, len(albums)) for i, al := range albums { entries[i] = FromAlbum(&al) } return entries, nil } func (g listGenerator) GetNowPlaying() (Entries, error) { npInfo, err := g.npRepo.GetAll() if err != nil { return nil, err } entries := make(Entries, len(*npInfo)) for i, np := range *npInfo { mf, err := g.mfRepository.Get(np.TrackId) if err != nil { return nil, err } entries[i] = FromMediaFile(mf) entries[i].UserName = np.Username entries[i].MinutesAgo = int(time.Now().Sub(np.Start).Minutes()) entries[i].PlayerId = np.PlayerId entries[i].PlayerName = np.PlayerName } return entries, nil }