Commit c05927f8 authored by hujiebin's avatar hujiebin

feat:搬运了svip的计算逻辑

parent 31f49f15
......@@ -2,28 +2,32 @@ package cp_e
import "git.hilo.cn/hilo-common/resource/mysql"
type CpGrade int
const (
EffectDays = 30 // 30天有效期
)
type CpLevel int
const (
CpGrade0 CpGrade = 0 // 无称号
CpGrade1 CpGrade = 1 // 恋爱CP
CpGrade2 CpGrade = 2 // 甜蜜CP
CpGrade3 CpGrade = 3 // 忠诚CP
CpGrade4 CpGrade = 4 // 炽热CP
CpGrade5 CpGrade = 5 // 荣耀CP
CpLevel0 CpLevel = 0 // 无称号
CpLevel1 CpLevel = 1 // 恋爱CP
CpLevel2 CpLevel = 2 // 甜蜜CP
CpLevel3 CpLevel = 3 // 忠诚CP
CpLevel4 CpLevel = 4 // 炽热CP
CpLevel5 CpLevel = 5 // 荣耀CP
CpGradeMax = CpGrade5
CpLevelMax = CpLevel5
)
var (
// cp等级
CpGradeExp = map[CpGrade]mysql.Num{
CpGrade0: 0,
CpGrade1: 200000,
CpGrade2: 800000,
CpGrade3: 1000000,
CpGrade4: 3000000,
CpGrade5: 10000000,
// cp等级积分
CpLevelPoints = map[CpLevel]mysql.Num{
CpLevel0: 0,
CpLevel1: 200000,
CpLevel2: 800000,
CpLevel3: 1000000,
CpLevel4: 3000000,
CpLevel5: 10000000,
}
// cp特权名称 // todo 翻译
CpPrivilegeNameMsgId = map[CpPrivilege]uint{
......@@ -37,13 +41,13 @@ var (
CpPrivilegeMicEffect: 0,
}
// cp等级icon // todo ui
CpGradeIcon = map[CpGrade]string{
CpGrade0: "icon0.png",
CpGrade1: "icon1.png",
CpGrade2: "icon2.png",
CpGrade3: "icon3.png",
CpGrade4: "icon4.png",
CpGrade5: "icon5.png",
CpLevelIcon = map[CpLevel]string{
CpLevel0: "icon0.png",
CpLevel1: "icon1.png",
CpLevel2: "icon2.png",
CpLevel3: "icon3.png",
CpLevel4: "icon4.png",
CpLevel5: "icon5.png",
}
// cp特权icon // todo ui
CpPrivilegeIcon = map[CpPrivilege]string{
......
......@@ -19,17 +19,17 @@ type CvCpInfo struct {
}
// cp等级
type CvCpGrade struct {
Grade cp_e.CpGrade `json:"grade"` // 等级 0:无称号 1:恋爱CP 2:甜蜜CP 3:忠诚CP 4:炽热CP 5:荣耀CP
Exp uint32 `json:"exp"` // 经验
NextExp uint32 `json:"nextExp,omitempty"` // 下个等级所需经验
RemainExp uint32 `json:"remainExp,omitempty"` // 还需要多少经验值到下一个级别
type CvCpLevel struct {
Level cp_e.CpLevel `json:"level"` // 等级 0:无称号 1:恋爱CP 2:甜蜜CP 3:忠诚CP 4:炽热CP 5:荣耀CP
Points uint32 `json:"points"` // CP
NextPoints uint32 `json:"nextPoints,omitempty"` // 下个等级所需CP
RemainPoints uint32 `json:"remainPoints,omitempty"` // 还需要多少CP值到下一个级别
ExpireAt string `json:"expireAt,omitempty"` // 有效期
}
// 资源等级
type CvResGrade struct {
Grade cp_e.CpGrade `json:"grade"` // 等级
type CvResLevel struct {
Level cp_e.CpLevel `json:"level"` // 等级
Icon string `json:"icon"` // 等级icon图
}
......@@ -44,36 +44,36 @@ type CvPrivilege struct {
// cp空间页
type CvSpace struct {
CpInfo CvCpInfo `json:"cpInfo"` // cp信息
CpGrade CvCpGrade `json:"cpGrade"` // cp等级
ResGradeList []CvResGrade `json:"resGradeList"` // 资源等级列表,无称号/恋爱CP/甜蜜CP/忠诚CP/炽热CP/荣耀CP
CpLevel CvCpLevel `json:"cpLevel"` // cp等级
ResLevelList []CvResLevel `json:"resLevelList"` // 资源等级列表,无称号/恋爱CP/甜蜜CP/忠诚CP/炽热CP/荣耀CP
PrivilegeList []CvPrivilege `json:"privilegeList"` // 等级特权
}
var CvResGradeList = []CvResGrade{
{cp_e.CpGrade0, cp_e.CpGradeIcon[cp_e.CpGrade0]},
{cp_e.CpGrade1, cp_e.CpGradeIcon[cp_e.CpGrade1]},
{cp_e.CpGrade2, cp_e.CpGradeIcon[cp_e.CpGrade2]},
{cp_e.CpGrade3, cp_e.CpGradeIcon[cp_e.CpGrade3]},
{cp_e.CpGrade4, cp_e.CpGradeIcon[cp_e.CpGrade4]},
{cp_e.CpGrade5, cp_e.CpGradeIcon[cp_e.CpGrade5]},
var CvResLevelList = []CvResLevel{
{cp_e.CpLevel0, cp_e.CpLevelIcon[cp_e.CpLevel0]},
{cp_e.CpLevel1, cp_e.CpLevelIcon[cp_e.CpLevel1]},
{cp_e.CpLevel2, cp_e.CpLevelIcon[cp_e.CpLevel2]},
{cp_e.CpLevel3, cp_e.CpLevelIcon[cp_e.CpLevel3]},
{cp_e.CpLevel4, cp_e.CpLevelIcon[cp_e.CpLevel4]},
{cp_e.CpLevel5, cp_e.CpLevelIcon[cp_e.CpLevel5]},
}
var CpGradePrivilegeList = map[cp_e.CpGrade][]CvPrivilege{
cp_e.CpGrade0: {},
cp_e.CpGrade1: {
var CpLevelPrivilegeList = map[cp_e.CpLevel][]CvPrivilege{
cp_e.CpLevel0: {},
cp_e.CpLevel1: {
{cp_e.CpPrivilegeSpace, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeSpace], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeSpace]},
{cp_e.CpPrivilegeBanner, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeBanner], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeBanner]},
{cp_e.CpPrivilegeMedal, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeMedal], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeMedal]},
{cp_e.CpPrivilegeCert, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeCert], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeCert]},
},
cp_e.CpGrade2: {
cp_e.CpLevel2: {
{cp_e.CpPrivilegeSpace, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeSpace], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeSpace]},
{cp_e.CpPrivilegeBanner, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeBanner], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeBanner]},
{cp_e.CpPrivilegeMedal, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeMedal], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeMedal]},
{cp_e.CpPrivilegeCert, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeCert], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeCert]},
{cp_e.CpPrivilegeRoomEffect, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeRoomEffect], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeRoomEffect]},
},
cp_e.CpGrade3: {
cp_e.CpLevel3: {
{cp_e.CpPrivilegeSpace, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeSpace], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeSpace]},
{cp_e.CpPrivilegeBanner, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeBanner], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeBanner]},
{cp_e.CpPrivilegeMedal, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeMedal], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeMedal]},
......@@ -81,7 +81,7 @@ var CpGradePrivilegeList = map[cp_e.CpGrade][]CvPrivilege{
{cp_e.CpPrivilegeRoomEffect, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeRoomEffect], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeRoomEffect]},
{cp_e.CpPrivilegeHeadwear, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeHeadwear], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeHeadwear]},
},
cp_e.CpGrade4: {
cp_e.CpLevel4: {
{cp_e.CpPrivilegeSpace, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeSpace], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeSpace]},
{cp_e.CpPrivilegeBanner, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeBanner], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeBanner]},
{cp_e.CpPrivilegeMedal, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeMedal], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeMedal]},
......@@ -90,7 +90,7 @@ var CpGradePrivilegeList = map[cp_e.CpGrade][]CvPrivilege{
{cp_e.CpPrivilegeHeadwear, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeHeadwear], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeHeadwear]},
{cp_e.CpPrivilegeActiveProfile, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeActiveProfile], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeActiveProfile]},
},
cp_e.CpGrade5: {
cp_e.CpLevel5: {
{cp_e.CpPrivilegeSpace, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeSpace], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeSpace]},
{cp_e.CpPrivilegeBanner, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeBanner], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeBanner]},
{cp_e.CpPrivilegeMedal, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeMedal], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeMedal]},
......@@ -102,9 +102,9 @@ var CpGradePrivilegeList = map[cp_e.CpGrade][]CvPrivilege{
},
}
func CopyCpGradePrivilegeList(grade cp_e.CpGrade, lang string) []CvPrivilege {
privileges := make([]CvPrivilege, len(CpGradePrivilegeList[grade]))
copy(privileges, CpGradePrivilegeList[grade])
func CopyCpLevelPrivilegeList(Level cp_e.CpLevel, lang string) []CvPrivilege {
privileges := make([]CvPrivilege, len(CpLevelPrivilegeList[Level]))
copy(privileges, CpLevelPrivilegeList[Level])
for i, v := range privileges {
privileges[i].Name = GetTranslate(v.NameMsgId, lang)
}
......
package cp_m
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/cp_e"
"hilo-user/myerr"
"time"
)
// cp等级
type CpLevel struct {
mysql.Entity
CpId mysql.ID
SmallUserId mysql.ID
LargeUserId mysql.ID
Points mysql.Num
Level cp_e.CpLevel
ExpireAt time.Time
}
// cp等级积分明细
type CpLevelDetail struct {
mysql.Entity
CpId mysql.ID
SmallUserId mysql.ID
LargeUserId mysql.ID
AddReduce mysql.AddReduce
Num mysql.Num
BefNum mysql.Num
AftNum mysql.Num
Remark string
}
// 添加cp等级积分增减明细
func AddCpLevelDetail(model *domain.Model, detail CpLevelDetail) error {
return model.DB().Create(&detail).Error
}
// 增加cp等级积分
// 送礼1钻石=1点数
// condition
// 1.记录不存在,首充加points计算level增加90天有效期
// 2.记录存在
// 2.1 在有效期内,直接加points后判断新level,升级需要更新有效期
// 2.2 不有效期内,算首充,重置points后判断新level,升级需要更新有效期
func AddCpLevelPoints(model *domain.Model, userId mysql.ID, points mysql.Num) (err error) {
start := time.Now()
defer func() {
model.Log.Infof("AddCpLevelPoints cost:%v,err:%v", time.Now().Sub(start), err)
}()
cpId := mysql.ID(1) // todo get from weijian
small, large := mysql.ID(4552), mysql.ID(7642) // todo get from weijian
var cpLevel CpLevel
var cpLevelDetails []CpLevelDetail
if err := model.DB().Model(CpLevel{}).Where("cp_id = ?", cpId).First(&cpLevel).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return myerr.WrapErr(err)
}
// 明细
cpLevelDetails = append(cpLevelDetails, CpLevelDetail{
CpId: cpId,
SmallUserId: small,
LargeUserId: large,
AddReduce: mysql.ADD,
Num: points,
BefNum: 0,
AftNum: points,
Remark: fmt.Sprintf("send %d gift diamonds", points),
})
// 1.记录不存在,首充加points计算level增加90天有效期
var level cp_e.CpLevel
for l := cp_e.CpLevelMax; l >= cp_e.CpLevel0; l-- {
if cp_e.CpLevelPoints[l] <= points {
level = l
break
}
}
if level > 0 {
points = points - cp_e.CpLevelPoints[level] // 减去用于已用于升级的积分
// 明细
cpLevelDetails = append(cpLevelDetails, CpLevelDetail{
CpId: cpId,
SmallUserId: small,
LargeUserId: large,
AddReduce: mysql.REDUCE,
Num: cp_e.CpLevelPoints[level],
BefNum: cp_e.CpLevelPoints[level] + points,
AftNum: points,
Remark: fmt.Sprintf("Become LEVEL%d", level),
})
}
cpLevel = CpLevel{
CpId: cpId,
SmallUserId: small,
LargeUserId: large,
Points: points,
Level: level,
ExpireAt: time.Now().AddDate(0, 0, cp_e.EffectDays),
}
} else {
// 2.记录存在
// 2.1 在有效期内,直接加points后判断新level,升级需要更新有效期
if cpLevel.ExpireAt.After(time.Now()) {
cpLevel.Points += points
// 明细
cpLevelDetails = append(cpLevelDetails, CpLevelDetail{
CpId: cpId,
SmallUserId: small,
LargeUserId: large,
AddReduce: mysql.ADD,
Num: points,
BefNum: cpLevel.Points - points,
AftNum: cpLevel.Points,
Remark: fmt.Sprintf("send %d gift diamonds", points),
})
oldLevel := cpLevel.Level
levelPoint := cp_e.CpLevelPoints[oldLevel] // 已经用于升级的积分
for level := cp_e.CpLevelMax; level > oldLevel; level-- {
if cp_e.CpLevelPoints[level] <= cpLevel.Points+levelPoint {
cpLevel.Level = level
break
}
}
// 升级
if oldLevel != cpLevel.Level {
// 减去已用于升级的积分
cpLevel.Points = cpLevel.Points - (cp_e.CpLevelPoints[cpLevel.Level] - cp_e.CpLevelPoints[oldLevel])
cpLevel.ExpireAt = time.Now().AddDate(0, 0, cp_e.EffectDays)
// 明细
cpLevelDetails = append(cpLevelDetails, CpLevelDetail{
CpId: cpId,
SmallUserId: small,
LargeUserId: large,
AddReduce: mysql.REDUCE,
Num: cp_e.CpLevelPoints[cpLevel.Level] - cp_e.CpLevelPoints[oldLevel],
BefNum: cpLevel.Points + cp_e.CpLevelPoints[cpLevel.Level] - cp_e.CpLevelPoints[oldLevel],
AftNum: cpLevel.Points,
Remark: fmt.Sprintf("Become LEVEL%d", cpLevel.Level),
})
}
} else {
// 2.2 不有效期内,算首充,重置points后判断新level,更新有效期30天
oldPoints := cpLevel.Points
cpLevel.Points = points
// 明细
cpLevelDetails = append(cpLevelDetails, CpLevelDetail{
CpId: cpId,
SmallUserId: small,
LargeUserId: large,
AddReduce: mysql.ADD,
Num: points,
BefNum: oldPoints,
AftNum: cpLevel.Points,
Remark: fmt.Sprintf("send %d gift diamonds", points),
})
for level := cp_e.CpLevelMax; level >= cp_e.CpLevel0; level-- {
if cp_e.CpLevelPoints[level] <= cpLevel.Points {
cpLevel.Level = level
break
}
}
if cpLevel.Level > 0 {
cpLevel.Points -= cp_e.CpLevelPoints[cpLevel.Level] // 减去已用于升级的积分
// 明细
cpLevelDetails = append(cpLevelDetails, CpLevelDetail{
CpId: cpId,
SmallUserId: small,
LargeUserId: large,
AddReduce: mysql.REDUCE,
Num: cp_e.CpLevelPoints[cpLevel.Level],
BefNum: cpLevel.Points + cp_e.CpLevelPoints[cpLevel.Level],
AftNum: cpLevel.Points,
Remark: fmt.Sprintf("Become SVIP%d", cpLevel.Level),
})
}
cpLevel.ExpireAt = time.Now().AddDate(0, 0, cp_e.EffectDays)
}
}
// 顺序增加明细
for _, detail := range cpLevelDetails {
if err := AddCpLevelDetail(model, detail); err != nil {
return myerr.WrapErr(err)
}
}
return cpLevel.Persistence(model)
}
// 清理过期svip积分
// 降级保级: 积分清零,svip去到大于0的等级,有效期90天
// svip0:积分清零,有效期保持过期
func ClearExpireUserSvipPoints(model *domain.Model) error {
var cpLevels []*CpLevel
// 过期 + (积分 or level) 大于0
if err := model.DB().Model(CpLevel{}).Where("expire_at < ? AND (points > 0 or level > 0) ", time.Now()).Find(&cpLevels).Error; err != nil {
return myerr.WrapErr(err)
}
for _, cpLevel := range cpLevels {
var doubleCheck CpLevel
if err := model.DB().Model(CpLevel{}).Where("id = ?", cpLevel.ID).First(&doubleCheck).Error; err != nil {
model.Log.Errorf("double check fail:%v", err)
continue
}
if doubleCheck.ExpireAt.After(time.Now()) {
continue
}
oldPoints := cpLevel.Points
cpLevel.Level, cpLevel.Points = cp_e.CpLevel0, 0 // 清零
var newLevel cp_e.CpLevel
// 0级不刷新30天有效期
for level := cp_e.CpLevelMax; level > cp_e.CpLevel0; level-- {
if cp_e.CpLevelPoints[level] <= oldPoints {
newLevel = level
break
}
}
// 降级/保级刷新30天有效期
if newLevel > 0 {
cpLevel.Level = newLevel
cpLevel.ExpireAt = time.Now().AddDate(0, 0, cp_e.EffectDays)
// 明细
if err := AddCpLevelDetail(model, CpLevelDetail{
CpId: cpLevel.CpId,
SmallUserId: cpLevel.SmallUserId,
LargeUserId: cpLevel.LargeUserId,
AddReduce: mysql.REDUCE,
Num: cp_e.CpLevelPoints[newLevel],
BefNum: oldPoints,
AftNum: 0,
Remark: fmt.Sprintf("Become LEVEL%d", newLevel),
}); err != nil {
model.Log.Errorf("AddCpLevelDetail fail:%v", err)
}
}
if err := cpLevel.Persistence(model); err != nil {
model.Log.Errorf("cpLevel persistence fail:%v", err)
}
// 明细
if err := AddCpLevelDetail(model, CpLevelDetail{
CpId: cpLevel.CpId,
SmallUserId: cpLevel.SmallUserId,
LargeUserId: cpLevel.LargeUserId,
AddReduce: mysql.SET,
Num: oldPoints - cp_e.CpLevelPoints[newLevel],
BefNum: oldPoints - cp_e.CpLevelPoints[newLevel],
AftNum: 0,
Remark: fmt.Sprintf("Expired clear"),
}); err != nil {
model.Log.Errorf("AddCpLevelDetail fail:%v", err)
}
}
return nil
}
package cp_m
import (
"git.hilo.cn/hilo-common/domain"
"hilo-user/domain/model"
)
func (p *CpLevel) Persistence(m *domain.Model) error {
return model.Persistent(m.DB(), p)
}
......@@ -41,27 +41,27 @@ func CpSpace(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
expireAt := "" // todo
cpGrade := cp_e.CpGrade3 // todo get from db
nextExp := cp_e.CpGradeExp[cp_e.CpGradeMax]
remainExp := mysql.Num(0)
if cpGrade != cp_e.CpGradeMax {
nextExp = cp_e.CpGradeExp[cpGrade+1]
remainExp = nextExp - cp_e.CpGradeExp[cpGrade] // todo get from db
cpLevel := cp_e.CpLevel3 // todo get from db
nextPoints := cp_e.CpLevelPoints[cp_e.CpLevelMax]
remainPoints := mysql.Num(0)
if cpLevel != cp_e.CpLevelMax {
nextPoints = cp_e.CpLevelPoints[cpLevel+1]
remainPoints = nextPoints - cp_e.CpLevelPoints[cpLevel] // todo get from db
}
response := cp_cv.CvSpace{
CpInfo: cp_cv.CvCpInfo{
UserInfo: user_cv.UserToTiny(*userInfo),
CpUserInfo: user_cv.UserToTiny(*cpUserInfo),
},
CpGrade: cp_cv.CvCpGrade{
Grade: cpGrade,
Exp: cp_e.CpGradeExp[cpGrade], // todo get from db
NextExp: nextExp,
RemainExp: remainExp,
CpLevel: cp_cv.CvCpLevel{
Level: cpLevel,
Points: cp_e.CpLevelPoints[cpLevel], // todo get from db
NextPoints: nextPoints,
RemainPoints: remainPoints,
ExpireAt: expireAt,
},
ResGradeList: cp_cv.CvResGradeList,
PrivilegeList: cp_cv.CopyCpGradePrivilegeList(cpGrade, lang),
ResLevelList: cp_cv.CvResLevelList,
PrivilegeList: cp_cv.CopyCpLevelPrivilegeList(cpLevel, lang),
}
resp.ResponseOk(c, response)
return myContext, nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment