photoprism/internal/query/moments.go
Michael Mayer dcc610d7a9 Use AlbumType to distinguish between manual collections and moments #154
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
2020-05-29 12:21:17 +02:00

150 lines
4.3 KiB
Go

package query
import (
"fmt"
"strings"
"time"
"github.com/gosimple/slug"
"github.com/photoprism/photoprism/internal/maps"
)
// Moment contains photo counts per month and year
type Moment struct {
PhotoCategory string `json:"Category"`
PhotoCountry string `json:"Country"`
PhotoState string `json:"State"`
PhotoYear int `json:"Year"`
PhotoMonth int `json:"Month"`
PhotoCount int `json:"Count"`
}
var MomentCategory = map[string]string{
"botanical garden": "Botanical Gardens",
"nature reserve": "Nature Reserves",
"bay": "Bays, Capes & Beaches",
"beach": "Bays, Capes & Beaches",
"cape": "Bays, Capes & Beaches",
}
// Slug returns an identifier string for a moment.
func (m Moment) Slug() string {
return slug.Make(m.Title())
}
// Title returns an english title for the moment.
func (m Moment) Title() string {
if m.PhotoYear == 0 && m.PhotoMonth == 0 {
if m.PhotoCategory != "" {
return MomentCategory[m.PhotoCategory]
}
country := maps.CountryName(m.PhotoCountry)
if strings.Contains(m.PhotoState, country) {
return m.PhotoState
}
if m.PhotoState == "" {
return m.PhotoCountry
}
return fmt.Sprintf("%s / %s", m.PhotoState, country)
}
if m.PhotoCountry != "" && m.PhotoYear > 1900 && m.PhotoMonth == 0 {
if m.PhotoState != "" {
return fmt.Sprintf("%s / %s / %d", m.PhotoState, maps.CountryName(m.PhotoCountry), m.PhotoYear)
}
return fmt.Sprintf("%s %d", maps.CountryName(m.PhotoCountry), m.PhotoYear)
}
if m.PhotoYear > 1900 && m.PhotoMonth > 0 && m.PhotoMonth <= 12 {
date := time.Date(m.PhotoYear, time.Month(m.PhotoMonth), 1, 0, 0, 0, 0, time.UTC)
if m.PhotoCountry == "" {
return date.Format("January 2006")
}
return fmt.Sprintf("%s / %s", maps.CountryName(m.PhotoCountry), date.Format("January 2006"))
}
if m.PhotoMonth > 0 && m.PhotoMonth <= 12 {
return time.Month(m.PhotoMonth).String()
}
return maps.CountryName(m.PhotoCountry)
}
type Moments []Moment
// MomentsTime counts photos by month and year.
func MomentsTime(threshold int) (results Moments, err error) {
db := UnscopedDb().Table("photos").
Where("photos.photo_quality >= 3 AND deleted_at IS NULL AND photo_year > 0 AND photo_month > 0").
Select("photos.photo_year, photos.photo_month, COUNT(*) AS photo_count").
Group("photos.photo_year, photos.photo_month").
Order("photos.photo_year DESC, photos.photo_month DESC").
Having("photo_count >= ?", threshold)
if err := db.Scan(&results).Error; err != nil {
return results, err
}
return results, nil
}
// MomentsCountries returns the most popular countries by year.
func MomentsCountries(threshold int) (results Moments, err error) {
db := UnscopedDb().Table("photos").
Where("photos.photo_quality >= 3 AND deleted_at IS NULL AND photo_country <> 'zz' AND photo_year > 0").
Select("photo_country, photo_year, COUNT(*) AS photo_count ").
Group("photo_country, photo_year").
Having("photo_count >= ?", threshold)
if err := db.Scan(&results).Error; err != nil {
return results, err
}
return results, nil
}
// MomentsStates returns the most popular states and countries by year.
func MomentsStates(threshold int) (results Moments, err error) {
db := UnscopedDb().Table("photos").
Joins("JOIN places p ON p.place_uid = photos.place_uid").
Where("photos.photo_quality >= 3 AND photos.deleted_at IS NULL AND p.loc_state <> '' AND p.loc_country <> 'zz'").
Select("p.loc_country AS photo_country, p.loc_state AS photo_state, COUNT(*) AS photo_count").
Group("photo_country, photo_state").
Having("photo_count >= ?", threshold)
if err := db.Scan(&results).Error; err != nil {
return results, err
}
return results, nil
}
// MomentsCategories returns the most popular photo categories.
func MomentsCategories(threshold int) (results Moments, err error) {
var cats []string
for cat, _ := range MomentCategory {
cats = append(cats, cat)
}
db := UnscopedDb().Table("photos").
Joins("JOIN locations l ON l.loc_uid = photos.loc_uid AND photos.loc_uid <> 'zz'").
Where("photos.photo_quality >= 3 AND photos.deleted_at IS NULL AND l.loc_category IN (?)", cats).
Select("l.loc_category AS photo_category, COUNT(*) AS photo_count").
Group("photo_category").
Having("photo_count >= ?", threshold)
if err := db.Scan(&results).Error; err != nil {
return results, err
}
return results, nil
}