group_grade.go 6.97 KB
Newer Older
hujiebin's avatar
hujiebin committed
1 2 3 4 5
package groupPower_m

import (
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/resource/mysql"
6 7
	"git.hilo.cn/hilo-common/utils"
	"github.com/jinzhu/now"
hujiebin's avatar
hujiebin committed
8 9 10 11 12 13
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"hilo-group/_const/enum/groupPower_e"
	"time"
)

hujiebin's avatar
hujiebin committed
14
type GroupPowerDayExp struct {
hujiebin's avatar
hujiebin committed
15 16
	Date         string
	GroupPowerId mysql.ID
hujiebin's avatar
hujiebin committed
17
	Exp          mysql.Num
hujiebin's avatar
hujiebin committed
18 19 20 21 22 23
	CreatedTime  time.Time `gorm:"->"`
	UpdatedTime  time.Time `gorm:"->"`
}

type GroupPowerGrade struct {
	GroupPowerId mysql.ID
hujiebin's avatar
hujiebin committed
24
	Exp          mysql.Num
hujiebin's avatar
hujiebin committed
25
	Grade        groupPower_e.GroupPowerGrade
hujiebin's avatar
hujiebin committed
26
	ExpireAt     time.Time
hujiebin's avatar
hujiebin committed
27 28 29 30
	CreatedTime  time.Time `gorm:"->"`
	UpdatedTime  time.Time `gorm:"->"`
}

hujiebin's avatar
hujiebin committed
31 32 33 34 35 36 37 38 39 40 41
type GroupPowerExpDetail struct {
	mysql.Entity
	GroupPowerId mysql.ID
	UserId       mysql.ID
	Exp          mysql.Num
	AddReduce    mysql.AddReduce
	BefNum       mysql.Num
	AftNum       mysql.Num
	Remark       string
}

hujiebin's avatar
hujiebin committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55
type GroupPowerOnMic struct {
	Date         string
	GroupPowerId mysql.ID
	UserId       mysql.ID
	Seconds      int64
	LastCalTs    int64
	CreatedTime  time.Time `gorm:"->"`
	UpdatedTime  time.Time `gorm:"->"`
}

type GroupPowerOnMicDetail struct {
	Date         string
	GroupPowerId mysql.ID
	UserId       mysql.ID
hujiebin's avatar
hujiebin committed
56
	Minute       int
hujiebin's avatar
hujiebin committed
57 58 59 60
	CreatedTime  time.Time `gorm:"->"`
	UpdatedTime  time.Time `gorm:"->"`
}

hujiebin's avatar
hujiebin committed
61 62 63
// 增加家族经验
// 达到经验值之后升级
// 单进程同步执行,不考虑并发
hujiebin's avatar
hujiebin committed
64
func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.Num, userId mysql.ID, remark string) error {
hujiebin's avatar
hujiebin committed
65 66 67 68 69 70 71 72
	var err error
	defer func() {
		if err != nil {
			txModel.Log.Errorf("IncrGroupPowerExp fail,id:%v,exp:%v,err:%v", groupPowerId, exp, err)
		}
	}()
	// 增加家族经验-天
	date := time.Now().Format("2006-01-02")
hujiebin's avatar
hujiebin committed
73
	gpe := &GroupPowerDayExp{
hujiebin's avatar
hujiebin committed
74 75 76 77
		Date:         date,
		GroupPowerId: groupPowerId,
		Exp:          exp,
	}
hujiebin's avatar
hujiebin committed
78
	if err = txModel.DB().Model(GroupPowerDayExp{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}},
hujiebin's avatar
hujiebin committed
79 80 81 82 83 84 85 86 87
		DoUpdates: clause.Assignments(map[string]interface{}{
			"exp": gorm.Expr("exp + ?", gpe.Exp)})}).Create(gpe).Error; err != nil {
		return err
	}
	// 增加家族经验-总
	gpg := &GroupPowerGrade{
		GroupPowerId: groupPowerId,
		Exp:          exp,
		Grade:        0,
hujiebin's avatar
hujiebin committed
88
		ExpireAt:     time.Time{},
hujiebin's avatar
hujiebin committed
89 90 91 92 93 94
	}
	if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
		DoUpdates: clause.Assignments(map[string]interface{}{
			"exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
		return err
	}
hujiebin's avatar
hujiebin committed
95
	// 当前写后读
hujiebin's avatar
hujiebin committed
96 97 98 99
	latestGrade := new(GroupPowerGrade)
	if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil {
		return err
	}
hujiebin's avatar
hujiebin committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113
	// 记录明细
	detail := &GroupPowerExpDetail{
		GroupPowerId: groupPowerId,
		UserId:       userId,
		Exp:          exp,
		AddReduce:    mysql.ADD,
		BefNum:       latestGrade.Exp - exp,
		AftNum:       latestGrade.Exp,
		Remark:       remark,
	}
	if err = txModel.DB().Model(GroupPowerExpDetail{}).Create(detail).Error; err != nil {
		return err
	}
	// 达到经验值之后升级
hujiebin's avatar
hujiebin committed
114
	for grade := groupPower_e.GroupPowerGradeMax; grade >= groupPower_e.GroupPowerGrade0; grade-- {
hujiebin's avatar
hujiebin committed
115
		if latestGrade.Exp > mysql.Num(groupPower_e.GroupPowerGradeExp[grade]) {
116
			if latestGrade.Grade < grade { // 积分清零后,等级保持一段时间
117 118 119 120 121 122 123
				expireAt := now.EndOfMonth()
				expireAt = utils.AddDate(expireAt, 0, 1) // 等级有效期到下个月月底
				updateAttrs := map[string]interface{}{
					"grade":     grade,
					"expire_at": expireAt,
				}
				if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", latestGrade.GroupPowerId).UpdateColumns(updateAttrs).Error; err != nil {
hujiebin's avatar
hujiebin committed
124 125 126 127 128 129 130 131
					return err
				}
			}
			break
		}
	}
	return nil
}
hujiebin's avatar
hujiebin committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

// 获取势力用户上麦加经验记录
func GetGroupPowerUserOnMicDetails(model *domain.Model, groupPowerId, userId mysql.ID) ([]*GroupPowerOnMicDetail, error) {
	var res []*GroupPowerOnMicDetail
	date := time.Now().Format("2006-01-02")
	if err := model.DB().Model(GroupPowerOnMicDetail{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).Find(&res).Error; err != nil {
		return res, err
	}
	return res, nil
}

// 获取势力用户上麦记录
func GetGroupPowerOnMic(model *domain.Model, groupPowerId, userId mysql.ID) (*GroupPowerOnMic, error) {
	gpom := new(GroupPowerOnMic)
	date := time.Now().Format("2006-01-02")
	if err := model.DB().Model(GroupPowerOnMic{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).First(gpom).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return &GroupPowerOnMic{Date: date, GroupPowerId: groupPowerId, UserId: userId}, nil
		}
		return nil, err
	}
	return gpom, nil
}

const MaxMinuteTimes = 18

// 增加势力上麦经验
hujiebin's avatar
hujiebin committed
159
// 事务操作
hujiebin's avatar
hujiebin committed
160
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
hujiebin's avatar
hujiebin committed
161 162 163 164 165
	return model.Transaction(func(model *domain.Model) error {
		// 获取用户上麦奖励历史
		onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId)
		if err != nil {
			return err
hujiebin's avatar
hujiebin committed
166
		}
hujiebin's avatar
hujiebin committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180
		numDetails := len(onMicDetails)
		if numDetails >= MaxMinuteTimes {
			// 上麦经验贡献值最多1800,1分钟100
			return nil
		}
		onMic, err := GetGroupPowerOnMic(model, groupPowerId, userId)
		if err != nil {
			return err
		}
		onMicSeconds := time.Now().Unix() - joinMicTimestamp
		if onMic.LastCalTs == joinMicTimestamp {
			onMicSeconds = onMicSeconds - int64(numDetails*600) // 扣除之前加过的时间
		}
		var moreDetails []*GroupPowerOnMicDetail
hujiebin's avatar
hujiebin committed
181
		totalMinuteTimes := int((onMic.Seconds + onMicSeconds) / 600) // 今天实际能加经验次数
hujiebin's avatar
hujiebin committed
182 183 184 185
		if totalMinuteTimes >= MaxMinuteTimes {
			totalMinuteTimes = MaxMinuteTimes
		}
		if totalMinuteTimes > numDetails {
hujiebin's avatar
hujiebin committed
186 187
			// 续上上一次的时间,从numDetails开始
			for mt := numDetails + 1; mt <= totalMinuteTimes; mt++ {
hujiebin's avatar
hujiebin committed
188 189 190 191
				moreDetails = append(moreDetails, &GroupPowerOnMicDetail{
					Date:         time.Now().Format("2006-01-02"),
					GroupPowerId: groupPowerId,
					UserId:       userId,
hujiebin's avatar
hujiebin committed
192
					Minute:       mt * 10, // 转换分钟
hujiebin's avatar
hujiebin committed
193 194 195 196 197 198 199 200 201 202 203
				})
			}
		}
		// 有更多麦上10分钟,可以加经验
		if len(moreDetails) > 0 {
			for _, detail := range moreDetails {
				// 添加明细,避免重复计算
				if err := model.DB().Model(GroupPowerOnMicDetail{}).Create(detail).Error; err != nil {
					return err
				}
				// 每10分钟增加100点经验
hujiebin's avatar
hujiebin committed
204
				if err := IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil {
hujiebin's avatar
hujiebin committed
205 206
					return err
				}
hujiebin's avatar
hujiebin committed
207
			}
hujiebin's avatar
hujiebin committed
208 209 210
			// 更新micExp信息
			onMic.Seconds = onMic.Seconds + onMicSeconds
			onMic.LastCalTs = joinMicTimestamp
hujiebin's avatar
hujiebin committed
211 212 213 214 215 216 217 218
			if err := model.DB().Model(GroupPowerOnMic{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}},
				DoUpdates: clause.Assignments(
					map[string]interface{}{
						"seconds":     onMic.Seconds,
						"last_cal_ts": joinMicTimestamp,
					},
				)}).
				Create(onMic).Error; err != nil {
hujiebin's avatar
hujiebin committed
219 220 221
				return err
			}
		}
hujiebin's avatar
hujiebin committed
222 223
		return nil
	})
hujiebin's avatar
hujiebin committed
224
}