mic.go 3.33 KB
package mic_m

import (
	"git.hilo.cn/hilo-common/_const/enum/timezone_e"
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/resource/mysql"
	"git.hilo.cn/hilo-common/utils"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"time"
)

// 用户上麦
type UserOnMic struct {
	Date        string
	UserId      mysql.ID
	Seconds     mysql.Num
	LastCalTs   int64
	CreatedTime time.Time `gorm:"->"`
	UpdatedTime time.Time `gorm:"->"`
	Tz          timezone_e.Timezone
}

// 获取用户当日上麦
// 允许返回gorm.ErrRecordNotFound
func GetUserOnMic(model *domain.Model, userId mysql.ID, tz timezone_e.Timezone) (*UserOnMic, error) {
	res := new(UserOnMic)
	day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
	if err := model.DB().Where("date = ? AND user_id = ? AND tz = ?", day, userId, tz).First(res).Error; err != nil {
		return nil, err
	}
	return res, nil
}

// 增加用户上麦时长
// 事务操作
func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) error {
	return model.Transaction(func(model *domain.Model) error {
		for _, tz := range timezone_e.Timezones {
			omMic, err := GetUserOnMic(model, userId, tz)
			if err != nil && err != gorm.ErrRecordNotFound {
				return err
			}
			curTs := joinMicTimestamp
			nowTs := time.Now().Unix()
			day0Ts := utils.GetZeroTime(time.Now().In(timezone_e.TimezoneLocMap[tz])).Unix()
			if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小
				curTs = omMic.LastCalTs
			}
			// 跨天
			if curTs < day0Ts {
				curTs = day0Ts
			}
			score := nowTs - curTs
			day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
			onMicNew := &UserOnMic{
				Date:      day,
				UserId:    userId,
				Seconds:   mysql.Num(score),
				LastCalTs: nowTs,
				Tz:        tz,
			}
			if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
				Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
				DoUpdates: clause.Assignments(map[string]interface{}{
					"seconds":     gorm.Expr("seconds + ?", onMicNew.Seconds),
					"last_cal_ts": nowTs,
				}),
			}).Create(onMicNew).Error; err != nil {
				model.Log.Errorf("IncrUserOnMic fail:%v", err)
				return err
			}
		}
		return nil
	})
}

// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
	var rows []UserOnMic
	res := make(map[mysql.ID]mysql.Num)
	if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND tz = ? AND user_id in ?", day, tz, userIds).Find(&rows).Error; err != nil {
		model.Log.Errorf("MGetUserOnMic fail:%v", err)
		return res, err
	}
	for _, r := range rows {
		res[r.UserId] = r.Seconds
	}
	return res, nil
}

// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSecondsRange(model *domain.Model, beginDate, endDate string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
	var rows []UserOnMic
	res := make(map[mysql.ID]mysql.Num)
	if err := model.DB().Model(UserOnMic{}).Where("`date` >= ? AND `date` <= ? AND tz = ? AND user_id in ?", beginDate, endDate, tz, userIds).Find(&rows).Error; err != nil {
		model.Log.Errorf("MGetUserOnMic fail:%v", err)
		return res, err
	}
	for _, r := range rows {
		res[r.UserId] = r.Seconds
	}
	return res, nil
}